ANTLR предупреждает множественные альтернативы, как это понять и как от этого избавиться?
Другие эксперты ANTLR, не могли бы вы объяснить, почему это предупреждение появляется в ANTLWorks? Как понять это сообщение и как избавиться от него в данном конкретном случае?
Пример правильного ввода: abc "xyz def" abc следует распознавать как токен keywordExpr, а "xyz def" - как фразу Expr.
[14:32:24] предупреждение (200): TestExpr.g:12:4: решение может соответствовать входным данным, таким как "CHAR", используя несколько альтернатив: 1, 2
В результате альтернатива (ы) 2 были отключены для этого ввода [14:32:24] предупреждение (200): / Users / imochurad /Development/antlr3/Grammars/TestExpr.g:12:4: решение может соответствовать такому вводу в качестве "CHAR" используется несколько альтернатив: 1, 2
В результате альтернатива (ы) 2 были отключены для этого ввода
grammar TestExpr;
options {
output=AST;
ASTLabelType=CommonTree;
}
expr
: kpExpr*;
kpExpr : keywordExpr|phraseExpr;
keywordExpr
: CHAR+;
phraseExpr
: '"' CHAR+ (' ' CHAR+)* '"';
CHAR : ('A'..'Z') | ('a'..'z');
INT : '0'..'9'+;
NEWLINE : '\r'? '\n';
WS : (' '|'\t'|'\n'|'\r')+ {skip();};
Большое спасибо!
1 ответ
Как написано, ваша грамматика неоднозначна при разборе строк без кавычек. ABC может быть проанализирован как один keywordExpr
(abc) или три (a, b и c) или даже два. Я думаю, вы ожидаете, что ключевые слова будут разделены пробелами. Однако, поскольку вы пропускаете пробелы в лексере, парсер не может определить разницу между abc
а также a b c
,
Я подозреваю что keywordExpr
а также phraseExpr
Должны быть правила лексера:
KeywordExpr: CHAR+;
PhraseExpr: '"' CHAR+ (' ' CHAR+)* '"';
CHAR
должно также стать фрагментом, чтобы случайно не генерировать CHAR
маркер, когда у вас есть одно ключевое слово.
С этим изменением abc становится недвусмысленным в лексере, так как лексер будет использовать максимально возможное совпадение.
Относительно того, чтобы пробелы обрабатывались по-разному, это работает лучше всего, если это делается в лексере. Приведенное выше правило для PhraseExpr будет правильно обрабатывать пробел, поскольку, когда лексер встречает его, он не может соответствовать WS
править. Обработка в парсере намного сложнее.