Skip to content

Instantly share code, notes, and snippets.

@masak
Created January 22, 2010 14:51
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/283799 to your computer and use it in GitHub Desktop.
Save masak/283799 to your computer and use it in GitHub Desktop.
$ ./test-regex '<[a..b]> | <[b..e]>' c
Alt[
EnumCharList ('ab')
EnumCharList ('bcde')
]
sub ($target, :$debug) {
my $mfrom;
my $cpos = 0;
my $pos;
my $rep;
my $lastpos = $target.chars;
my @gpad; # TODO: PGE generates this one only when needed
my @ustack; # 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');
break;
}
$mfrom = $pos = $cpos;
local-branch('R');
}
when 'try_match_cont' {
++$cpos;
goto('try_match');
}
when 'succeed' {
return GGE::Match.new(:$target, :from($mfrom), :to($pos));
}
when 'fail' {
local-return();
if !@cstack {
return GGE::Match.new(:$target, :from(0), :to(-2));
}
}
when 'R' { # alt R0, R1
push @ustack, $pos;
local-branch('R0');
}
when 'R_cont' {
$pos = pop @ustack;
goto('R1');
}
when 'R0' {
if $pos >= $lastpos
|| !defined 'ab'.index($target.substr($pos, 1)) {
goto('fail');
break;
}
++$pos;
goto('succeed');
}
when 'R1' {
if $pos >= $lastpos
|| !defined 'bcde'.index($target.substr($pos, 1)) {
goto('fail');
break;
}
++$pos;
goto('succeed');
}
default {
die "Don't know a label {@cstack[*-1]}";
}
}
}
}
mob: <c @ 0>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment