Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a default method for an action class of a grammar?

Tags:

grammar

raku

Recently, I experimented with some grammars for modifying small parts of a file. In those test cases, I would keep much of the file as it was, only modifying small pieces here and there, see this review question for an example.

So I needed one (or a few) action methods (i.e. methods in the action class of the grammar) where I would attach the modified parts of the file to the match object using its make method. The problem was that the grammar itself would have many more token/rules/regex with complicated nesting. Hence, there was a need to propagate (by successively calling make()) the small change (currently attached to a token's match object) up to the TOP() method in the action class such that everything else (all other tokens/rules/regexes) in the file was kept untouched in the result returned from the grammar's .parse() call.

So all methods in the action class except for one, was on the exact same form:

method make-data ($match-data) {
    $match-data.make( [~] $match-data.chunks.map: {$_.value.?made // $_.value} );
}

Now, this explicit repetition of the same code for all action methods seems to me very verbose, and also breaks with the DRY programming principle.

Is there a way to tell the grammar class that if an action method (corresponding to a token in the grammar) is not specified , it will default to the make-data method above (or a similar one)?

So in this case, I envision a DEFAULT() method in the action class:

method DEFAULT ($match-data) {
    $match-data.make( [~] $match-data.chunks.map: {$_.value.?made // $_.value} );
}

that is called if a token in the grammar class does not have a corresponding method in the action class.

like image 975
Håkon Hægland Avatar asked Feb 05 '23 01:02

Håkon Hægland


1 Answers

Perl 6's Type system will call a FALLBACK method, if it's present in a class and an unknown method call is made.

The following solution adds default construction methods to the Calculations actions class.

grammar Calculator {
    token TOP { [ <add> | <sub> ] }
    rule  add { <num> '+' <num> }
    rule  sub { <num> '-' <num> }
    token num { \d+ }
}

class Calculations {
    method ws($) {}
    method FALLBACK($token, $match-data) {
        $match-data.make( [~] $match-data.chunks.map: {
            $_.value.?made // $_.value;
        } );
    }
}

say Calculator.parse('2 + 3', actions => Calculations).made;
like image 168
dwarring Avatar answered Mar 14 '23 21:03

dwarring