Я пытаюсь создать программу, которая может вычислять цепочки бросков костей (используя формат n d n , поэтому 2d8 будет бросать две 8-сторонние кости и суммировать их ). Я работаю в Java, но это не имеет значения для этого вопроса. У меня нет большого опыта работы с контекстно-независимыми грамматиками, и у меня есть несколько вопросов о том, как их создать.
Я знаю, что мне нужны элементы (токены):
- Числа
- Операторы сложения (+, -)
- Операторы умножения (*, /)
- оператор «игральных костей» (d)
- Модификаторы броска (kh, kl, dh, dl)
Модификаторы броска:
- kh: сохранение наивысшего n кубика. 4d6kh1 сохранит наивысший бросок, 4d6kh2 сохранит два самых высоких броска и т. Д.
- kl: оставить наивысший n dice
- dh: выпадать наивысший n dice
- dl: drop младший n dice
Эти модификаторы состоят из двух символов каждый, которым предшествует последовательность оператора кости (число d) и затем число (количество оставшихся рулонов).
Возможные значения:
- 4d4
- 3d6 + 2d4
- 2 * (1d6 + 8)
- 4 * 1d20 + 2
- 2d20dl1
- 4d20kh2 + 3d8
Моя попытка создать грамматику ( EBNF):
expr = term (addop factor)*
term = factor (mulop factor)*
diceop = <number> 'd' <number>
dicemod = diceop dmod <number>
factor = <number> | ( expr ) | diceop
dmod = kl | kh | dl | dh
addop = + | -
mulop = * | /
где <number>
- любое число
У меня есть несколько вопросов по этому поводу:
- Это сделано / заказано каким-либо образом возможно реализовать?
- как мне указать, что в
dicemod
число должно быть меньше или равно первому числу в члене diceop
? Я просто делаю это в коде? - нужно ли мне правило выше
expr
(что означает, что первый токен на любом входе имеет тип expr
) или мне нужно что-то выше этого?
Если это поможет, то вот как у меня есть классы для пакета AST на данный момент:
[abstract class] Node, extended by:
[abstract class] Expr, extended by:
[class] Number (0-9)
[class] BinOp (+, -, *, /)
[class] DiceOp (Number 'd' Number)
[class] DiceMod (dl, dh, kl, kh)
Где DiceOp
должен предшествовать токен Number
за которым следует маркер Number
; и DiceMod
должен предшествовать токен DiceOp
, за которым следует токен Number
, который является <= первым <code>Number токеном, удерживаемым токеном DiceOp
(как дочерний элемент токена).
Я новичок в грамматике и переводчиках в целом, поэтому приветствую любую помощь.