Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[nrx] Implement subrule calls
  • Loading branch information
sorear committed Sep 6, 2010
1 parent 705c3d8 commit 6d0d084
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 122 deletions.
16 changes: 15 additions & 1 deletion lib/Cursor.cs
Expand Up @@ -15,7 +15,8 @@ public sealed class PSN<X> {

public struct State {
public PSN<int> reps;
public PSN<IP6> captures;
public PSN<Variable> captures;
public PSN<string[]> capnames;
public PSN<DynMetaObject> klasses;

public int pos;
Expand Down Expand Up @@ -81,6 +82,19 @@ public struct State {
bt = new PSN<State>(bt.obj, bt);
}

public void PushCursorList(string[] cn, Variable cl) {
bt.obj.capnames = new PSN<string[]>(cn, bt.obj.capnames);
bt.obj.captures = new PSN<Variable>(cl, bt.obj.captures);
}

public Variable GetCursorList() {
return bt.obj.captures.obj;
}

public void SetPos(int pos) {
bt.obj.pos = pos;
}

public void CommitAll() {
XAct x = bt.next.obj.xact;
while (x != null) {
Expand Down
14 changes: 14 additions & 0 deletions lib/SAFE.setting
Expand Up @@ -564,6 +564,7 @@ my class List is Cool {
"items", LLArray.new(), "rest", LLArray.new(self.iterator)));
@y;
}
method list() { my @y := self; @y }
method clone() {
self.RAWCREATE("flat", $!flat, "items", $!items.clone, "rest",
Expand Down Expand Up @@ -929,6 +930,19 @@ my class Enum is Cool {
}
}
PRE-INIT {
Q:CgOp {
(prog
(rawsset RxFrame.EMPTYP (@ {EMPTY}))
(rawsset RxFrame.ListMO (getfield klass (cast DynObject (@ {List}))))
(rawsset RxFrame.LLArrayMO (getfield klass
(cast DynObject (@ {LLArray}))))
(rawsset RxFrame.GatherIteratorMO (getfield klass
(cast DynObject (@ {GatherIterator}))))
(null Variable))
}
}
my class Pair is Enum {
}
Expand Down
4 changes: 4 additions & 0 deletions src/CodeGen.pm
Expand Up @@ -66,6 +66,10 @@ use 5.010;
OpenQuant => [m => 'Void'],
CloseQuant => [m => 'Int32'],
CommitGroup => [m => 'Void'],
GetCursorList => [m => 'Variable'],
PushCursorList => [m => 'Void'],
MakeCursor => [m => 'Cursor'],
SetPos => [m => 'Void'],
Backtrack => [c => 'Void'],
End => [c => 'Void'] },
'Niecza.FatalException' =>
Expand Down
35 changes: 18 additions & 17 deletions src/Niecza/Actions.pm
Expand Up @@ -586,18 +586,19 @@ sub metachar__S_Double_Double { my ($cl, $M) = @_;
}

sub rxcapturize { my ($cl, $name, $rxop) = @_;
if (!$rxop->isa('RxOp::Capture')) {
# $<foo>=[ ] or ( ) or <foo>
return RxOp::Capture->new(names => [$name], zyg => [$rxop]);
if (!$rxop->isa('RxOp::Subrule')) {
die '$<foo> = [bar] NYI';
}

my @extra = map { $_ => $rxop->$_ } qw/zyg arglist name/;

# $<foo>=(...)
if (@{ $rxop->names } == 1 && !defined($rxop->names->[0])) {
return RxOp::Capture->new(names => [$name], zyg => $rxop->zyg);
if (@{ $rxop->captures } == 1 && !defined($rxop->captures->[0])) {
return RxOp::Subrule->new(captures => [$name], @extra);
}

return RxOp::Capture->new(names => [ $name, @{ $rxop->names } ],
zyg => $rxop->zyg);
return RxOp::Subrule->new(captures => [ $name, @{ $rxop->captures } ],
@extra);
}

sub do_cclass { my ($cl, $M) = @_;
Expand Down Expand Up @@ -627,12 +628,14 @@ sub decapturize { my ($cl, $M) = @_;
$M->sorry("Binding to a method doesn't work like that");
return;
}
if (!$M->{assertion}{_ast}->isa('RxOp::Capture')) {
if (!$M->{assertion}{_ast}->isa('RxOp::Subrule')) {
$M->sorry("Internal error in assertion:method parse");
return;
}
RxOp::Capture->new(names => [],
zyg => $M->{assertion}{_ast}->zyg);
RxOp::Subrule->new(captures => [],
zyg => $M->{assertion}{_ast}->zyg,
arglist => $M->{assertion}{_ast}->arglist,
name => $M->{assertion}{_ast}->name);
}

sub cclass_elem {}
Expand All @@ -645,14 +648,12 @@ sub assertion__S_name { my ($cl, $M) = @_;
if ($M->{assertion}[0]) {
$M->{_ast} = $M->{assertion}[0]{_ast};
} else {
my $args = ($M->{arglist}[0] ? $M->{arglist}[0]{_ast} :
$M->{nibbler}[0] ? [$M->{nibbler}[0]{_ast}] : []);
if ($name eq 'before') {
$M->{_ast} = RxOp::Before->new(zyg => $args);
} elsif ($name eq 'after') {
$M->{_ast} = RxOp::After->new(zyg => $args);
if ($M->{nibbler}[0]) {
my $args = [$M->{nibbler}[0]{_ast}];
$M->{_ast} = RxOp::Subrule->new(zyg => $args, name => $name);
} else {
$M->{_ast} = RxOp::CallMethod->new(arglist => $args, name => $name);
my $args = ($M->{arglist}[0] ? $M->{arglist}[0]{_ast} : []);
$M->{_ast} = RxOp::Subrule->new(arglist => $args, name => $name);
}
}
$M->{_ast} = $cl->rxcapturize($name, $M->{_ast});
Expand Down
97 changes: 25 additions & 72 deletions src/RxOp.pm
Expand Up @@ -268,70 +268,37 @@ use CgOp;
}

{
package RxOp::Capture;
package RxOp::Subrule;
use Moose;
extends 'RxOp';

has names => (isa => 'ArrayRef[Maybe[Str]]', is => 'ro', required => 1);
has name => (isa => 'Str', is => 'ro', required => 1);
has captures => (isa => 'ArrayRef[Maybe[Str]]', is => 'ro', default => sub { [] });
has arglist => (isa => 'ArrayRef[Op]', is => 'ro');

sub op {
my ($self, $cn, $cont) = @_;
my $icn = Niecza::Actions->gensym;
my @n = @{ $self->names };
for (@n) {
$::parennum = $_ if defined($_) && $_ =~ /^[0-9]+$/;
$_ = $::parennum++ if !defined($_);
}
$icn, Op::CallSub->new(
invocant => Op::Lexical->new(name => '&_rxbind'),
positionals => [
Op::Lexical->new(name => $icn),
Op::CallSub->new(
invocant => Op::Lexical->new(name => '&infix:<,>'),
positionals => [
map { Op::StringLiteral->new(text => $_) }
@{ $self->names }
]),
$self->_close_op($self->zyg->[0]),
$self->_close_k($cn, $cont)]);
}

sub lad {
my ($self) = @_;
$self->zyg->[0]->lad;
}

__PACKAGE__->meta->make_immutable;
no Moose;
}

{
package RxOp::CallMethod;
use Moose;
extends 'RxOp';

has name => (isa => 'Str', is => 'ro', required => 1);
sub code {
my ($self, $body) = @_;
my $bt = $self->label;
my $sk = $self->label;

sub op {
my ($self, $cn, $cont) = @_;
my $icn = Niecza::Actions->gensym;
if ($self->name eq 'sym') {
# Should probably be a separate pass (before rx optimizer)
return $icn, Op::CallSub->new(
invocant => Op::Lexical->new(name => '&_rxstr'),
positionals => [
Op::Lexical->new(name => $icn),
Op::StringLiteral->new(text => $::symtext),
$self->_close_k($cn, $cont)
]);
}
my @code;
push @code, CgOp::rawcall(CgOp::rxframe, "PushCursorList",
CgOp::rawnewarr('String', map { CgOp::clr_string($_) } @{ $self->captures }),
CgOp::methodcall(CgOp::methodcall(CgOp::methodcall(
CgOp::newscalar(CgOp::rawcall(CgOp::rxframe, "MakeCursor")),
$self->name), "list"), "clone"));
push @code, CgOp::goto($sk);
push @code, CgOp::label($bt);
push @code, CgOp::methodcall(CgOp::rawcall(CgOp::rxframe,
"GetCursorList"), "shift");
push @code, CgOp::label($sk);
push @code, CgOp::letn("k", CgOp::rawcall(CgOp::rxframe, "GetCursorList"),
CgOp::ternary(CgOp::unbox('Boolean', CgOp::fetch(CgOp::methodcall(CgOp::letvar("k"), "!fill", CgOp::box('Num', CgOp::double(1))))),
CgOp::rawcall(CgOp::rxframe, "SetPos", CgOp::getfield("pos", CgOp::cast("Cursor", CgOp::fetch(CgOp::methodcall(CgOp::letvar("k"), "at-pos", CgOp::box('Num', CgOp::double(0))))))),
CgOp::rawccall(CgOp::rxframe, "Backtrack")));
push @code, CgOp::rxpushb("SUBRULE", $bt);

$icn, Op::CallSub->new(
invocant => Op::Lexical->new(name => '&_rxcall'),
positionals => [
Op::CallMethod->new(name => $self->name,
receiver => Op::Lexical->new(name => $icn)),
$self->_close_k($cn, $cont)]);
@code;
}

sub lad {
Expand Down Expand Up @@ -376,20 +343,6 @@ use CgOp;
use Moose;
extends 'RxOp';

sub op {
my ($self, $cn, $cont) = @_;
my $icn = Niecza::Actions->gensym;
$icn, Op::CallSub->new(
invocant => Op::Lexical->new(name => '&_rxalt'),
positionals => [
Op::Lexical->new(name => $icn),
Op::CgOp->new(op => CgOp::wrap(CgOp::rawnewarr('LAD',
map { $_->lad } @{ $self->zyg }))), #XXX
$self->_close_k($cn, $cont),
map { $self->_close_op($_) } @{ $self->zyg }
]);
}

sub lad {
my ($self) = @_;
CgOp::rawnew('LADAny', CgOp::rawnewarr('LAD',
Expand Down
51 changes: 19 additions & 32 deletions test2.pl
Expand Up @@ -3,19 +3,6 @@

#ok '{}' ~~ / \{ <.ws> \} /, 'ws matches between \W';

PRE-INIT {
Q:CgOp {
(prog
(rawsset RxFrame.EMPTYP (@ {EMPTY}))
(rawsset RxFrame.ListMO (getfield klass (cast DynObject (@ {List}))))
(rawsset RxFrame.LLArrayMO (getfield klass
(cast DynObject (@ {LLArray}))))
(rawsset RxFrame.GatherIteratorMO (getfield klass
(cast DynObject (@ {GatherIterator}))))
(null Variable))
}
}
{
ok ("a" ~~ /a/), "letter matches itself";
ok !("a" ~~ /b/), "letter does not match other";
Expand Down Expand Up @@ -44,32 +31,32 @@
ok !Bob.parse("acx"), "grammars anchor (2)";
}

# {
# my grammar G1 {
# regex TOP { <.foo> }
# regex foo { x }
# }
#
# ok G1.parse("x"), "subrules work (positive)";
# ok !G1.parse("y"), "subrules work (negative)";
#
# my grammar G2 {
# regex TOP { y <.foo> <.foo> y }
# regex foo { x }
# }
#
# ok G2.parse("yxxy"), "subrule position tracking works";
# ok !G2.parse("yxy"), "subrule position tracking works (2)";
#
{
my grammar G1 {
regex TOP { <.foo> }
regex foo { x }
}

ok G1.parse("x"), "subrules work (positive)";
ok !G1.parse("y"), "subrules work (negative)";

my grammar G2 {
regex TOP { y <.foo> <.foo> y }
regex foo { x }
}

ok G2.parse("yxxy"), "subrule position tracking works";
ok !G2.parse("yxy"), "subrule position tracking works (2)";

# my grammar G3 {
# regex TOP { <moo> }
# regex moo { x }
# }
#
# ok G3.parse("x"), "capturing subrules work (positive)";
# ok !G3.parse("y"), "capturing subrules work (negative)";
# }
#
}

{
ok ("aab" ~~ /a* ab/), "a*ab backtracks";
ok !("aab" ~~ /a*: ab/), "a*: ab doesn't";
Expand Down

0 comments on commit 6d0d084

Please sign in to comment.