Почему моя грамматика работает для операторов типа *, -, /, но не +?

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

Вот связанная часть моей грамматики:

SUBTRACT: '-';
PLUS: '+';
DIVIDE: '/';
MULTIPLY: '*';

expr: 
      (
        IDENTIFIER 
        | INTEGER 
        | STRING 
        | TRUE 
        | FALSE
      )
      (
        PLUS expr 
        | SUBTRACT expr 
        | MULTIPLY expr 
        | DIVIDE expr 
        | LESS_THAN expr 
        | LESS_THAN_OR_EQUAL expr 
        | EQUALS expr
      )*
      ;

INTEGER: ('0'..'9')*;
IDENTIFIER: ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '0'..'9' | '_')*;

Затем, когда я пытаюсь сделать что-то вроде

x*1

Это отлично работает. Однако, когда я пытаюсь сделать что-то вроде

x+1

Я получаю сообщение об ошибке:

MismatchedTokenException: несоответствующий ввод '+' ожидающий '\u001C'

Я занимался этим некоторое время, но не понимаю, почему это работает с *, - и /, но не +. У меня точно такой же код для всех них.

Редактировать: если я переупорядочу его и поставлю SUBTRACT выше PLUS, символ + теперь будет работать, но символ - не будет. Почему Antlr беспокоиться о порядке вещей такого рода?

2 ответа

Избегание левой рекурсии (в грамматике выражения) обычно выполняется следующим образом:

grammar Expr;

parse
  :  expr EOF
  ;

expr
  :  equalityExpr
  ;

equalityExpr
  :  relationalExpr (('==' | '!=') relationalExpr)*
  ;

relationalExpr
  :  additionExpr (('>=' | '<=' | '>' | '<') additionExpr)*
  ;

additionExpr
  :  multiplyExpr (('+'| '-') multiplyExpr)*
  ;

multiplyExpr
  :  atom (('*' | '/') atom)*
  ;

atom
  :  IDENTIFIER
  |  INTEGER
  |  STRING
  |  TRUE
  |  FALSE
  |  '(' expr ')'
  ;

// ... lexer rules ...

Например, вход A+B+C будет проанализирован следующим образом:

Также посмотрите этот связанный ответ: ANTLR: Есть простой пример?

Я исправил это, сделав новое правило для части в конце, которое я сделал из удаления левой рекурсии:

expr: 
      (
        IDENTIFIER 
        | INTEGER 
        | STRING 
        | TRUE 
        | FALSE
      ) lr*
      ;

lr:         PLUS expr 
        | SUBTRACT expr 
        | MULTIPLY expr 
        | DIVIDE expr 
        | LESS_THAN expr 
        | LESS_THAN_OR_EQUAL expr 
        | EQUALS expr;
Другие вопросы по тегам