Просто переписать шаблон antlr
Я абсолютно новичок в antlr. Я пытаюсь использовать antlr для некоторого языкового перевода. Я думаю, что я использую правильный синтаксис, но я получил исключение.
Следующее является частью грамматики:
primary
: parExpression
| 'this' ('.' Identifier)* identifierSuffix?
| 'super' superSuffix
| literal
| 'new' creator
| Identifier ('.' Identifier)* identifierSuffix?
| primitiveType ('[' ']')* '.' 'class'
| 'void' '.' 'class'
;
Я добавил правило перезаписи, например
| 'new' creator -> 'mynew' creator
Исключение происходит:
[11:11:48] error(100): rjava_new_rewrite.g:851:26: syntax error: antlr: NoViableAltException(58@[921:1: rewrite_alternative options {k=1; } : ({...}? => rewrite_template | {...}? => ( rewrite_element )+ -> {!stream_rewrite_element.hasNext()}? ^( ALT[LT(1),"ALT"] EPSILON["epsilon"] EOA["<end-of-alt>"] ) -> ^( ALT[LT(1),"ALT"] ( rewrite_element )+ EOA["<end-of-alt>"] ) | -> ^( ALT[LT(1),"ALT"] EPSILON["epsilon"] EOA["<end-of-alt>"] ) | {...}? ETC );])
[11:11:48] error(100): rjava_new_rewrite.g:851:34: syntax error: antlr: MissingTokenException(inserted [@-1,0:0='<missing SEMI>',<52>,851:33] at creator)
[11:11:48] error(100): rjava_new_rewrite.g:852:5: syntax error: antlr: MissingTokenException(inserted [@-1,0:0='<missing COLON>',<54>,852:4] at |)
[11:11:48] error(100): rjava_new_rewrite.g:0:1: syntax error: assign.types: MismatchedTreeNodeException(0!=3)
[11:11:48] error(100): rjava_new_rewrite.g:0:1: syntax error: assign.types: MismatchedTreeNodeException(3!=28)
[11:11:48] error(100): rjava_new_rewrite.g:0:1: syntax error: assign.types: MismatchedTreeNodeException(3!=27)
[11:11:48] java.util.NoSuchElementException: can't look backwards more than one token in this stream
at org.antlr.runtime.misc.LookaheadStream.LB(LookaheadStream.java:159)
at org.antlr.runtime.misc.LookaheadStream.LT(LookaheadStream.java:120)
at org.antlr.runtime.RecognitionException.extractInformationFromTreeNodeStream(RecognitionException.java:144)
at org.antlr.runtime.RecognitionException.<init>(RecognitionException.java:111)
at org.antlr.runtime.MismatchedTreeNodeException.<init>(MismatchedTreeNodeException.java:42)
at org.antlr.runtime.tree.TreeParser.recoverFromMismatchedToken(TreeParser.java:135)
at org.antlr.runtime.BaseRecognizer.match(BaseRecognizer.java:115)
at org.antlr.grammar.v3.AssignTokenTypesWalker.grammar_(AssignTokenTypesWalker.java:388)
at org.antlr.tool.CompositeGrammar.assignTokenTypes(CompositeGrammar.java:337)
at org.antlr.tool.Grammar.setGrammarContent(Grammar.java:605)
at org.antlr.works.grammar.antlr.ANTLRGrammarEngineImpl.createNewGrammar(ANTLRGrammarEngineImpl.java:192)
at org.antlr.works.grammar.antlr.ANTLRGrammarEngineImpl.createParserGrammar(ANTLRGrammarEngineImpl.java:225)
at org.antlr.works.grammar.antlr.ANTLRGrammarEngineImpl.createCombinedGrammar(ANTLRGrammarEngineImpl.java:203)
at org.antlr.works.grammar.antlr.ANTLRGrammarEngineImpl.createGrammars(ANTLRGrammarEngineImpl.java:165)
at org.antlr.works.grammar.engine.GrammarEngineImpl.getGrammarLanguage(GrammarEngineImpl.java:115)
at org.antlr.works.components.GrammarWindowMenu.getEditTestRigTitle(GrammarWindowMenu.java:244)
at org.antlr.works.components.GrammarWindowMenu.menuItemState(GrammarWindowMenu.java:529)
at org.antlr.works.components.GrammarWindow.menuItemState(GrammarWindow.java:440)
at org.antlr.xjlib.appkit.menu.XJMainMenuBar.refreshMenuItemState(XJMainMenuBar.java:175)
at org.antlr.xjlib.appkit.menu.XJMainMenuBar.refreshMenuState(XJMainMenuBar.java:169)
at org.antlr.xjlib.appkit.menu.XJMainMenuBar.refreshState(XJMainMenuBar.java:153)
at org.antlr.xjlib.appkit.menu.XJMainMenuBar.refresh(XJMainMenuBar.java:145)
at org.antlr.works.grammar.decisiondfa.DecisionDFAEngine.refreshMenu(DecisionDFAEngine.java:203)
at org.antlr.works.components.GrammarWindow.afterParseOperations(GrammarWindow.java:1179)
at org.antlr.works.components.GrammarWindow.access$200(GrammarWindow.java:96)
at org.antlr.works.components.GrammarWindow$AfterParseOperations.threadRun(GrammarWindow.java:1553)
at org.antlr.works.ate.syntax.misc.ATEThread.run(ATEThread.java:152)
at java.lang.Thread.run(Thread.java:680)
Кто-нибудь может дать какую-нибудь идею?
1 ответ
Qinsoon написал (а):
Я думаю, что я использую правильный синтаксис, но я получил исключение.
Ты подумал неправильно.:)
Вы не можете поместить в правило перезаписи вещи, которые не были сопоставлены синтаксическим анализатором. Итак, в вашем случае:
| 'new' creator -> 'mynew' creator
'mynew'
неверно, потому что парсер никогда не сталкивался с таким токеном / правилом. Если вы хотите вставить токены в свой AST, с которым парсер не сталкивался (в ANTLR они называются воображаемыми токенами), вам нужно определить их в tokens {...}
вашей грамматики, вот так:
grammar YourGrammarName;
options {
output=AST;
}
tokens {
MYNEW;
}
primary
: ...
| 'new' creator -> ^(MYNEW creator)
| ...
;
Это вставит узел с типом MYNEW
и внутренний текст "MYNEW"
, Если вы хотите связать некоторый пользовательский текст в узле, сделайте это так:
primary
: ...
| 'new' creator -> ^(MYNEW["mynew"] creator)
| ...
;
Как видно из вышесказанного, я создал AST, где корневой узел MYNEW
, Если я сделаю:
| 'new' creator -> MYNEW creator
ANTLR вернет 2 узла из этого правила. У вас будут проблемы, если это правило когда-нибудь станет корнем другого (под) дерева: в конце концов, вы можете получить AST с двумя корнями! Всегда старайтесь, чтобы правила перезаписи создавали один AST/ узел:
rule
: subrule ';' -> subrule // omit the semi-colon
;
или когда нужно создать больше узлов, создайте правильный AST с одним корневым узлом:
rule
: AToken subrule1 subrule2 ';' -> ^(AToken subrule1 subrule2) // AToken is the root
;