AFAIK you cannot configure infix operators and determine priority, etc. in grammars. They apply only to the Perl 6 extension.
Here is a possible approach. It analyzes multiplicative terms before adding, and also allows you to enter words or characters, for example. times or * .
use v6; grammar TestGrammar { rule TOP { <expr=.add> } rule add { <expr=.multiply> +% [ <add-op> ] } rule multiply { <digit> +% [ <mult-op> ] } proto token mult-op {*} token mult-op:sym<times> { <sym>|'*' } token mult-op:sym<divided> { <sym>|'/' } proto token add-op {*} token add-op:sym<plus> { <sym>|'+' } token add-op:sym<minus> { <sym>|'-' } } sub MAIN() { for ("2+2", "2 + 2", "1 * 2", "1 + 2 * 6", "4 times 7 minus 3") { say $_; my $match = TestGrammar.parse($_); say $match; } }
Note that % is a delimiter operator. <digit> +% [ <mult-op> ] means a list of digits separated by multiplicative operators ( times , * , divided or / ).
Alternative Sep 2014 Solution:
S05 mentions that although rules and tokens are special methods, both can be declared as multi and accept arguments in the same way as regular methods.
This approach uses both recursion and multitasking to implement operator priority levels.
use v6; grammar TestGrammar { rule TOP { <expr(3)> } # operator multi-dispatch, loosest to tightest multi token op(3) {'+'|'-'|add|minus} multi token op(2) {'*'|'/'|times|divided} multi token op(1) {'**'} # expression multi-dispatch (recursive) multi rule expr(0) { <digit> | '(' ~ ')' <expr(3)> } multi rule expr($pred) { <expr($pred-1)> +% [ <op($pred)> ] } } sub MAIN() { for ("2+2", "2 + 2", "1 * 2", "1 + 2**3 * 6", "4 times (7 minus 3) * 3") { say $_; my $match = TestGrammar.parse($_); say $match; } }
dwarring
source share