С учетом следующей упрощенной грамматики
grammar org.xtext.example.mydsl1.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl1/MyDsl"
Model:
(expressions+=Expression ";")*;
Expression returns Expression:
OrExpression;
OrExpression returns Expression:
PrimaryExpression ({OrExpression.left=current} name="OR" right=PrimaryExpression)*;
PrimaryExpression returns Expression:
'(' Expression ')'
| {Negation} "NOT" expr=Expression
| {IntLiteral} value=INT
| {StringLiteral} value=STRING
| {Variable} name=ID;
вход NOT x or y
может быть проанализирован двумя способами: либо как
Or(Negation(Variable("x")), Variable("y"))
, либо как
Negation(Or(Variable("x"), Variable("y")))
При компиляции грамматики Xtext он говорит вам (несколько расплывчато) с предупреждениями, например:
warning(200): ../org.xtext.example.mydsl1/src-gen/org/xtext/example/mydsl1/parser/antlr/internal/InternalMyDsl.g:195:3: Decision can match input such as "'OR'" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input
Важная часть здесь: [...]alternative(s) 2 were disabled for that input
.Таким образом, части вашей грамматики являются мертвым кодом и фактически игнорируются.
Решение: Поместите все операторы в иерархию приоритетов правильно. не помещайте что-нибудь сложное в PrimaryExpression
.Фактически ( Expression )
должно быть местом only , которое вызывает правило выше в иерархии.В результате получается бесконфликтная грамматика, подобная этой:
OrExpression returns Expression:
IsNullExpression ({OrExpression.left=current} name="OR" right=IsNullExpression)*;
IsNullExpression returns Expression:
CompareExpression ({IsNullExpression.expr=current} 'IS' not?='NOT'? 'NULL')?;
CompareExpression returns Expression:
NegationExpression ({CompareExpression.left=current} name=("NOT"| "=" | "!=") right=NegationExpression)*;
NegationExpression returns Expression:
{NegationExpression} name=("NOT" | "-") expr=PrimaryExpression
| PrimaryExpression;
PrimaryExpression returns Expression:
'(' Expression ')'
| {IntLiteral} name=INT
| {StringLiteral} name=STRING
| {Variable} name=ID;
Обратите внимание, что эта грамматика не конфликтует, несмотря на то, что несколько ключевых слов используются несколько раз в разных местах (например, NOT
, -
).