Что не так с этой грамматикой ANTLR? Условное утверждение вложенная скобка

Мне было поручено написать прототип DSL моей команды на Java, поэтому я решил попробовать его с помощью ANTLR. Однако у меня проблемы с правилами "выражения" и "условия".

DSL уже четко определен, поэтому я хотел бы сохранить как можно ближе к текущей спецификации.

grammar MyDSL;
// Obviously this is just a snippet of the whole language, but it should give a 
// decent view of the issue.

entry
    : condition EOF
    ;

condition
    : LPAREN condition RPAREN
    | atomic_condition
    | NOT condition
    | condition AND condition
    | condition OR condition
    ;

atomic_condition
    : expression compare_operator expression
    | expression (IS NULL | IS NOT NULL)
    | identifier
    | BOOLEAN
    ;

compare_operator
    : EQUALS
    | NEQUALS
    | GT | LT
    | GTEQUALS | LTEQUALS
    ;

expression
    : LPAREN expression RPAREN
    | atomic_expression
    | PREFIX expression
    | expression (MULTIPLY | DIVIDE) expression 
    | expression (ADD | SUBTRACT) expression
    | expression CONCATENATE expression
    ;

atomic_expression
    :  SUBSTR LPAREN expression COMMA expression (COMMA expression)? RPAREN
    | identifier
    | INTEGER
    ;

identifier
    : WORD
    ;

// Function Names
SUBSTR: 'SUBSTR';
// Control Chars
LPAREN : '(';
RPAREN : ')';
COMMA  : ',';
// Literals and Identifiers
fragment DIGIT : [0-9] ;
INTEGER: DIGIT+;
fragment LETTER : [A-Za-z@$#];
fragment CHARACTER : DIGIT | LETTER | '_';
WORD: LETTER CHARACTER*;
BOOLEAN: 'TRUE' | 'FALSE';
// Arithmetic Operators
MULTIPLY : '*';
DIVIDE   : '/';
ADD      : '+';
SUBTRACT : '-';
PREFIX: ADD| SUBTRACT ;
// String Operators
CONCATENATE : '||';
// Comparison Operators
EQUALS   : '==';
NEQUALS  : '<>';
GTEQUALS : '>=';
LTEQUALS : '<=';
GT       : '>';
LT       : '<';
// Logical Operators
NOT : 'NOT';
AND : 'AND';
OR  : 'OR';
// Keywords
IS  : 'IS';
NULL: 'NULL';
// Whitespace
BLANK: [ \t\n\r]+ -> channel(HIDDEN) ;

Фраза, с которой я тестирую

(FOO == 115 AND (SUBSTR(BAR,2,1) == 1 OR SUBSTR(BAR,4,1) == 1))

Однако он разбивается на вложенные скобки, сопоставляя первое (с первым) вместо внешнего (см. Ниже). В ANTLR3 я решил эту проблему с помощью семантических предикатов, но кажется, что ANTLR4 должен был устранить необходимость в них.

ANTLRWorks Parse tree

Я бы очень хотел сохранить condition и expression правила раздельные, если это вообще возможно. Я смог заставить его работать, когда объединены в одном expression правила (на основе примеров здесь и в других местах), но в текущей спецификации DSL они различны, и я пытаюсь уменьшить возможные различия в поведении.
Может кто-нибудь указать, как я могу заставить все это работать, сохраняя отдельное правило для conditions' andexpressions`? Большое спасибо!

1 ответ

Решение

Грамматика мне кажется хорошей.

В лексере есть одна проблема: WORD токен определяется перед различными ключевыми словами / операторами, в результате чего он получает приоритет над ними. Поместите свой WORD править в самом конце ваших правил лексера (или, по крайней мере, после последних ключевых слов, которые WORD также может соответствовать).

Другие вопросы по тегам