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; }

Reply via email to