Генерация синтаксического анализатора ANTLR4: проблема с простой грамматикой для условных выражений - PullRequest
0 голосов
/ 25 апреля 2018

Я пытаюсь сгенерировать лексер и парсер для простого языка. На данный момент язык может анализировать только условное выражение. Условное выражение во многом похоже на выражение в C, и, поскольку я изучаю здесь только зачатки, все ошибки, которые есть у нас на языке, подобном C, я не буду беспокоиться о реализации.

У меня есть следующая грамматика:

grammar Simple ;

cond_expr     : left_paren operand operator operand right_paren ;
operand       : function_expr | ID | literal | cond_expr ;
function_expr : ID left_paren paramList right_paren ;
paramList     : param (',' param)* ;
param         : ID | function_expr ;
literal       : string | number ;
string        : '"' sentence '"' ;
sentence      : (WORD | WORD (' ' WORD)*)* ;
number        : INTEGER | FLOAT ;
left_paren    : LEFT_PAREN ;
right_paren   : RIGHT_PAREN ;
operator      : OPERATOR ;

INTEGER     : [0-9]+ ;
FLOAT       : INTEGER '.' INTEGER | '.' INTEGER ;
LEFT_PAREN  : '(' ;
RIGHT_PAREN : ')' ;
ID          : [A-Za-z]+[A-Za-z0-9_]* ;
WORD        : [A-Za-z]+ ;
OPERATOR    : ('==' | '>=' | '<=' | '!=' | '&&' | '||' | '~') ;
WS          : (' '|'\r'|'\n'|'\t') -> channel(HIDDEN);

И когда я запускаю на нем парсер, я не получаю ожидаемых результатов. Вот пример неправильного вывода:

~/sandbox $ grun Simple cond_expr -tree
(a (c, d (e, f)) != b)
line 1:2 mismatched input ' ' expecting OPERATOR
line 1:5 mismatched input ',' expecting OPERATOR
line 1:8 mismatched input ' ' expecting ')'
(cond_expr (left_paren () (operand a) (operator  ) (operand (cond_expr (left_paren () (operand c) (operator ,  ) (operand d) (right_paren   ( e ,   f))) (right_paren )))

В чем ошибка в моей грамматике? Любая помощь приветствуется.

1 Ответ

0 голосов
/ 25 апреля 2018

Похоже, что грамматика является прямой реализацией представления EBNF требуемого DSL.Требуется немного больше работы, чтобы заставить его хорошо работать в ANTLR.Как:

1) существует проблема взаимной рекурсии слева с правилами function_expr, paramList и param;

2) sentence ничего не может сравниться;

3) WS скрыто в лексере, поэтому sentence никогда не сможет совпадать;);

4) тени ID правила WORD, поэтому токены WORD никогда не будут выбрасываться.

(Вы должны были получить предупреждение Tool на 1 и 2; никогда не игнорировать, так как предупреждения указывают, что поведение во время выполнения может быть затронуто.)

Основная форма для выраженияправило состоит в том, чтобы перечислить в одном правиле все альтернативные формы выражения.

expr  : LPAREN expr RPAREN 
      | expr operator expr
      | function
      | string
      | number
      | ID
      ;

function  : ID LPAREN ( ID | function ) (',' ( ID | function ))* RPAREN ;

string        : STRING ;
number        : INTEGER | FLOAT ;
operator      : OPERATOR ;

STRING : '"' .*? '"' ;

(не проверено)

Таким образом, (a (c, d (e, f)) != b) должно правильно вычисляться как

expr (function ( ID, function ( ID, ID ) ) operator ID 
...