Skip to content

Instantly share code, notes, and snippets.

@masak
Created January 24, 2010 02:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save masak/284959 to your computer and use it in GitHub Desktop.
Save masak/284959 to your computer and use it in GitHub Desktop.
$ ./test-regex '[(.)$0]+' bookkeeper
Quant ('greedy 1..Inf') [
Group[
Concat[
CGroup[
CCShortcut ('.')
]
Scalar ('$0')
]
]
]
sub ($target, :$debug) {
my $mob = GGE::Match.new(:$target);
my $mfrom;
my $cpos = 0;
my $pos;
my $rep;
my $lastpos = $target.chars;
my $cutmark;
my @gpad; # TODO: PGE generates this one only when needed
my @ustack; # TODO: PGE generates this one only when needed
my $captscope = $mob; # TODO: PGE generates this one only when needed
my $captob; # TODO: PGE generates this one only when needed
my @cstack = 'try_match';
my &goto = -> $label { @cstack[*-1] = $label };
my &local-branch = -> $label {
@cstack[*-1] ~= '_cont';
@cstack.push($label)
};
my &local-return = -> { @cstack.pop };
loop {
given @cstack[*-1] {
when 'try_match' {
if $cpos > $lastpos { goto('fail_rule'); break; }
$mfrom = $pos = $cpos;
$cutmark = 0;
local-branch('R');
}
when 'try_match_cont' {
if $cutmark <= -2 { goto('fail_cut'); break; }
++$cpos;
goto('try_match');
}
when 'fail_rule' {
# $cutmark = -2 # XXX: Not needed yet
goto('fail_cut');
}
when 'fail_cut' {
$mob.from = 0;
$mob.to = -2;
return $mob;
}
when 'succeed' {
$mob.from = $mfrom;
$mob.to = $pos;
return $mob;
}
when 'fail' {
local-return();
}
when 'R' { # quant 1..Inf (greedy) greedy/none
push @gpad, 0;
local-branch('R_repeat');
}
when 'R_cont' {
pop @gpad;
### if $cutmark != 0 { goto('fail'); break; }
### $cutmark = 0;
goto('fail');
}
when 'R_repeat' {
$rep = @gpad[*-1];
### if $rep >= Inf { goto('R_1'); break; }
++$rep;
@gpad[*-1] = $rep;
push @ustack, $pos;
push @ustack, $rep;
local-branch('R1');
}
when 'R_repeat_cont' {
$rep = pop @ustack;
$pos = pop @ustack;
if $cutmark != 0 { goto('fail'); break; }
--$rep;
goto('R_1');
}
when 'R_1' {
if $rep < 1 { goto('fail'); break; }
pop @gpad;
push @ustack, $rep;
local-branch('succeed');
}
when 'R_1_cont' {
$rep = pop @ustack;
push @gpad, $rep;
if $cutmark != 0 { goto('fail'); break; }
### $cutmark = 0;
goto('fail');
}
# concat
when 'R1' { # capture
if defined $captscope[0] {
goto('R1_cgen');
break;
}
$captscope[0] = [];
local-branch('R1_cgen');
}
when 'R1_cont' {
$captscope[0] = undef;
goto('fail');
}
when 'R1_cgen' {
goto('R1_1');
}
when 'R1_1' {
$captob = $captscope.new($captscope);
$captob.from = $pos; # XXX: PGE uses .pos here somehow.
push @gpad, $captscope;
push @gpad, $captob;
$captscope = $captob;
local-branch('R3');
}
when 'R1_1_cont' {
$captob = pop @gpad;
$captscope = pop @gpad;
### if $cutmark != ... { goto('fail'); break; }
### $cutmark = 0;
goto('fail');
}
when 'R1_close' {
push @ustack, $captscope;
$captob = pop @gpad;
$captscope = pop @gpad;
$captob.to = $pos;
$captscope[0].push($captob);
push @ustack, $captob;
local-branch('R2');
}
when 'R1_close_cont' {
$captob = pop @ustack;
$captscope[0].pop();
push @gpad, $captscope;
push @gpad, $captob;
$captscope = pop @ustack;
goto('fail');
}
when 'R3' { # ccshortcut .
if $pos >= $lastpos || False {
goto('fail');
break;
}
++$pos;
goto('R1_close');
}
when 'R2' { # scalar 0
my $capture = $mob[0];
if $capture ~~ Array {
$capture = $capture[*-1];
}
my $length = $capture.chars;
if $pos + $length > $lastpos
|| $target.substr($pos, $length) ne $capture {
goto('fail');
break;
}
$pos += $length;
goto('R_repeat');
}
default {
die "No such label: {@cstack[*-1]}";
}
}
}
}
mob: <ookkee @ 1>
mob 0 0: <o @ 1>
mob 0 1: <k @ 3>
mob 0 2: <e @ 5>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment