Предположим, у нас есть ввод, который выглядит как последовательность простых английских утверждений, каждое в отдельной строке, например:
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, могу я услышать от вас?