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");
+           

Reply via email to