ANTLR4 书,计算器练习

kma*_*oor 2 antlr antlr4

我对antlr 的理解停留在非常基础的层面。浏览 Parr 博士的“权威 ANTLR 4 参考”。在第 4.2 节“使用访问者构建计算器”中列出了以下语法:

\n\n
grammar LabeledExpr; // rename to distinguish from Expr.g4\n\nprog:   stat+ ;\n\nstat:   expr NEWLINE                # printExpr\n    |   ID \'=\' expr NEWLINE         # assign\n    |   NEWLINE                     # blank\n    ;\n\nexpr:   expr op=(\'*\'|\'/\') expr      # MulDiv\n    |   expr op=(\'+\'|\'-\') expr      # AddSub\n    |   INT                         # int\n    |   ID                          # id\n    |   \'(\' expr \')\'                # parens\n    ;\n\nMUL :   \'*\' ; // assigns token name to \'*\' used above in grammar\nDIV :   \'/\' ;\nADD :   \'+\' ;\nSUB :   \'-\' ;\nID  :   [a-zA-Z]+ ;      // match identifiers\nINT :   [0-9]+ ;         // match integers\nNEWLINE:\'\\r\'? \'\\n\' ;     // return newlines to parser (is end-statement signal)\nWS  :   [ \\t]+ -> skip ; // toss out whitespace\n
Run Code Online (Sandbox Code Playgroud)\n\n

我试图clear在书中添加以下声明:

\n\n

在继续之前,您可能需要花一些时间尝试通过添加语句来扩展此表达式语言clear。该clear命令应该清除memory地图,并且您\xe2\x80\x99将需要规则中的新替代方案stat来识别它。标记替代方案# clear,然后运行ANTLR语法以获得增强的访问者界面。

\n\n

这是我的尝试:

\n\n
grammar LabeledExpr;\n\nprog:   stat+ ;\n\nstat:   expr NEWLINE          # printExpr\n    |   ID \'=\' expr NEWLINE   # assign\n    |   clear NEWLINE         # clearMem\n    |   NEWLINE               # blank\n    ;\n\nexpr:   expr op=(\'*\'|\'/\') expr   # MulDiv\n    |   expr op=(\'+\'|\'-\') expr   # AddSub\n    |   INT                   # int\n    |   ID                    # id\n    |   \'(\' expr \')\'          # parens\n    ;\n\nclear:  CLEAR               \n    ;\n\nMUL:    \'*\' ;   // assigns token name to \'*\' used above in grammar\nDIV:    \'/\' ;\nADD:    \'+\' ;\nSUB:    \'-\' ;\n\nID  :   [a-zA-Z]+ ;\nINT :   [0-9]+ ;\nNEWLINE: \'\\r\'?\'\\n\' ;\nWS  :   [ \\t]+ -> skip ;\nCLEAR:  \'clear\';\n
Run Code Online (Sandbox Code Playgroud)\n\n

然而,visitClearMem永远不会被调用:

\n\n
@Override\npublic Integer visitClearMem(LabeledExprParser.ClearMemContext ctx) {\n    String text = ctx.getText();\n    if (text.equalsIgnoreCase("clear")) {\n        memory.clear();\n    }\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Sam*_*ell 5

问题在于规则CLEAR在词法分析器中的位置。由于输入clear同时匹配规则IDCLEAR,ANTLR 选择语法中第一个出现的规则。在这种情况下,输入clear变为ID.

一般来说,您希望将您语言的所有关键字放置在其他标识符的规则之前,以确保它们正确匹配。