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 Diff line number Diff line change
Expand Up @@ -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
Expand Down
46 changes: 35 additions & 11 deletions lib/Cursor.cs
Original file line number 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
// 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;
Expand Down Expand Up @@ -211,7 +215,7 @@ public Frame Backtrack(Frame th) {
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);
Expand Down Expand Up @@ -243,6 +247,7 @@ public void PushBacktrack(int ip) {
}

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

Expand All @@ -266,6 +271,13 @@ public void SetPos(int 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) {
Cursor child = match as Cursor;

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

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);
}
Expand All @@ -725,11 +747,11 @@ public Frame End(Frame th) {
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;
Expand Down Expand Up @@ -867,14 +889,15 @@ public Variable GetKey(string str) {
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)
Expand All @@ -889,7 +912,9 @@ public void UnpackCaps(P6any into) {
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;
Expand All @@ -902,7 +927,6 @@ public void UnpackCaps(P6any into) {
}
t.Unshift(it.cap);
}
it = it.prev;
}

if (posr[0].Count() == 0)
Expand Down
13 changes: 13 additions & 0 deletions src/niecza
Original file line number 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 {
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;

Expand Down
20 changes: 20 additions & 0 deletions test2.pl
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,26 @@
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 {
has $!pie;
Expand Down

0 comments on commit ac66b89

Please sign in to comment.