Course of Raku / Addendum 🆕 / Types and text machines / Regexes and grammars / Exercises / A grammar that adds
Solution: A grammar that adds
Here is a possible solution to the task.
Code
grammar Sum {
token TOP { <number>+ % '+' }
token number { \d+ }
}
class SumActions {
method TOP($/) { make [+] $<number>.map(*.Int) }
}
say Sum.parse('3+4+5', actions => SumActions).made;🦋 You can find the source code in the file grammar-sum.raku.
Output
12Comments
<number>+ % '+'matches one or more numbers separated by+signs — the%modifier describes the separator between repetitions.The action method runs when
TOPmatches.makeattaches a computed value — the sum of the numbers — which.madereads back after parsing.A
tokennever skips spaces, so this grammar is strict about its input:'3+4+5'parses, but'3 + 4 + 5'does not (.parsereturnsNil). To accept spaces around the plus signs, makeTOParule— and detach the quantifier from its atom:grammar Sum { rule TOP { <number> + % '+' } token number { \d+ } }
In a
rule, whitespace in the pattern stands for an implicit<.ws>call. Written as<number> + % '+', with a space before the+quantifier, that implied whitespace covers the whole repetition — separators included — so both'3+4+5'and'3 + 4 + 5'are parsed, and the sum is12either way. (If you prefer to stay with atoken, spell the spaces out in the separator:<number>+ % [ \s* '+' \s* ].)