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?