Permalink
Browse files

[dotnet] make regex Actions generate method not sub

  • Loading branch information...
diakopter committed Nov 22, 2010
1 parent 5f2da69 commit 2bceca45a5e781c60d06dd9f7a678831297f16d2
Showing with 112 additions and 29 deletions.
  1. +4 −0 common/NQP/NQPSetting.pm
  2. +19 −15 common/NQP/P6Objects.pm
  3. +87 −4 dotnet/compiler/Actions.pm
  4. +2 −10 dotnet/compiler/PAST2DNSTCompiler.pm
View
@@ -24,6 +24,10 @@ my knowhow NQPStr is repr('P6str') {
method defined() {
nqp::repr_defined(self)
}
+ method ACCEPTS($target) {
+ my $what := self;
+ $what.isa($target, $what);
+ }
}
my knowhow NQPInt is repr('P6int') {
View
@@ -30,7 +30,12 @@ class Mu {
class Capture {
has $.cap;
method new() {
- $!cap := nqp::instance_of(NQPCapture);
+ my $obj := self.CREATE();
+ $obj.BUILD();
+ $obj;
+ }
+ method BUILD() {
+ $!cap := nqp::instance_of(NQPCapture.WHAT)
}
method at_pos($pos) {
nqp::llcap_get_at_pos($!cap, $pos)
@@ -79,9 +84,9 @@ class Match is Capture {
}
}
-# Cursor is used for managing regular expression control flow
+# Regex::Cursor is used for managing regular expression control flow
# and is also a base class for grammars.
-class Cursor {
+class Regex::Cursor {
has $.target is rw;
has $.from is rw;
has $.pos is rw;
@@ -188,17 +193,17 @@ class Cursor {
# Parse C<target> in the current grammar starting with C<regex>.
# If C<regex> is omitted, then use the C<TOP> rule for the grammar.
- method parse($target, :$rule?, :$actions?, :$rxtrace?, *%options) {
+ method parse($target, :$rule?, :$actions?, :$rxtrace?, :$p?, :$c?) {
$rule := 'TOP' unless nqp::repr_defined($rule);
- if $rule ~~ NQPStr {
+ if $rule.WHAT =:= NQPStr {
$rule := self.HOW.find_method($rule);
}
my $*ACTIONS := $actions;
- my $cur := self.cursor_init($target, :p(%options{'p'}), :c(%options{'c'}));
- if $rxtrace {
- $cur.DEBUG
- }
- my $cap := Capture.new();
+ my $cur := self.cursor_init($target, nqp::repr_defined($p) ?? $p !! 0, $c);
+ #if nqp::repr_defined($rxtrace) {
+ # $cur.DEBUG
+ #}
+ my $cap := Capture.new;
$cap.bind_pos(0, $cur);
Ops.invoke($rule, $cap).MATCH;
}
@@ -209,7 +214,7 @@ class Cursor {
}
# Create a new cursor for matching C<target>.
- method cursor_init($target, $p, $c) {
+ method cursor_init($target, $p, $c?) {
my $cur := nqp::instance_of(self);
$cur.target($target);
if nqp::repr_defined($c) {
@@ -401,15 +406,14 @@ class Cursor {
}
}
-class Regex {
+class Regex::Regex {
has $!regex_block;
method new($regex_block) {
- $regex_block();
$!regex_block := $regex_block;
self
}
- multi method ACCEPTS(Regex:D $self: $target) {
- Cursor.new.parse($target, :rule($!regex_block))
+ method ACCEPTS($target) {
+ Regex::Cursor.new.parse($target, :rule($!regex_block))
}
}
View
@@ -874,8 +874,7 @@ method regex_declarator($/, $key?) {
return 0;
}
else {
- my $regex :=
- Regex::P6Regex::Actions::buildsub($<p6regex>.ast, @BLOCK.shift);
+ my $regex := buildsub($<p6regex>.ast, @BLOCK.shift);
$regex.name($name);
$past :=
PAST::Op.new(
@@ -1109,8 +1108,7 @@ method quote:sym</ />($/, $key?) {
@BLOCK[0].symbol('$/', :scope('lexical'));
return 0;
}
- my $regex :=
- Regex::P6Regex::Actions::buildsub($<p6regex>.ast, @BLOCK.shift);
+ my $regex := buildsub($<p6regex>.ast, @BLOCK.shift);
my $past :=
PAST::Op.new(
:pasttype<callmethod>, :name<new>,
@@ -1122,6 +1120,91 @@ method quote:sym</ />($/, $key?) {
make $past;
}
+sub buildsub($rpast, $block = PAST::Block.new() ) {
+ my %capnames := capnames($rpast, 0);
+ %capnames{''} := 0;
+ $rpast := PAST::Regex.new(
+ PAST::Regex.new( :pasttype('scan') ),
+ $rpast,
+ PAST::Regex.new( :pasttype('pass'),
+ # XXX :backtrack(@MODIFIERS[0]<r> ?? 'r' !! 'g') ),
+ :backtrack('g') ),
+ :pasttype('concat'),
+ :capnames(%capnames)
+ );
+ unless $block.symbol('') { $block.symbol('', :scope<lexical>); }
+ unless $block.symbol('$/') { $block.symbol('$/', :scope<lexical>); }
+ $block.push($rpast);
+ $block.blocktype('declaration');
+ $block.unshift(PAST::Var.new( :name('self'), :scope('parameter') ));
+ $block;
+}
+
+sub capnames($ast, $count) {
+ my %capnames;
+ my $pasttype := $ast.pasttype;
+ if $pasttype eq 'alt' {
+ my $max := $count;
+ for $ast.list {
+ my %x := capnames($_, $count);
+ for %x {
+ %capnames{$_} := +%capnames{$_} < 2 && %x{$_} == 1
+ ?? 1
+ !! 2;
+ }
+ if %x{''} > $max { $max := %x{''}; }
+ }
+ $count := $max;
+ }
+ elsif $pasttype eq 'concat' {
+ for $ast.list {
+ my %x := capnames($_, $count);
+ for %x {
+ %capnames{$_} := +%capnames{$_} + %x{$_};
+ }
+ $count := %x{''};
+ }
+ }
+ elsif $pasttype eq 'subrule' && $ast.subtype eq 'capture' {
+ my $name := $ast.name;
+ if $name eq '' { $name := $count; $ast.name($name); }
+ my @names := Q:PIR {
+ $P0 = find_lex '$name'
+ $S0 = $P0
+ %r = split '=', $S0
+ };
+ for @names {
+ if $_ eq '0' || $_ > 0 { $count := $_ + 1; }
+ %capnames{$_} := 1;
+ }
+ }
+ elsif $pasttype eq 'subcapture' {
+ my $name := $ast.name;
+ my @names := Q:PIR {
+ $P0 = find_lex '$name'
+ $S0 = $P0
+ %r = split '=', $S0
+ };
+ for @names {
+ if $_ eq '0' || $_ > 0 { $count := $_ + 1; }
+ %capnames{$_} := 1;
+ }
+ my %x := capnames($ast[0], $count);
+ for %x {
+ %capnames{$_} := +%capnames{$_} + %x{$_};
+ }
+ $count := %x{''};
+ }
+ elsif $pasttype eq 'quant' {
+ my %astcap := capnames($ast[0], $count);
+ for %astcap {
+ %capnames{$_} := 2;
+ }
+ $count := %astcap{''};
+ }
+ %capnames{''} := $count;
+ %capnames;
+}
method quote_escape:sym<$>($/) { make $<variable>.ast; }
method quote_escape:sym<{ }>($/) {
make PAST::Op.new(
@@ -1171,18 +1171,10 @@ our multi sub dnst_for(PAST::Regex $r) {
my $rb; # regex block
my $pasttype := $r.pasttype;
pir::die("Don't know how to compile toplevel regex pasttype $pasttype.") if $pasttype ne 'concat';
- # Toplevel regex creation
my $stmts := PAST::Stmts.new;
- $rb := PAST::Block.new(:blocktype('declaration'), $stmts);
- # emit regex to $rb
-
- dnst_for(PAST::Op.new(
- emit_outer_lexical_lookup('Regex'),
- :name('new'),
- :pasttype('callmethod'),
- dnst_for($rb)
- ))
+ $stmts.push(dnst_for(PAST::Val.new( :value(1) )));
+ dnst_for($stmts);
}
# Regex nodes reached inside a regex

0 comments on commit 2bceca4

Please sign in to comment.