> > I am working with a grammar that I would like to have operate in two > different modes. In both modes the rules are identical, but the methods > should behave differently.
... > As an illustration (not the actual problem), say we want to proces > arithmetical expressions in two modes: normally we just copy the input, but > within a pair of braces we directly calculate the result. My first thought was to subclass the grammar, and re-use the parsing while overriding some actions. But I didn't look into it, and saw you had an answer that keeps track of parsing depth. Still I wanted to try this by having different actions on the top-level vs inner parsing. To work with the example, I started with a grammar with no actions. grammar Sums { rule TOP { <any-expr> } token any-expr { <operand>+ % <op> } token operand { <int> | <bracketed-expr> } token bracketed-expr { '{' <any-expr> '}' } token op { <[-+]> } token int { \d+ } } and I realized that the differing actions can be hung on the different parts of the tree. "bracketed-expr" computes "any-expr", while "TOP" simply converts it to a string. class do-sums { method TOP($/) { make $<any-expr>.caps.map: { ($_<op> || $_<operand>.made).Str } } method operand($/) { make $<int> // $<bracketed-expr>.made } method bracketed-expr($/) { make evaluate( $/<any-expr> ) } sub evaluate($expr) { if $expr.caps.elems > 1 { return ($expr.caps).reduce: -> $left is rw, (:value(:$op),|), $right is rw { $left = evaluate($left<operand>) unless $left ~~ Numeric; $right= evaluate($right<operand>); given $op { when '+' { $left + $right } when '-' { $left - $right } } } } return $expr<bracketed-expr> ?? evaluate($expr<bracketed-expr><any-expr>) !! $expr; } } # Try it out say Sums.parse('5', actions => do-sums.new).made; # 5 say Sums.parse('{6}+{8-{9+1+2}}-5', actions => do-sums.new).made; # 6 + -4 - 5 Which is a solution to "how do I keep one grammar, but do different things when the same token matches in different contexts." Not quite Theo's original question of "how to make a method behave differently at different parse depths" still it was a fun way to spend all morning... I'd like to simplify "sub evaluate"- in particular the deconstructed argument $op. That positional parameter is a Pair keyed on 'op', is there a clearer way of assigning it to $op? -y