ANTLRWorks - Генерация кода застревает и не генерирует
Я определяю грамматику для арифметических выражений, используя следующий синтаксис. Это подмножество более сложного целого, но проблемы возникали только тогда, когда я расширил грамматику, включив в нее логические операции.
Когда я пытаюсь закодировать gen с помощью antlrworks, он очень долго даже начинает генерироваться. Я думаю, что проблема в правиле для paren, так как включает в себя цикл до начала expr. Любая помощь в исправлении этого было бы здорово
заранее спасибо
используемые параметры:
options {
tokenVocab = MAliceLexer;
backtrack = true;
}
код для грамматики ниже:
type returns [ASTTypeNode n]
: NUMBER {$n = new IntegerTypeNode();}
| LETTER {$n = new CharTypeNode();}
| SENTENCE { $n = new StringTypeNode();}
;
term returns [ASTNode n]
: IDENTIFIER {$n = new IdentifierNode($IDENTIFIER.text);}
| CHAR {$n = new LetterNode($CHAR.text.charAt(1));}
| INTEGER {$n = new NumberNode(Integer.parseInt( $INTEGER.text ));}
| STRING { $n = new StringNode( $STRING.text ); }
;
paren returns [ASTNode n]
:term { $n = $term.n; }
| LPAR expr RPAR { $n = $expr.n; }
;
negation returns [ASTNode n]
:BITNEG (e = negation) {$n = new BitNotNode($e.n);}
| paren {$n = $paren.n;}
;
unary returns [ASTNode n]
:MINUS (u =unary) {$n = new NegativeNode($u.n);}
| negation {$n = $negation.n;}
;
mult returns [ASTNode n]
: unary DIV (m = mult) {$n = new DivideNode($unary.n, $m.n);}
| unary MULT (m = mult) {$n = new MultiplyNode($unary.n, $m.n);}
| unary MOD (m=mult) {$n = new ModNode($unary.n, $m.n);}
| unary {$n = $unary.n;}
;
binAS returns [ASTNode n]
: mult PLUS (b=binAS) {$n = new AdditionNode($mult.n, $b.n);}
| mult MINUS (b=binAS) {$n = new SubtractionNode($mult.n, $b.n);}
| mult {$n = $mult.n;}
;
comp returns [ASTNode n]
: binAS GREATEREQ ( e =comp) {$n = new GreaterEqlNode($binAS.n, $e.n);}
|binAS GREATER ( e = comp ) {$n = new GreaterNode($binAS.n, $e.n);}
|binAS LESS ( e = comp ) {$n = new LessNode($binAS.n, $e.n);}
|binAS LESSEQ ( e = comp ) {$n = new LessEqNode($binAS.n, $e.n);}
|binAS {$n = $binAS.n;}
;
equality returns [ASTNode n]
: comp EQUAL ( e = equality) {$n = new EqualNode($comp.n, $e.n);}
|comp NOTEQUAL ( e = equality ) {$n = new NotEqualNode($comp.n, $e.n);}
|comp { $n = $comp.n; }
;
bitAnd returns [ASTNode n]
: equality BITAND (b=bitAnd) {$n = new BitAndNode($equality.n, $b.n);}
| equality {$n = $equality.n;}
;
bitXOr returns [ASTNode n]
: bitAnd BITXOR (b = bitXOr) {$n = new BitXOrNode($bitAnd.n, $b.n);}
| bitAnd {$n = $bitAnd.n;}
;
bitOr returns [ASTNode n]
: bitXOr BITOR (e =bitOr) {$n = new BitOrNode($bitXOr.n, $e.n);}
| bitXOr {$n = $bitXOr.n;}
;
logicalAnd returns [ASTNode n]
: bitOr LOGICALAND (e = logicalAnd){ $n = new LogicalAndNode( $bitOr.n, $e.n ); }
| bitOr { $n = $bitOr.n; }
;
expr returns [ASTNode n]
: logicalAnd LOGICALOR ( e = expr ) { $n = new LogicalOrNode( $logicalAnd.n, $e.n); }
| IDENTIFIER INC {$n = new IncrementNode(new IdentifierNode($IDENTIFIER.text));}
| IDENTIFIER DEC {$n = new DecrementNode(new IdentifierNode($IDENTIFIER.text));}
| logicalAnd {$n = $logicalAnd.n;}
;
`
1 ответ
Это похоже на ошибку, появившуюся в версии 3.3 (и выше). ANTLR 3.2 выдает следующую ошибку при генерации парсера из вашей грамматики:
предупреждение (205): Test.g:31:2: ANTLR не удалось проанализировать это решение в равенстве правил; часто это происходит из-за рекурсивных ссылок на правила, видимых с левого края альтернатив. ANTLR повторно проанализирует решение с фиксированным прогнозом k=1. Подумайте об использовании "options {k=1;}" для этого решения и, возможно, добавьте синтаксический предикат. ошибка (10): внутренняя ошибка: org.antlr.tool.Grammar.createLookaheadDFA(Grammar.java:1279): не удалось даже сделать k = 1 для решения 6; причина: истекло время ожидания (>1000 мс)
Мне кажется, вы использовали грамматику LR в качестве основы для вашей грамматики ANTLR. Подумайте о том, чтобы начать сначала, но потом с разбором LL. Взгляните на следующие вопросы и ответы, чтобы узнать, как анализировать выражения с помощью ANTLR: ANTLR: Есть ли простой пример?
Кроме того, я вижу, что вы используете некоторые токены, которые очень похожи друг на друга: LETTER
, CHAR
, SENTENCE
а также IDENTIFIER
, Вы должны понимать, что если все они могут начинаться, например, со строчной буквы, то соответствует только одно из правил (то, которое соответствует большинству, или, в случае связи, то, которое определено первым в грамматике лексера), Лексер не производит токены на основе того, что "запрашивает" парсер, он создает токены независимо от парсера.
Наконец, для простого парсера выражений вам действительно не нужны предикаты (и backtrack=true
заставляет ANTLR автоматически вставлять предикаты перед всеми правилами синтаксического анализатора!).