Skip to content

Commit

Permalink
Implement <( and )>
Browse files Browse the repository at this point in the history
  • Loading branch information
sorear committed Dec 17, 2011
1 parent 0a764b6 commit ac66b89
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 12 deletions.
1 change: 0 additions & 1 deletion docs/TODO.S05
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ All line numbers are relative to c4882a67. Also, deliberate discrepencies.)
(1744) No <*...> (1744) No <*...>
(1804) No <~~> DISCUSS (1804) No <~~> DISCUSS
(1843) No <|g> etc (1843) No <|g> etc
(1857) No <( or )>
(1893) Missing predefined rules include upper, lower, digit, xdigit, print, (1893) Missing predefined rules include upper, lower, digit, xdigit, print,
graph, cntrl, punct, alnum, wb, ww, space, blank graph, cntrl, punct, alnum, wb, ww, space, blank
(2246) regex :ratchet syntax doesn't work (2246) regex :ratchet syntax doesn't work
Expand Down
46 changes: 35 additions & 11 deletions lib/Cursor.cs
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -163,7 +163,11 @@ public sealed class RxFrame: IFreeze {


// when this is set, one value has already been given, so we don't need // when this is set, one value has already been given, so we don't need
// any more Lists // 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 // .from in matches
public int from; public int from;
Expand Down Expand Up @@ -211,7 +215,7 @@ public Frame Backtrack(Frame th) {
if (st.pos > global.highwater) if (st.pos > global.highwater)
global.IncHighwater(st.pos); global.IncHighwater(st.pos);
if (bt == rootf) { if (bt == rootf) {
if (return_one) { if ((flags & RETURN_ONE) != 0) {
if (Cursor.Trace) if (Cursor.Trace)
Console.WriteLine("Failing {0}@{1} after no matches", Console.WriteLine("Failing {0}@{1} after no matches",
name, from); name, from);
Expand Down Expand Up @@ -243,6 +247,7 @@ public void PushBacktrack(int ip) {
} }


public void PushCapture(string[] cn, Variable cl) { public void PushCapture(string[] cn, Variable cl) {
if (cn.Length == 0) return;
st.captures = new CapInfo(st.captures, cn, cl); st.captures = new CapInfo(st.captures, cn, cl);
} }


Expand All @@ -266,6 +271,13 @@ public void SetPos(int pos) {
st.pos = pos; 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) { public void IncorporateChild(string[] names, P6any match) {
Cursor child = match as Cursor; Cursor child = match as Cursor;


Expand Down Expand Up @@ -701,10 +713,20 @@ public Cursor MakeCursor() {


Cursor _matchObj; Cursor _matchObj;
public Frame MakeMatch(Frame th) { 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) if (Cursor.Trace)
Console.WriteLine("Matching {0} from {1} to {2}", Console.WriteLine("Matching {0} from {1} to {2} (really {3}-{4})",
name, from, st.pos); name, use_from, use_to, from, st.pos);
_matchObj = new Cursor(global, st.ns.klass, from, st.pos, _matchObj = new Cursor(global, st.ns.klass, use_from, use_to,
st.captures, ast, name); st.captures, ast, name);
return global.CallAction(th, name, _matchObj); return global.CallAction(th, name, _matchObj);
} }
Expand All @@ -725,11 +747,11 @@ public Frame End(Frame th) {
public Frame EndWith(Frame th, Cursor m) { public Frame EndWith(Frame th, Cursor m) {
if (st.pos > global.highwater) if (st.pos > global.highwater)
global.IncHighwater(st.pos); global.IncHighwater(st.pos);
if (return_one) { if ((flags & RETURN_ONE) != 0) {
return Kernel.Take(th, Kernel.NewROScalar(m)); return Kernel.Take(th, Kernel.NewROScalar(m));
} else { } else {
th.MarkSharedChain(); th.MarkSharedChain();
return_one = true; flags |= RETURN_ONE;
VarDeque ks = new VarDeque(); VarDeque ks = new VarDeque();
ks.Push(Kernel.NewROScalar(m)); ks.Push(Kernel.NewROScalar(m));
th.coro_return = th; th.coro_return = th;
Expand Down Expand Up @@ -867,14 +889,15 @@ public Variable GetKey(string str) {
CapInfo it = captures; CapInfo it = captures;
VarDeque caps = new VarDeque(); 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) { foreach (string cn in it.names) {
if (cn == str) { if (cn == str) {
caps.Unshift(it.cap); caps.Unshift(it.cap);
break; break;
} }
} }
it = it.prev;
} }


if (str == "0" && caps.Count() == 0) if (str == "0" && caps.Count() == 0)
Expand All @@ -889,7 +912,9 @@ public void UnpackCaps(P6any into) {
Dictionary<string,VarDeque> namr = new Dictionary<string,VarDeque>(); Dictionary<string,VarDeque> namr = new Dictionary<string,VarDeque>();
CapInfo it = captures; 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) { foreach (string name in it.names) {
int nami; int nami;
VarDeque t; VarDeque t;
Expand All @@ -902,7 +927,6 @@ public void UnpackCaps(P6any into) {
} }
t.Unshift(it.cap); t.Unshift(it.cap);
} }
it = it.prev;
} }


if (posr[0].Count() == 0) if (posr[0].Count() == 0)
Expand Down
13 changes: 13 additions & 0 deletions src/niecza
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -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 { 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($/) { method regex_def($/) {
my $ast = $<regex_block>.ast; my $ast = $<regex_block>.ast;


Expand Down
20 changes: 20 additions & 0 deletions test2.pl
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -76,6 +76,26 @@
is G.parse("ceeed")[0], 'ceeed', 'LTM works into dispatch nodes'; is G.parse("ceeed")[0], 'ceeed', 'LTM works into dispatch nodes';
} }


{
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 { my class Bt {
has $!pie; has $!pie;
Expand Down

0 comments on commit ac66b89

Please sign in to comment.