Permalink
Browse files

Implement <( and )>

  • Loading branch information...
1 parent 0a764b6 commit ac66b89858896e5046fc944406705c163dfa9a3d @sorear committed Dec 17, 2011
Showing with 68 additions and 12 deletions.
  1. +0 −1 docs/TODO.S05
  2. +35 −11 lib/Cursor.cs
  3. +13 −0 src/niecza
  4. +20 −0 test2.pl
View
@@ -34,7 +34,6 @@ All line numbers are relative to c4882a67. Also, deliberate discrepencies.)
(1744) No <*...>
(1804) No <~~> DISCUSS
(1843) No <|g> etc
-(1857) No <( or )>
(1893) Missing predefined rules include upper, lower, digit, xdigit, print,
graph, cntrl, punct, alnum, wb, ww, space, blank
(2246) regex :ratchet syntax doesn't work
View
@@ -163,7 +163,11 @@ public sealed class RxFrame: IFreeze {
// when this is set, one value has already been given, so we don't need
// any more Lists
- public bool return_one;
+ public const int RETURN_ONE = 1;
+ // <( and )> have been used; MakeMatch needs to search for the end
+ // tokens
+ public const int USED_ENDS = 2;
+ public byte flags;
// .from in matches
public int from;
@@ -211,7 +215,7 @@ public sealed class RxFrame: IFreeze {
if (st.pos > global.highwater)
global.IncHighwater(st.pos);
if (bt == rootf) {
- if (return_one) {
+ if ((flags & RETURN_ONE) != 0) {
if (Cursor.Trace)
Console.WriteLine("Failing {0}@{1} after no matches",
name, from);
@@ -243,6 +247,7 @@ public sealed class RxFrame: IFreeze {
}
public void PushCapture(string[] cn, Variable cl) {
+ if (cn.Length == 0) return;
st.captures = new CapInfo(st.captures, cn, cl);
}
@@ -266,6 +271,13 @@ public sealed class RxFrame: IFreeze {
st.pos = pos;
}
+ // This is not the most efficient way, but it avoids adding another
+ // field to the backtrack state.
+ public void SetEndpoint(string which) {
+ flags |= USED_ENDS;
+ PushCapture(new string[] { null, which }, Builtins.MakeInt(st.pos));
+ }
+
public void IncorporateChild(string[] names, P6any match) {
Cursor child = match as Cursor;
@@ -701,10 +713,20 @@ public sealed class RxFrame: IFreeze {
Cursor _matchObj;
public Frame MakeMatch(Frame th) {
+ int use_from = from;
+ int use_to = st.pos;
+ if ((flags & USED_ENDS) != 0) {
+ for (CapInfo c = st.captures; c != null; c = c.prev) {
+ if (c.names[0] == null && c.names[1] == "from")
+ use_from = Kernel.UnboxAny<int>(c.cap.Fetch());
+ if (c.names[0] == null && c.names[1] == "to")
+ use_to = Kernel.UnboxAny<int>(c.cap.Fetch());
+ }
+ }
if (Cursor.Trace)
- Console.WriteLine("Matching {0} from {1} to {2}",
- name, from, st.pos);
- _matchObj = new Cursor(global, st.ns.klass, from, st.pos,
+ Console.WriteLine("Matching {0} from {1} to {2} (really {3}-{4})",
+ name, use_from, use_to, from, st.pos);
+ _matchObj = new Cursor(global, st.ns.klass, use_from, use_to,
st.captures, ast, name);
return global.CallAction(th, name, _matchObj);
}
@@ -725,11 +747,11 @@ public sealed class RxFrame: IFreeze {
public Frame EndWith(Frame th, Cursor m) {
if (st.pos > global.highwater)
global.IncHighwater(st.pos);
- if (return_one) {
+ if ((flags & RETURN_ONE) != 0) {
return Kernel.Take(th, Kernel.NewROScalar(m));
} else {
th.MarkSharedChain();
- return_one = true;
+ flags |= RETURN_ONE;
VarDeque ks = new VarDeque();
ks.Push(Kernel.NewROScalar(m));
th.coro_return = th;
@@ -867,14 +889,15 @@ public Cursor(P6any proto, string text, P6any actions)
CapInfo it = captures;
VarDeque caps = new VarDeque();
- while (it != null) {
+ for (; it != null; it = it.prev) {
+ if (it.names[0] == null)
+ continue; // special node
foreach (string cn in it.names) {
if (cn == str) {
caps.Unshift(it.cap);
break;
}
}
- it = it.prev;
}
if (str == "0" && caps.Count() == 0)
@@ -889,7 +912,9 @@ public Cursor(P6any proto, string text, P6any actions)
Dictionary<string,VarDeque> namr = new Dictionary<string,VarDeque>();
CapInfo it = captures;
- while (it != null) {
+ for (; it != null; it = it.prev) {
+ if (it.names[0] == null)
+ continue; // special node
foreach (string name in it.names) {
int nami;
VarDeque t;
@@ -902,7 +927,6 @@ public Cursor(P6any proto, string text, P6any actions)
}
t.Unshift(it.cap);
}
- it = it.prev;
}
if (posr[0].Count() == 0)
View
@@ -39,7 +39,20 @@ augment class RxOp::ProtoRedis {
}
}
+class RxOp::Endpoint is RxOp {
+ has Str $.type = die "Endpoint.type required";
+
+ method code($) { CgOp.rxcall('SetEndpoint', CgOp.str($!type)); }
+ method lad() { [ 'Null' ] }
+}
+
augment class NieczaActions {
+method metachar:sym« <( » ($/) {
+ make ::RxOp::Endpoint.new(|node($/), :type<from>)
+}
+method metachar:sym« )> » ($/) {
+ make ::RxOp::Endpoint.new(|node($/), :type<to>)
+}
method regex_def($/) {
my $ast = $<regex_block>.ast;
View
@@ -77,6 +77,26 @@
}
{
+ is ("fffoxxx" ~~ / f <( . )> x /), "o", '<( )> works basically';
+ is $/.from, 3, '$/.from set correctly';
+ is $/.to, 4, '$/.to set correctly';
+
+ my $var = 'one $16 two $9 three';
+ $var ~~ s:g[\$ <( \d+ )>] *= 2;
+ is $var, 'one $32 two $18 three', 's:g <( example from S05';
+
+ # because of anchoring behavior, leading context behaves differently
+ is "abcdef".comb(/<(.)>../).join('|'), 'a|b|c|d',
+ '.comb with overlapping context regions';
+ $var = 'abcdef';
+ $var ~~ s:g[<(.)>....] = $/.uc;
+ is $var, 'ABcdef', 's:g with overlapping context';
+
+ is ("foo" ~~ / f <( .. /), "oo", '<( does not need to be paired';
+ is ("foo" ~~ / f )> .. /), "f", ')> does not need to be paired';
+}
+
+{
my class Bt {
has $!pie;
method get_pie() { $!pie }

0 comments on commit ac66b89

Please sign in to comment.