У меня есть простая грамматика:
grammar sample;
options { output = AST; }
assignment
: IDENT ':=' expr ';'
;
expr
: factor ('*' factor)*
;
factor
: primary ('+' primary)*
;
primary
: NUM
| '(' expr ')'
;
IDENT : ('a'..'z')+ ;
NUM : ('0'..'9')+ ;
WS : (' '|'\n'|'\t'|'\r')+ {$channel=HIDDEN;} ;
Теперь я хочу добавить несколько правил перезаписи для генерации AST. Из того, что я прочитал в Интернете и в книге «Языковые шаблоны», я смогу изменить грамматику следующим образом:
assignment
: IDENT ':=' expr ';' -> ^(':=' IDENT expr)
;
expr
: factor ('*' factor)* -> ^('*' factor+)
;
factor
: primary ('+' primary)* -> ^('+' primary+)
;
primary
: NUM
| '(' expr ')' -> ^(expr)
;
Но это не работает. Хотя он компилируется нормально, когда я запускаю парсер, я получаю ошибку RewriteEmptyStreamException. Вот где все становится странным.
Если я определю псевдотекены ADD и MULT и использую их вместо литералов узлов дерева, это будет работать без ошибок.
tokens { ADD; MULT; }
expr
: factor ('*' factor)* -> ^(MULT factor+)
;
factor
: primary ('+' primary)* -> ^(ADD primary+)
;
В качестве альтернативы, если я использую обозначение суффикса узла, оно также работает нормально:
expr
: factor ('*'^ factor)*
;
factor
: primary ('+'^ primary)*
;
Является ли это несоответствие в поведении ошибкой?