Perl 6 grammar example with operator precedence rules

I am very new to Perl and want to create a domain-specific language with statements that take precedence using the new Perl 6 grammar features. For example, parse "1 + 2 * 6" correctly.

The documentation I have found so far (e.g. this ) has no examples with grammar rules for operators with priority declarations.

I have this very simple example

use v6; #use Grammar::Tracer; grammar TestGrammar { token TOP { <digit> <infix> <digit> } token infix:sym<times> is equiv(&infix:<*>) { <sym> } } sub MAIN() { my $text = "1 times 2" ; say $text ; my $match = TestGrammar.parse($text); say $match; } 

It gives me

 No such method 'infix' for invocant of type 'TestGrammar' 

I just want to build an abstract syntax tree.

+7
parsing perl6 grammar
source share
1 answer

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; } } 
+5
source share

All Articles