Предположим, у нас есть входные данные, которые выглядят как последовательность простых английских операторов, каждая из которых находится на отдельной строке, например:
Alice checks
Bob bets 100
Charlie raises 100
Alice folds
Давайте попробуем разобрать его с помощью этой грамматики:
actions: action* EOF;
action: player=name (check | call | raise | fold) NEWLINE;
check: 'checks';
call: 'calls' amount;
raise: 'raises' amount;
fold: 'folds';
name: /* The subject of this question */;
amount: '$'? INT;
INT: ('0'..'9')+;
NEWLINE: '\r'? '\n';
Число различных глаголов фиксировано, но интересно то, что имя, которому мы пытаемся соответствовать, может содержать пробелы - и глаголы потенциально могут быть его частями! Таким образом, следующий ввод действителен:
Guy who always bets 100 checks
Guy who always checks bets 100
Guy who always calls folds
Guy who always folds raises 100
Guy who always checks and then raises bets by others calls $100
Итак, вопрос в следующем: как мы определяем name
, поэтому достаточно жадного, чтобы есть пробелы и слова, которые мы обычно рассматриваем как глаголы, но не супер-жадные, чтобы глаголы еще могли быть соответствует action
правило?
Моя первая попытка решить эту задачу выглядела так:
name: WORD (S WORD)*;
WORD: ('a'..'z'|'A'..'Z'|'0'..'9')+; // Yes, 1234 is a WORD, too...
S: ' '; // We have to keep spaces in names
К сожалению, это не будет соответствовать «Парню, который всегда делает ставку», поскольку bets
- это не WORD
, а другой токен, определенный литералом в правиле bets
. Я хотел обойти это путем создания правила типа keyword[String word]
и сопоставления других правил, скажем, keyword["bets"]
вместо литерала, но я застрял там. (Полагаю, я мог бы просто перечислить все свои глаголы как действительные альтернативы, чтобы быть частью name
, но это просто неправильно.)
Вот еще что: все name
объявляются до того, как они используются, поэтому я могу прочитать их, прежде чем начать синтаксический анализ action
с. И они не могут быть длиннее, чем MAX_NAME_LENGTH символов. Может ли это помочь?
Может, я все равно делаю это неправильно. Гуру ANTLR, могу ли я услышать от вас?