Курс языка программирования Raku / Приложение 🆕 / Типы и текстовые машины / Регулярные выражения и грамматики / Exercises / Грамматика, которая складывает

Решение: Грамматика, которая складывает

Вот один из возможных вариантов решения задачи.

Код

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;

🦋 Исходный код можно найти в файле grammar-sum.raku.

Вывод

12

Комментарии

  1. <number>+ % '+' сопоставляется с одним или несколькими числами, разделёнными знаками +: модификатор % описывает разделитель между повторениями.

  2. Метод действия выполняется, когда сработал TOP. make прикрепляет вычисленное значение — сумму чисел, — которое .made считывает после разбора.

  3. Token никогда не пропускает пробелы, поэтому эта грамматика строга к своему входу: '3+4+5' разбирается, а '3 + 4 + 5' — нет (.parse возвращает Nil). Чтобы принимать пробелы вокруг плюсов, сделайте TOP правилом rule — и отделите квантификатор от его атома:

    grammar Sum {
        rule TOP     { <number> + % '+' }
        token number { \d+ }
    }

    В rule пробел в шаблоне означает неявный вызов <.ws>. Записанное как <number> + % '+', с пробелом перед квантификатором +, это неявное пробельное правило покрывает всё повторение, включая разделители, — поэтому разбираются и '3+4+5', и '3 + 4 + 5', а сумма в обоих случаях равна 12. (Если вы предпочитаете остаться с token, выпишите пробелы прямо в разделителе: <number>+ % [ \s* '+' \s* ].)

Навигация по курсу

Грамматика, которая складывает   |   Собираем всё вместе