diff --git a/lib/Cursor.cs b/lib/Cursor.cs index bb244dde..e8e32ad6 100644 --- a/lib/Cursor.cs +++ b/lib/Cursor.cs @@ -6,11 +6,14 @@ // stuff that should 'N'est, like subrules do public sealed class NState { public NState next; + public string name; + public Choice cut_to; public int quant; public DynMetaObject klass; - public NState(NState proto) { - next = proto; if (proto != null) klass = proto.klass; + public NState(Choice cut_to, string name, NState proto) { + next = proto; this.cut_to = cut_to; this.name = name; + if (proto != null) klass = proto.klass; } } @@ -39,31 +42,19 @@ public sealed class Choice { // the current Choice doesn't really have any of these fields, which are // used for backtrack control public int ip; - public string tag; - public bool committed; public void Commit() { // we aren't going to backtrack here, so we can't use this. // help out the GC st.subrule_iter = null; - committed = true; + ip = (ip < 0) ? ip : (-ip-1); } - public Choice(Choice prev, string tag, int ip, State st) { - this.tag = tag; + public Choice(Choice prev, int ip, State st) { this.ip = ip; this.st = st; this.prev = prev; } - - public void Dump(string st) { - string ac = st; - for (Choice x = this; x != null; x = x.prev) { - ac += x.committed ? " + " : " - "; - ac += x.tag; - } - Console.WriteLine(ac); - } } // extends Frame for a time/space tradeoff @@ -93,8 +84,8 @@ public sealed class RxFrame { orig = csr.backing_ca; orig_s = csr.backing; end = orig.Length; - rootf = bt = new Choice(csr.xact, "RULE " + name, -1, default(State)); - st.ns = new NState(csr.nstate); + rootf = bt = csr.xact; + st.ns = new NState(rootf, "RULE " + name, csr.nstate); st.ns.klass = csr.klass; st.pos = csr.pos; from = csr.pos; @@ -102,7 +93,7 @@ public sealed class RxFrame { public Frame Backtrack(Frame th) { // throw away cut or mark-only frames - while (bt != rootf && (bt.committed || bt.ip < 0)) + while (bt != rootf && (bt.ip < 0)) bt = bt.prev; if (bt == rootf) { if (return_one) { @@ -124,8 +115,8 @@ public sealed class RxFrame { } } - public void PushBacktrack(string name, int ip) { - bt = new Choice(bt, name, ip, st); + public void PushBacktrack(int ip) { + bt = new Choice(bt, ip, st); } public void PushCapture(string[] cn, Cursor cl) { @@ -144,21 +135,18 @@ public sealed class RxFrame { st.pos = pos; } - public void CommitAll() { - Choice x = bt; - while (x != null) { - x.Commit(); - x = x.prev; - } + public void PushCutGroup(string tag) { + st.ns = new NState(bt, tag, st.ns); } - public void CommitSpecificRule(string name) { + public void PopCutGroup() { + st.ns = st.ns.next; + } + + public void CommitAll() { Choice x = bt; - name = "RULE " + name; while (x != null) { x.Commit(); - if (x.tag.Equals(name)) - break; x = x.prev; } } @@ -171,27 +159,18 @@ public sealed class RxFrame { } } - public void CommitGroup(string open, string close) { - Choice x = bt; - if (Cursor.Trace) - x.Dump("committing " + open + "," + close); - int level = 1; - while (x != null) { - x.Commit(); - if (x.tag == open) - level--; - else if (x.tag == close) - level++; - x = x.prev; - if (level == 0) - break; + public void CommitGroup(string id) { + NState nsi = st.ns; + while (nsi != null && !nsi.name.Equals(id)) + nsi = nsi.next; + Choice to = (nsi != null) ? nsi.cut_to : null; + Choice it = bt; + while (it != to) { + it.Commit(); + it = it.prev; } } - public bool IsTopCut() { - return bt.committed; - } - public bool Exact(string str) { if (st.pos + str.Length > end) return false; @@ -224,15 +203,15 @@ public sealed class RxFrame { } public void LTMPushAlts(Lexer lx, int[] addrs) { - PushBacktrack("LTM", -1); + PushCutGroup("LTM"); int[] cases = lx.Run(orig_s, st.pos); for (int i = cases.Length - 1; i >= 0; i--) { - PushBacktrack("LTMALT", addrs[cases[i]]); + PushBacktrack(addrs[cases[i]]); } } public void OpenQuant() { - st.ns = new NState(st.ns); + st.ns = new NState(bt, "QUANT", st.ns); } public int CloseQuant() { diff --git a/src/CgOp.pm b/src/CgOp.pm index 211c156a..f2a849f0 100644 --- a/src/CgOp.pm +++ b/src/CgOp.pm @@ -554,6 +554,9 @@ use warnings; } sub rxframe { getfield('rx', callframe) } + sub rxcall { rawcall(rxframe, @_) } + sub pushcut { rxcall('PushCutGroup', clr_string($_[0])) } + sub popcut { rxcall('PopCutGroup') } sub letvar { $_[1] ? diff --git a/src/CodeGen.pm b/src/CodeGen.pm index 46faccfe..45a7340d 100644 --- a/src/CodeGen.pm +++ b/src/CodeGen.pm @@ -64,7 +64,6 @@ use 5.010; 'RxFrame' => { Exact => [m => 'Boolean'], Exact1 => [m => 'Boolean'], - IsTopCut => [m => 'Boolean'], IncQuant => [m => 'Void'], GetQuant => [m => 'Int32'], OpenQuant => [m => 'Void'], @@ -72,7 +71,8 @@ use 5.010; CommitGroup => [m => 'Void'], CommitRule => [m => 'Void'], CommitAll => [m => 'Void'], - CommitSpecificRule => [m => 'Void'], + PushCutGroup => [m => 'Void'], + PopCutGroup => [m => 'Void'], GetCursorList=> [m => 'Variable'], SetCursorList=> [m => 'Void'], LTMPushAlts => [m => 'Void'], @@ -692,8 +692,7 @@ use 5.010; sub rxpushb { my ($self, $tag, $label) = @_; - push @{ $self->buffer }, " th.rx.PushBacktrack(" . qm($tag) . - ", " . ($label ? "\@\@L$label" : "-1") . ");\n"; + push @{ $self->buffer }, " th.rx.PushBacktrack(\@\@L$label);\n"; } sub return { diff --git a/src/RxOp.pm b/src/RxOp.pm index e413a790..4ef03345 100644 --- a/src/RxOp.pm +++ b/src/RxOp.pm @@ -172,14 +172,12 @@ use CgOp; my $n = @{ $self->zyg }; for (my $i = 0; $i < $n; $i++) { - push @code, CgOp::rxpushb("SEQALT", - ($i == $n - 1) ? undef : $ends[$i]); + push @code, CgOp::rxpushb("SEQALT", $ends[$i]) unless $i == $n - 1; push @code, $self->zyg->[$i]->code($body); push @code, CgOp::goto($ends[$n-1]) unless $i == $n-1; push @code, CgOp::label($ends[$i]); } - push @code, CgOp::rxpushb("ENDSEQALT"); @code; } @@ -198,9 +196,9 @@ use CgOp; sub code { my ($self, $body) = @_; my @code; - push @code, CgOp::rxpushb("BRACK"); + push @code, CgOp::pushcut("BRACK"); push @code, $self->zyg->[0]->code($body); - push @code, CgOp::rxpushb("ENDBRACK"); + push @code, CgOp::popcut(); @code; } @@ -222,11 +220,11 @@ use CgOp; my ($self, $body) = @_; my @code; - push @code, CgOp::rxpushb("CUTGRP"); + push @code, CgOp::pushcut("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"); + CgOp::clr_string("CUTGRP")); + push @code, CgOp::popcut(); @code; } @@ -248,22 +246,8 @@ use CgOp; sub code { my ($self, $body) = @_; - my $fail = $self->label; - my $pass = $self->label; - my @code; - push @code, CgOp::rxpushb("CUTGRP", $pass); - push @code, CgOp::rxpushb("CUTGRP", $fail); - 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::goto('backtrack'); - push @code, CgOp::label($fail); - push @code, CgOp::rawcall(CgOp::rxframe, 'CommitGroup', - CgOp::clr_string("CUTGRP"), CgOp::clr_string("ENDCUTGRP")); - push @code, CgOp::goto('backtrack'); - push @code, CgOp::label($pass); - - @code; + RxOp::NotBefore->new(zyg => [RxOp::NotBefore->new(zyg => $self->zyg)]) + ->code($body); } sub lad { @@ -285,12 +269,13 @@ use CgOp; my $pass = $self->label; my @code; + push @code, CgOp::pushcut("CUTGRP"); push @code, CgOp::rxpushb("CUTGRP", $pass); 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::rxcall('CommitGroup', CgOp::clr_string("CUTGRP")); push @code, CgOp::goto('backtrack'); push @code, CgOp::label($pass); + push @code, CgOp::popcut; @code; } @@ -344,17 +329,16 @@ use CgOp; my $namesf = CgOp::const(CgOp::rawnewarr('String', map { CgOp::clr_string($_) } @{ $self->captures })); - my $callf = CgOp::methodcall(CgOp::newscalar(CgOp::rawcall( - CgOp::rxframe, "MakeCursor")), $self->name); + my $callf = CgOp::methodcall(CgOp::newscalar( + CgOp::rxcall("MakeCursor")), $self->name); my @pushcapf = (@{ $self->captures } == 0) ? () : ( - CgOp::rawcall(CgOp::rxframe, "PushCapture", - $namesf, CgOp::cast('Cursor', CgOp::letvar("k")))); + CgOp::rxcall("PushCapture", $namesf, + CgOp::cast('Cursor', CgOp::letvar("k")))); my $updatef = CgOp::prog( CgOp::ncgoto('backtrack', CgOp::rawcall(CgOp::letvar("k"), 'IsDefined')), @pushcapf, - CgOp::rawcall(CgOp::rxframe, "SetPos", - CgOp::getfield("pos", CgOp::cast("Cursor", + CgOp::rxcall("SetPos", CgOp::getfield("pos", CgOp::cast("Cursor", CgOp::letvar("k"))))); my @code; @@ -365,19 +349,18 @@ use CgOp; CgOp::fetch($callf))), $updatef); } else { - push @code, CgOp::rawcall(CgOp::rxframe, "SetCursorList", $callf); + push @code, CgOp::rxcall("SetCursorList", $callf); push @code, CgOp::goto($sk); push @code, CgOp::label($bt); - push @code, CgOp::sink(CgOp::methodcall(CgOp::rawcall(CgOp::rxframe, + push @code, CgOp::sink(CgOp::methodcall(CgOp::rxcall( "GetCursorList"), "shift")); push @code, CgOp::label($sk); push @code, CgOp::letn( "k", CgOp::fetch(CgOp::rawsccall('Kernel.GetFirst:c,Variable', - CgOp::fetch(CgOp::rawcall(CgOp::rxframe, "GetCursorList")))), + CgOp::fetch(CgOp::rxcall("GetCursorList")))), $updatef); push @code, CgOp::rxpushb("SUBRULE", $bt); - push @code, CgOp::rawcall(CgOp::rxframe, "SetCursorList", - CgOp::null("Variable")); + push @code, CgOp::rxcall("SetCursorList", CgOp::null("Variable")); } @code; @@ -423,8 +406,7 @@ use CgOp; sub code { my ($self, $body) = @_; - CgOp::rawcall(CgOp::rxframe, 'CommitGroup', - CgOp::clr_string("LTM"), CgOp::clr_string("ENDLTM")); + CgOp::rxcall('CommitGroup', CgOp::clr_string("LTM")) } sub lad { @@ -443,7 +425,7 @@ use CgOp; sub code { my ($self, $body) = @_; - CgOp::rawcall(CgOp::rxframe, 'CommitRule'); + CgOp::rxcall('CommitRule'); } sub lad { @@ -480,7 +462,7 @@ use CgOp; my $end = $self->label; my @code; - push @code, CgOp::rawcall(CgOp::rxframe, "LTMPushAlts", + push @code, CgOp::rxcall("LTMPushAlts", CgOp::rawscall('Lexer.GetLexer', CgOp::rawcall(CgOp::rxframe, 'MakeCursor'), CgOp::const(RxOp::lad2cgop($self->lads)), @@ -493,7 +475,7 @@ use CgOp; push @code, CgOp::goto($end) unless $i == @ls - 1; } push @code, CgOp::label($end); - push @code, CgOp::rxpushb('ENDLTM'); + push @code, CgOp::popcut; @code; } @@ -517,7 +499,7 @@ use CgOp; sub code { my ($self, $body) = @_; CgOp::subcall(CgOp::fetch($self->block->cgop($body)), - CgOp::newscalar(CgOp::rawcall(CgOp::rxframe, "MakeCursor"))); + CgOp::newscalar(CgOp::rxcall("MakeCursor"))); } sub lad { @@ -547,14 +529,15 @@ use CgOp; "i", CgOp::int(0), "ks", CgOp::null('Variable'), "k", CgOp::null('IP6'), + CgOp::pushcut('LTM'), CgOp::label('nextfn'), CgOp::cgoto('backtrack', CgOp::compare('>=', CgOp::letvar("i"), CgOp::getfield("Length", CgOp::letvar("fns")))), CgOp::rxpushb('LTM', 'nextfn'), CgOp::letvar("ks", CgOp::subcall(CgOp::getindex(CgOp::letvar("i"), - CgOp::letvar("fns")), CgOp::newscalar(CgOp::rawcall( - CgOp::rxframe, 'MakeCursor')))), + CgOp::letvar("fns")), CgOp::newscalar(CgOp::rxcall( + 'MakeCursor')))), CgOp::letvar("i", CgOp::arith('+', CgOp::letvar("i"), CgOp::int(1))), CgOp::letvar("k", CgOp::fetch(CgOp::rawsccall('Kernel.GetFirst:c,Variable', CgOp::fetch(CgOp::letvar("ks"))))),