From b199a36bd84b32b017ffbb3f9f4c3d56f3325b0b Mon Sep 17 00:00:00 2001 From: Stefan O'Rear Date: Sun, 5 Sep 2010 18:30:44 -0700 Subject: [PATCH] [nrx] Reimplement simple cuts --- lib/Cursor.cs | 29 +++++++++++++++++++++++------ src/CodeGen.pm | 1 + src/Niecza/Actions.pm | 2 +- src/Op.pm | 5 +++-- src/RxOp.pm | 19 ++++++++++--------- test2.pl | 18 +++++++++--------- 6 files changed, 47 insertions(+), 27 deletions(-) diff --git a/lib/Cursor.cs b/lib/Cursor.cs index ae7281c3..151a4d09 100644 --- a/lib/Cursor.cs +++ b/lib/Cursor.cs @@ -23,7 +23,8 @@ public struct State { public XAct xact; } - // invariant: xact of top state is NEVER committed/pruned + // the current State doesn't really have an xact; bt.obj.xact is used to + // hold the parent of what will become bt.next.obj.xact public PSN bt; @@ -37,13 +38,13 @@ public struct State { // cache of orig.Length public int end; - public RxFrame(Cursor csr) { + public RxFrame(string name, Cursor csr) { orig = csr.backing_ca; orig_s = csr.backing; end = orig.Length; bt = new PSN(default(State), null); bt.obj.klasses = new PSN(csr.klass, null); - bt.obj.xact = new XAct("MATCH", csr.xact); + bt.obj.xact = new XAct("RULE " + name, csr.xact); bt.obj.pos = csr.pos; } @@ -68,6 +69,7 @@ public struct State { return th.caller; } else { + bt.obj.xact = bt.obj.xact.next; th.ip = bt.obj.ip; return th; } @@ -75,8 +77,8 @@ public struct State { public void PushBacktrack(string name, int ip) { bt.obj.ip = ip; - bt = new PSN(bt.obj, bt); bt.obj.xact = new XAct(name, bt.obj.xact); + bt = new PSN(bt.obj, bt); } public void CommitAll() { @@ -92,9 +94,9 @@ public struct State { name = "RULE " + name; while (x != null) { x.committed = true; - x = x.next; if (x.tag.Equals(name)) break; + x = x.next; } } @@ -102,9 +104,24 @@ public struct State { XAct x = bt.next.obj.xact; while (x != null) { x.committed = true; - x = x.next; if (x.tag.StartsWith("RULE ")) break; + x = x.next; + } + } + + public void CommitGroup(string open, string close) { + XAct x = bt.next.obj.xact; + int level = 1; + while (x != null) { + x.committed = true; + if (x.tag == open) + level--; + else if (x.tag == close) + level++; + x = x.next; + if (level == 0) + break; } } diff --git a/src/CodeGen.pm b/src/CodeGen.pm index 9a3e6b41..cf1ef0c6 100644 --- a/src/CodeGen.pm +++ b/src/CodeGen.pm @@ -65,6 +65,7 @@ use 5.010; GetQuant => [m => 'Int32'], OpenQuant => [m => 'Void'], CloseQuant => [m => 'Int32'], + CommitGroup => [m => 'Void'], Backtrack => [c => 'Void'], End => [c => 'Void'] }, 'Niecza.FatalException' => diff --git a/src/Niecza/Actions.pm b/src/Niecza/Actions.pm index cd50fbb9..47697430 100644 --- a/src/Niecza/Actions.pm +++ b/src/Niecza/Actions.pm @@ -379,7 +379,7 @@ sub regex_def { my ($cl, $M) = @_; class => 'Regex', type => 'regex', signature => $sig->for_regex, - do => Op::RegexBody->new(rxop => $ast))); + do => Op::RegexBody->new(name => ($name // ''), rxop => $ast))); } sub regex_declarator { my ($cl, $M) = @_; diff --git a/src/Op.pm b/src/Op.pm index f3a86057..730b0669 100644 --- a/src/Op.pm +++ b/src/Op.pm @@ -1014,6 +1014,7 @@ use CgOp; extends 'Op'; has rxop => (isa => 'RxOp', is => 'ro', required => 1); + has name => (isa => 'Str', is => 'ro', default => ''); sub zyg { $_[0]->rxop->opzyg } @@ -1022,8 +1023,8 @@ use CgOp; CgOp::prog( CgOp::setfield('rx', CgOp::callframe, - CgOp::rawnew('RxFrame', CgOp::cast('Cursor', - CgOp::fetch(CgOp::scopedlex('$¢'))))), + CgOp::rawnew('RxFrame', CgOp::clr_string($self->name), + CgOp::cast('Cursor', CgOp::fetch(CgOp::scopedlex('$¢'))))), $self->rxop->code($body), CgOp::rawccall(CgOp::getfield('rx', CgOp::callframe), 'End'), CgOp::rawccall(CgOp::getfield('rx', CgOp::callframe), 'Backtrack'), diff --git a/src/RxOp.pm b/src/RxOp.pm index 050d1182..61570c48 100644 --- a/src/RxOp.pm +++ b/src/RxOp.pm @@ -188,16 +188,17 @@ use CgOp; use Moose; extends 'RxOp'; - sub op { - my ($self, $cn, $cont) = @_; + sub code { + my ($self, $body) = @_; - my $icn = Niecza::Actions->gensym; - $icn, Op::CallSub->new( - invocant => Op::Lexical->new(name => '&_rxcut'), - positionals => [ - Op::Lexical->new(name => $icn), - $self->_close_op($self->zyg->[0]), - $self->_close_k($cn, $cont)]); + my @code; + push @code, CgOp::rxpushb("CUTGRP"); + push @code, $self->zyg->[0]->code($body); + push @code, CgOp::rawcall(CgOp::rxframe, 'CommitGroup', + CgOp::clr_string("CUTGRP"), CgOp::clr_string("ENDCUTGRP")); + push @code, CgOp::rxpushb("ENDCUTGRP"); + + @code; } sub lad { diff --git a/test2.pl b/test2.pl index 4e6fdb7f..4e9e95ef 100644 --- a/test2.pl +++ b/test2.pl @@ -70,14 +70,14 @@ # ok !G3.parse("y"), "capturing subrules work (negative)"; # } # -# { -# ok ("aab" ~~ /a* ab/), "a*ab backtracks"; -# ok !("aab" ~~ /a*: ab/), "a*: ab doesn't"; -# ok ("aab" ~~ /a*! ab/), "a*! ab backtracks"; -# ok !("aab" ~~ /:r a* ab/), "ratcheting a* ab does not"; -# ok !("aab" ~~ /:r a*: ab/), "ratcheting a*: ab does not"; -# ok ("aab" ~~ /:r a*! ab/), "ratcheting a*! ab does"; -# ok !("aab" ~~ token { a* ab }), "a* ab in a token does not"; +{ + ok ("aab" ~~ /a* ab/), "a*ab backtracks"; + ok !("aab" ~~ /a*: ab/), "a*: ab doesn't"; + ok ("aab" ~~ /a*! ab/), "a*! ab backtracks"; + ok !("aab" ~~ /:r a* ab/), "ratcheting a* ab does not"; + ok !("aab" ~~ /:r a*: ab/), "ratcheting a*: ab does not"; + ok ("aab" ~~ /:r a*! ab/), "ratcheting a*! ab does"; + ok !("aab" ~~ token { a* ab }), "a* ab in a token does not"; # # ok ("ab ab" ~~ / ab <.ws> ab /), "ws matches a space"; # ok (q:to/end/ ~~ / ab <.ws> ab /), "ws matches a newline"; @@ -87,7 +87,7 @@ # ok ("ab ab" ~~ / ab <.ws> ab /), "ws matches several spaces"; # ok !("abab" ~~ / ab <.ws> ab /), "ws does not match nothing"; # ok ("ab ab" ~~ rule { ab ab }), "rule gives space"; -# } +} # # { # # doing a more reasonable test will probably require embedded blocks