Author: pmichaud
Date: Tue Nov 1 20:13:24 2005
New Revision: 9697
Added:
trunk/t/p6rules/closure.t
Modified:
trunk/MANIFEST
trunk/compilers/pge/PGE/Exp.pir
trunk/compilers/pge/PGE/P6Rule.pir
Log:
Added ability to call language-specific executables from rules.
* {{ executable }}
* Added :lang(compiler) modifier
* Added tests in t/p6rules/closure.t
Modified: trunk/MANIFEST
==============================================================================
--- trunk/MANIFEST (original)
+++ trunk/MANIFEST Tue Nov 1 20:13:24 2005
@@ -1866,6 +1866,7 @@ t/p6rules/backtrack.t
t/p6rules/builtins.t []
t/p6rules/capture.t []
t/p6rules/cclass.t []
+t/p6rules/closure.t []
t/p6rules/escape.t []
t/p6rules/metachars.t []
t/p6rules/modifiers.t []
Modified: trunk/compilers/pge/PGE/Exp.pir
==============================================================================
--- trunk/compilers/pge/PGE/Exp.pir (original)
+++ trunk/compilers/pge/PGE/Exp.pir Tue Nov 1 20:13:24 2005
@@ -25,6 +25,7 @@
$P1 = subclass $P0, "PGE::Exp::Cut"
$P1 = subclass $P0, "PGE::Exp::Quant"
$P1 = subclass $P0, "PGE::Exp::Modifier"
+ $P1 = subclass $P0, "PGE::Exp::Closure"
$P0 = new Integer
store_global "PGE::Exp", "$_serno", $P0
.end
@@ -970,3 +971,41 @@ register.
emit(code, " goto fail")
.return ()
.end
+
+.namespace [ "PGE::Exp::Closure" ]
+
+.sub "reduce" :method
+ self["isquant"] = 1
+ .return (self)
+.end
+
+.sub "gen" :method
+ .param pmc code
+ .param string label
+ .param string next
+ .local pmc emit
+ .local string value, lang
+ emit = find_global "PGE::Exp", "emit"
+ value = self["value"]
+ lang = self["lang"]
+ $P0 = find_global "Data::Escape", "String"
+ value = $P0(value, '"')
+ lang = $P0(lang, '"')
+ emit(code, "\n %s: # closure ##", label)
+ emit(code, " $S0 = \"%s:\"", lang)
+ emit(code, " $S1 = \"%s\"", value)
+ emit(code, " $S0 .= $S1")
+ emit(code, " $P0 = find_global \"PGE::Rule\", \"%:cache\"")
+ emit(code, " $I0 = exists $P0[$S0]")
+ emit(code, " if $I0 goto %s_1", label)
+ emit(code, " $P1 = compreg \"%s\"", lang)
+ emit(code, " $P1 = $P1($S1)")
+ emit(code, " $P0[$S0] = $P1")
+ emit(code, " %s_1:", label)
+ emit(code, " $P1 = $P0[$S0]")
+ emit(code, " mpos = pos")
+ emit(code, " $P1(mob)")
+ emit(code, " goto %s", next)
+ .return ()
+.end
+
Modified: trunk/compilers/pge/PGE/P6Rule.pir
==============================================================================
--- trunk/compilers/pge/PGE/P6Rule.pir (original)
+++ trunk/compilers/pge/PGE/P6Rule.pir Tue Nov 1 20:13:24 2005
@@ -47,6 +47,9 @@
optable.addtok("term:<[", "term:", "nows", $P0)
optable.addtok("term:<-[", "term:", "nows", $P0)
+ $P0 = find_global "PGE::P6Rule", "parse_closure"
+ optable.addtok("term:{{", "term:", "nows", $P0)
+
$P0 = find_global "PGE::P6Rule", "parse_quant"
optable.addtok("postfix:*", "<term:", "left", $P0)
optable.addtok("postfix:+", "postfix:*", "left", $P0)
@@ -160,6 +163,38 @@
.end
+.sub "parse_closure"
+ .param pmc mob
+ .local pmc newfrom
+ .local string target
+ .local pmc mfrom, mpos
+ .local int pos, len
+ $P0 = find_global "PGE::Match", "newfrom"
+ (mob, target, mfrom, mpos) = $P0(mob, 0, "PGE::Exp::Closure")
+ pos = mfrom
+ len = 0
+ init:
+ $S0 = substr target, pos, 1
+ if $S0 != "{" goto body
+ inc len
+ inc pos
+ goto init
+ body:
+ $S0 = repeat "}", len
+ $I0 = index target, $S0, pos
+ if $I0 < pos goto err_noclose
+ $I1 = $I0 - pos
+ $S1 = substr target, pos, $I1
+ mob["value"] = $S1
+ pos = $I0 + len
+ mpos = pos
+ .return (mob)
+ err_noclose:
+ parse_error(mob, pos, "Missing closing braces for closure")
+ .return (mob)
+.end
+
+
.sub "parse_quant"
.param pmc mob
.local string target
@@ -444,8 +479,6 @@
.param int has_gram :opt_flag
.param string name :optional
.param int has_name :opt_flag
- .param int pironly :optional
- .param int has_pironly :opt_flag
.local pmc exp
.local pmc newfrom
.local pmc code
@@ -468,6 +501,7 @@
pad["reps"] = $P0
pad["cutnum"] = PGE_CUT_GROUP
pad["subpats"] = 0
+ pad[":lang"] = "PIR"
$P0 = exp["expr"]
$P0 = $P0.p6analyze(pad)
exp["expr"] = $P0
@@ -479,7 +513,6 @@
code = exp."as_pir"(name)
code = concat $P0, code
- if has_pironly goto end
$P0 = compreg "PIR"
sub = $P0(code)
if has_name == 0 goto end
@@ -768,3 +801,20 @@
exp1 = exp1.p6analyze(pad)
.return (exp1)
.end
+
+.namespace [ "PGE::Exp::Closure" ]
+
+.sub "p6analyze" :method
+ .param pmc pad
+ $S0 = pad[":lang"]
+ self["lang"] = $S0
+ if $S0 != "PIR" goto end
+ $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"
+ self["value"] = $S1
+ end:
+ .return (self)
+.end
Added: trunk/t/p6rules/closure.t
==============================================================================
--- (empty file)
+++ trunk/t/p6rules/closure.t Tue Nov 1 20:13:24 2005
@@ -0,0 +1,20 @@
+
+use Parrot::Test tests => 3;
+use Parrot::Test::PGE;
+
+p6rule_like("abcd", "<alpha>**{3} {{ print match }}",
+ qr/abcmatched/, "PIR closure");
+
+p6rule_like("123 any",
+ ":lang(PIR) <digit>+ {{ I0 = match \n I0 *= 2 \n print I0 }}",
+ qr/246/, "multi-line PIR closure");
+
+p6rule_like("123 any",
+ ":lang(PASM) <digit>+ {{{{
+ .pcc_sub _foo:
+ print \"foo\\n\"
+ set_returns \"()\"
+ returncc
+ }}}}",
+ qr/foo/, "multi-line PASM closure");
+