#antlr #grammar
#antlr #грамматика
Вопрос:
Я использую ANTLRWorks 1.4.2 для создания простой грамматики с целью оценки предоставленного пользователем выражения как логического результата. В конечном итоге это станет частью более масштабной грамматики, но у меня есть несколько вопросов по этому текущему фрагменту. Я хочу, чтобы пользователи могли использовать такие выражения, как:
2 > 1
2 > 1 and 3 < 1
(2 > 1 or 1 < 3) and 4 > 1
(2 > 1 or 1 < 3) and (4 > 1 or (2 < 1 and 3 > 1))
Первые два выражения допустимы в моей грамматике, но последние два — нет, и я не уверен, почему. Кроме того, ANTLRWorks, похоже, предполагает, что ввод, такой как ((((1 > 2)
с несовпадающими скобками, является законным, и я не уверен, почему. Итак, я, кажется, упускаю из виду некоторое представление о правильном способе обработки группировки в скобках в грамматике.
Как я могу изменить свою грамматику, чтобы правильно обрабатывать круглые скобки?
Моя грамматика приведена ниже:
grammar conditional_test;
boolean
: boolean_value_expression
EOF
;
boolean_value_expression
: boolean_term (OR boolean_term)*
EOF
;
boolean_term
: boolean_factor (AND boolean_factor)*
;
boolean_factor
: (NOT)? boolean_test
;
boolean_test
: predicate
;
predicate
: expression relational_operator expression
| LPAREN boolean_value_expression RPAREN
;
relational_operator
: EQ
| LT
| GT
;
expression
: NUMBER
;
LPAREN : '(';
RPAREN : ')';
NUMBER : '0'..'9' ;
EQ : '=';
GT : '>';
LT : '<';
AND : 'and';
OR : 'or' ;
NOT : 'not';
Ответ №1:
Крис Фармер написал:
Первые два выражения допустимы в моей грамматике, но последние два — нет, и я не уверен, почему. …
Вам следует удалить EOF
токен из:
boolean_value_expression
: boolean_term (OR boolean_term)*
EOF
;
Обычно вы используете только EOF
после точки входа вашей грамматики ( boolean
в вашем случае). Будьте осторожны boolean
— это зарезервированное слово в Java, и поэтому его нельзя использовать в качестве правила синтаксического анализа!
Итак, первые два правила должны выглядеть следующим образом:
bool
: boolean_value_expression
EOF
;
boolean_value_expression
: boolean_term (OR boolean_term)*
;
И вы также можете захотеть игнорировать буквенные пробелы, добавив следующее правило лексера:
SPACE : ' ' {$channel=HIDDEN;};
(вы можете включить табуляции и разрывы строк, конечно)
Теперь все входные данные вашего примера соответствуют должным образом (также протестировано с ANTLRWorks 1.4.2).
Крис Фармер написал:
Кроме того, ANTLRWorks, похоже, предполагает, что ввод, такой как ((((1 > 2) с несовпадающими скобками, является законным, …
Нет, ANTLRWorks действительно выдает ошибки, возможно, не очень заметные. Дерево синтаксического анализа, созданное ANTLRWorks, имеет NoViableAltException
вид листа, и на вкладке «Консоль» есть некоторые ошибки.
Комментарии:
1. Спасибо! Я не уверен, как туда попал этот дополнительный EOF, но это определенно сбивало с толку некоторые вещи. Спасибо, что взглянули на это. Ваши предложения отлично работают.
2. @Chris, обратите внимание, что ваша грамматика не допускает круглых скобок вокруг таких чисел, как:
1 < (2)
. Возможно, вы сделали это намеренно, но, возможно, и нет, и в этом случае вам следует перейтиLPAREN boolean_value_expression RPAREN
кexpression
правилу и изменитьpredicate
на:predicate : expression (relational_operator expression)? ;