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?