Andrew Whitworth said:
> Instead of simply giving all optables a unique identifier, maybe we
> should add them to a hash with the name of the "is optable" rule
> being the key for it. That way we could get to the various optables
> by name. Languages like Perl6 that expect to only have one optable
> could simply bind the preferred one to the "$optable" variable.

Good point.

My previous patch was actually broken (I hadn't re-compiled the NQP
grammar with the new Perl6Grammar), and I think your remark may explain
why (I didn't want to check the details, however).

This new patch does the following:
* optables are registered as "$optable_rulename", where "rulename" is
the... name of the rule defining the optable!
* the first optable is also registered as "$optable".

-- 
Florian,
http://openweb.eu.org/
http://www.linux-france.org/

--- runtime/parrot/library/PGE/Perl6Grammar.pir	2008-10-12 19:16:15.000000000 +0200
+++ runtime/parrot/library/PGE/Perl6Grammar.new	2008-10-12 19:16:06.000000000 +0200
@@ -192,8 +192,6 @@
   ns_optable:
     $P0 = ns['optable']
     if $P0 == '' goto iter_loop
-    initpir.emit("          optable = new 'PGE::OPTable'")
-    initpir.emit("          set_hll_global ['%0'], '$optable', optable", namespace)
     initpir .= $P0
     goto iter_loop
   iter_end:
@@ -290,16 +288,35 @@
     goto with_rulepir
   rulepir_optable:
     ##   this is a special rule generated via the 'is optable' trait
+    .local pmc optable
+    $P0 = nstable[namespace]
+    optable = $P0['optable']
+    $P0 = stmt['name']
+    # The optable is called $optable_rulename
+    $S0 = "optable_"
+    $S1 = $P0[0]
+    $S0 = concat $S0, $S1
+
     rulepir = new 'CodeString'
-    rulepir.emit(<<'      END', namespace, name)
+    rulepir.emit(<<'      END', namespace, name, $S0)
       .namespace [ "%0" ]
       .sub "%1"
         .param pmc mob
         .param pmc adverbs :named :slurpy
-        $P0 = get_hll_global ["%0"], "$optable"
+        $P0 = get_hll_global ["%0"], "$%2"
         .return $P0.'parse'(mob, 'rulename'=>"%1", adverbs :named :flat)
       .end
       END
+
+    $S1 = optable
+    optable.emit("          optable = new 'PGE::OPTable'")
+
+    # The first (default, preferred, and only one for many languages) optable is
+    # simply called "$optable".
+    if $S1 != '' goto not_first_optable
+      optable.emit("          set_hll_global ['%0'], '$optable', optable", namespace)
+    not_first_optable:
+      optable.emit("          set_hll_global ['%0'], '$%1', optable", namespace, $S0)
   with_rulepir:
 
     ##   add to set of rules
--- docs/pct/pct_optable_guide.pod	2008-09-17 00:14:34.000000000 +0200
+++ docs/pct/pct_optable_guide.new	2008-10-10 13:23:41.000000000 +0200
@@ -426,7 +426,22 @@
 
 =item * How many operator tables can I use in my language?
 
-{{ XXX I think one only? Anybody? }}
+You can use as many operator tables as you like: each operator table is declared
+in a rule, as above. Operators automatically belong to the last operator table
+defined before their C<proto> rule. This means, in particular, that you cannot
+add any more operator to an optable once you've started another optable.
+
+The following example defines two optables C<expr> and C<otherexpr>, with some
+operators:
+
+ rule expr is optable { ... }
+ proto 'infix:+' is precedence('1') { ... }
+ proto 'infix:*' is tighter('infix:+') { ... }
+ proto 'term:' is tighter('infix:*') is parsed(&term) { ... }
+
+ rule otherexpr is optable { ... }
+ proto 'infix:+' is precedence('1')
+ proto 'term:' is tighter('infix:+') is parsed(&otherterm) { ... }
 
 =item * How does an optable parser work?
 

Reply via email to