Author: pmichaud
Date: Tue Nov 15 21:11:51 2005
New Revision: 10013
Modified:
trunk/compilers/pge/PGE/Rule.pir
trunk/t/p6rules/builtins.t
Log:
Added a naive implementation of <after> (lookbehinds).
Modified: trunk/compilers/pge/PGE/Rule.pir
==============================================================================
--- trunk/compilers/pge/PGE/Rule.pir (original)
+++ trunk/compilers/pge/PGE/Rule.pir Tue Nov 15 21:11:51 2005
@@ -482,6 +482,62 @@ success.
.return (mob)
.end
+=item C<after(PMC mob, STR pattern)>
+
+Perform lookbehind -- i.e., check if the string before the
+current position matches <pattern> (anchored at the end).
+Returns a zero-width Match object on success.
+
+XXX: Note that this implementation cheats in a big way.
+S05 says that C<after> is implemented by reversing the
+syntax tree and looking for things in opposite order going
+to the left. This implementation just grabs the (sub)string
+up to the current match position and tests that, anchoring
+the pattern to the end of the substring. It's cheap and
+potentially very inefficient, but it "works" for now.
+
+=cut
+
+.sub "after"
+ .param pmc mob
+ .param string pattern :optional
+ .param int has_pattern :opt_flag
+ .local pmc cache, rule
+ .local int from
+
+ if has_pattern goto lookbehind
+ mob = fail(mob)
+ .return (mob)
+ lookbehind:
+ pattern = concat "[", pattern
+ pattern = concat pattern, "]$"
+ cache = find_global "PGE::Rule", "%:cache"
+ $I0 = exists cache[pattern]
+ if $I0 == 0 goto new_pattern
+ rule = cache[pattern]
+ goto match
+ new_pattern:
+ $P0 = find_global "PGE", "p6rule"
+ rule = $P0(pattern)
+ cache[pattern] = rule
+ match:
+ $P0 = getattribute mob, "PGE::Match\x0$:target"
+ $S0 = $P0
+ $P0 = getattribute mob, "PGE::Match\x0$:pos"
+ from = $P0
+ $S0 = substr $S0, 0, from
+ mob = rule($S0)
+ unless mob goto end
+ $P0 = getattribute mob, "PGE::Match\x0$:from"
+ $P1 = getattribute mob, "PGE::Match\x0$:pos"
+ $P0 = from
+ $P1 = from
+ null $P0
+ setattribute mob, "PGE::Match\x0&:corou", $P0
+ end:
+ .return (mob)
+.end
+
=head1 AUTHOR
Modified: trunk/t/p6rules/builtins.t
==============================================================================
--- trunk/t/p6rules/builtins.t (original)
+++ trunk/t/p6rules/builtins.t Tue Nov 15 21:11:51 2005
@@ -137,6 +137,19 @@ p6rule_like ("aabaaa", '<!before ..b> a
qr/mob: <aa @ 3>/,
'negated lookahead');
+p6rule_is ('ab', '<after a>b', 'lookbehind <after>');
+p6rule_isnt('cb', '<after a>b', 'lookbehind <after>');
+p6rule_isnt('b', '<after a>b', 'lookbehind <after>');
+p6rule_is ('ab', '<!after c>b', 'lookbehind <!after>');
+p6rule_isnt('cb', '<!after c>b', 'lookbehind <!after>');
+p6rule_is ('b', '<!after c>b', 'lookbehind <!after>');
+p6rule_isnt('dbcb', '<!after <[cd]>>b', 'lookbehind <!after>');
+p6rule_is ('dbaacb', '<!after <[cd]>><[ab]>', 'lookbehind <!after>');
+p6rule_isnt('dbcb', '<!after c|d>b', 'lookbehind <!after>');
+p6rule_is ('dbaacb', '<!after c|d><[ab]>', 'lookbehind <!after>');
+p6rule_is ('cbaccb', '<!after cd><[ab]>', 'lookbehind <!after>');
+p6rule_is ('a', '$ <after ^a>', 'lookbehind <after>');
+p6rule_is ('axxbxxyc', '<after x+>y', 'lookbehind <after>');
## leading + -- enumerated char class
p6rule_is ('az', '<[a..z]>+', 'metasyntax with leading + (<+...>)');
@@ -164,4 +177,4 @@ p6rule_is ($str, 'x | y | <?null>', 'nu
## remember to change the number of tests :-)
-BEGIN { plan tests => 55; }
+BEGIN { plan tests => 68; }