Author: pmichaud
Date: Fri Mar 17 16:48:00 2006
New Revision: 11921
Modified:
trunk/compilers/pge/PGE/Exp.pir
trunk/compilers/pge/PGE/Match.pir
trunk/compilers/pge/PGE/P6Rule.pir
trunk/t/compilers/pge/p6rules/closure.t
Log:
Added "return value" capability for embedded closures in p6 rules.
Modified: trunk/compilers/pge/PGE/Exp.pir
==============================================================================
--- trunk/compilers/pge/PGE/Exp.pir (original)
+++ trunk/compilers/pge/PGE/Exp.pir Fri Mar 17 16:48:00 2006
@@ -1192,8 +1192,13 @@
emit(code, " %s_1:", label)
emit(code, " $P1 = $P0[$S0]")
emit(code, " mpos = pos")
- emit(code, " $P1(mob)")
- emit(code, " goto %s", next)
+ emit(code, " ($P0 :optional, $I0 :opt_flag) = $P1(mob)")
+ emit(code, " if $I0 == 0 goto %s", next)
+ emit(code, " setattribute mob, \"PGE::Match\\x0$!return\", $P0")
+ self.emitsub(code, "succeed", "pos")
+ emit(code, " null $P0")
+ emit(code, " setattribute mob, \"PGE::Match\\x0$!return\", $P0")
+ emit(code, " goto fail")
.return ()
.end
Modified: trunk/compilers/pge/PGE/Match.pir
==============================================================================
--- trunk/compilers/pge/PGE/Match.pir (original)
+++ trunk/compilers/pge/PGE/Match.pir Fri Mar 17 16:48:00 2006
@@ -19,6 +19,7 @@
addattribute base, "$.pos" # current match position
addattribute base, "&!corou" # match's corou
addattribute base, "@!capt" # subpattern captures
+ addattribute base, "$!return" # return value
.return ()
.end
@@ -132,6 +133,44 @@
.return (to)
.end
+=item C<substring()>
+
+Returns the portion of the target string matched by this object.
+
+=cut
+
+.sub "substr" :method
+ $P0 = getattribute self, "PGE::Match\x0$.target"
+ $P1 = getattribute self, "PGE::Match\x0$.from"
+ $P2 = getattribute self, "PGE::Match\x0$.pos"
+ if $P2 < 0 goto false
+ if $P2 <= $P1 goto false
+ $I1 = $P1
+ $I2 = $P2
+ $I2 -= $I1
+ $S1 = substr $P0, $I1, $I2
+ .return ($S1)
+ false:
+ .return ("")
+.end
+
+=item C<value()>
+
+Returns the "return value" for the match object. If no return value has
+been explicitly set (by an embedded closure), return the substring
+that was matched by this match object.
+
+=cut
+
+.sub "value" :method
+ $P0 = getattribute self, "PGE::Match\x0$!return"
+ if_null $P0, value_1
+ .return ($P0)
+ value_1:
+ $S0 = self."substr"()
+ .return ($S0)
+.end
+
=item C<__get_bool()>
Returns 1 if this object successfully matched the target string,
@@ -153,8 +192,7 @@
=cut
.sub "__get_integer" :method
- $S0 = self
- $I0 = $S0
+ $I0 = self."value"()
.return ($I0)
.end
@@ -165,8 +203,7 @@
=cut
.sub "__get_number" :method
- $S0 = self
- $N0 = $S0
+ $N0 = self."value"()
.return ($N0)
.end
@@ -177,18 +214,8 @@
=cut
.sub "__get_string" :method
- $P0 = getattribute self, "PGE::Match\x0$.target"
- $P1 = getattribute self, "PGE::Match\x0$.from"
- $P2 = getattribute self, "PGE::Match\x0$.pos"
- if $P2 < 0 goto false
- if $P2 <= $P1 goto false
- $I1 = $P1
- $I2 = $P2
- $I2 -= $I1
- $S1 = substr $P0, $I1, $I2
- .return ($S1)
- false:
- .return ("")
+ $S0 = self."value"()
+ .return ($S0)
.end
=item C<__get_string_keyed_int(int key)>
Modified: trunk/compilers/pge/PGE/P6Rule.pir
==============================================================================
--- trunk/compilers/pge/PGE/P6Rule.pir (original)
+++ trunk/compilers/pge/PGE/P6Rule.pir Fri Mar 17 16:48:00 2006
@@ -83,6 +83,12 @@
$P0["n"] = unicode:"\x0a\x0d\x0c\x85\u2028\u2029"
# See http://www.unicode.org/Public/UNIDATA/PropList.txt for above
+ # Create and store closure preprocessors in %closure_pp
+ $P0 = new Hash
+ store_global "PGE::P6Rule", "%closure_pp", $P0
+ $P1 = find_global "PGE::P6Rule", "PIR_closure"
+ $P0["PIR"] = $P1
+
$P0 = find_global "PGE", "p6rule"
compreg "PGE::P6Rule", $P0
.end
@@ -951,15 +957,39 @@
.sub "p6analyze" :method
.param pmc pad
- $S0 = pad[":lang"]
- self["lang"] = $S0
- if $S0 != "PIR" goto end
+ .local string lang
+ .local pmc closure_pp
+ .local pmc closure_fn
+ lang = pad[":lang"]
+ self["lang"] = lang
+ # see if we need to do any pre-processing of the closure
+ closure_pp = find_global "PGE::P6Rule", "%closure_pp"
+ $I0 = defined closure_pp[lang]
+ if $I0 == 0 goto end
+ closure_fn = closure_pp[lang]
$S1 = self["value"]
- $I0 = index $S1, ".sub"
- if $I0 >= 0 goto end
- $S1 = concat ".sub anon :anon\n.param pmc match\n", $S1
- $S1 .= "\n.end\n"
+ $S1 = closure_fn($S1)
self["value"] = $S1
end:
.return (self)
.end
+
+=item C<PIR_closure(string code)>
+
+This helper function helps with :lang(PIR) closures in rules
+by adding a ".sub" wrapper around the code if one isn't
+already present.
+
+=cut
+
+.namespace [ "PGE::P6Rule" ]
+
+.sub "PIR_closure"
+ .param string code
+ $I0 = index code, ".sub"
+ if $I0 >= 0 goto end
+ code = concat ".sub anon :anon\n.param pmc match\n", code
+ code .= "\n.end\n"
+ end:
+ .return (code)
+.end
Modified: trunk/t/compilers/pge/p6rules/closure.t
==============================================================================
--- trunk/t/compilers/pge/p6rules/closure.t (original)
+++ trunk/t/compilers/pge/p6rules/closure.t Fri Mar 17 16:48:00 2006
@@ -42,6 +42,25 @@
}}}}",
qr/foo/, "multi-line PASM closure");
+p6rule_like("abcdef",
+ ":lang(PIR) abc {{{{
+ .return (\"xyz\")
+ }}}}",
+ qr/xyz/, "PIR closure with return");
+
+p6rule_like("abcdef",
+ ":lang(PIR) abc {{{{
+ .return (\"xyz\")
+ }}}} ghi",
+ qr/xyz/, "PIR closure with return always succeeds");
+p6rule_like("1234xyz5678",
+ ":lang(PIR) 2\\d\\d {{{{
+ \$I0 = match
+ \$I0 += 123
+ .return (\$I0)
+ }}}} ghi",
+ qr/357/, "PIR closure modifying match");
+
# remember to change the number of tests :-)
-BEGIN { plan tests => 3; }
+BEGIN { plan tests => 6; }