我正在尝试使用Antlr 4设置一个简单的计算器.
I'm trying to setup a simple calculator with Antlr 4.
语法:
grammar calcGrammar; input : expression EOF; expression : MINUS expression #unaryMinusExpr | expression op=(MULTIPLY | DIVIDE) expression #multiplicationExpr | expression op=(MINUS | ADD) expression #additiveExpr | NUMBER #num ; NUMBER : [0-9]+ ; DOUBLE : NUMBER '.' NUMBER; LPAR : '('; RPAR : ')'; ADD : ('+'); MINUS : ('-'); DIVIDE : ('/'); MULTIPLY : ('*');Java代码:
public class Listener extends ListenerBaseVisitor { @Override public Object visitUnaryMinusExpr(ArithmeticGrammarParser.UnaryMinusExprContext ctx) { System.out.println(ctx.children.get(0).getText()); } @Override public Object visitAdditiveExpr(ArithmeticGrammarParser.AdditiveExprContext ctx) { System.out.println(ctx.children.get(0).getText()); System.out.println(ctx.children.get(1).getText()); }如果我的输入是2--2.输入的代码永远不会进入此方法.请注意,输入具有负一元运算符,应将其视为"-2".当我在该方法中放置调试点时,永远不会进入.
If my input is 2 - -2. The code will never go into this method with this input. Notice that the input has a negative unary operator, this should be perceived as '-2'. When i put a debug point in the method is never enters.
使用我的语法设置时,不应该总是总是考虑一进制减号吗?
With my grammar setup should it not be the case that it should always take into consideration the unary minus first?
似乎同时执行一元和令人上瘾的表达式时,会出现此错误.在这种情况下,输入'2--2'时,程序将不会进入一元方法
It seems that this error arises when both unary and addictive expressions are implemented. The program will not go into the unary method in this case with input '2 - -2'
推荐答案
使用我的语法设置时,不是应该总是先考虑一元减号吗?
With my grammar setup should it not be the case that it should always take into consideration the unary minus first?
是的,它应该(而且确实如此).
Yes, it should (and it does).
我猜您最近没有重新生成解析器和词法分析器类,因为给定您的语法(我只添加了SPACE : [ \t\r\n] -> skip;),当我运行此类时:
I'm guessing you didn't regenerate your parser and lexer classes recently, because given your grammar (I only added SPACE : [ \t\r\n] -> skip;), when I run this class:
import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTreeWalker; public class Main { static class Listener extends calcGrammarBaseListener { @Override public void enterUnaryMinusExpr(calcGrammarParser.UnaryMinusExprContext ctx) { System.out.println("enterUnaryMinusExpr: " + ctx.getText()); } @Override public void enterAdditiveExpr(calcGrammarParser.AdditiveExprContext ctx) { System.out.println("enterAdditiveExpr: " + ctx.getText()); } } public static void main(String[] args) { String source = "2 - -2"; calcGrammarLexer lexer = new calcGrammarLexer(CharStreams.fromString(source)); calcGrammarParser parser = new calcGrammarParser(new CommonTokenStream(lexer)); ParseTreeWalker.DEFAULT.walk(new Listener(), parser.input()); } }打印以下内容:
enterAdditiveExpr: 2--2 enterUnaryMinusExpr: -2对于访问者,您需要实施所有访问方法,如下所示:
For a visitor, you'll need to implement all your visit-methods like this:
import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; public class Main { static class Visitor extends calcGrammarBaseVisitor<Integer> { @Override public Integer visitInput(calcGrammarParser.InputContext ctx) { System.out.println("visitInput: " + ctx.getText()); return visit(ctx.expression()); } @Override public Integer visitUnaryMinusExpr(calcGrammarParser.UnaryMinusExprContext ctx) { System.out.println("visitUnaryMinusExpr: " + ctx.getText()); return -1 * visit(ctx.expression()); } @Override public Integer visitNum(calcGrammarParser.NumContext ctx) { System.out.println("visitNum: " + ctx.getText()); return Integer.parseInt(ctx.getText()); } @Override public Integer visitMultiplicationExpr(calcGrammarParser.MultiplicationExprContext ctx) { System.out.println("visitMultiplicationExpr: " + ctx.getText()); if (ctx.op.getType() == calcGrammarLexer.MULTIPLY) { return visit(ctx.expression(0)) * visit(ctx.expression(1)); } return visit(ctx.expression(0)) / visit(ctx.expression(1)); } @Override public Integer visitAdditiveExpr(calcGrammarParser.AdditiveExprContext ctx) { System.out.println("visitAdditiveExpr: " + ctx.getText()); if (ctx.op.getType() == calcGrammarLexer.ADD) { return visit(ctx.expression(0)) + visit(ctx.expression(1)); } return visit(ctx.expression(0)) - visit(ctx.expression(1)); } } public static void main(String[] args) { String expression = "2 - -2"; calcGrammarLexer lexer = new calcGrammarLexer(CharStreams.fromString(expression)); calcGrammarParser parser = new calcGrammarParser(new CommonTokenStream(lexer)); Integer answer = new Visitor().visit(parser.input()); System.out.printf("%s = %s\n", expression, answer); } }将打印:
visitInput: 2--2<EOF> visitAdditiveExpr: 2--2 visitNum: 2 visitUnaryMinusExpr: -2 visitNum: 2 2 - -2 = 4这是一个表达式解析器/评估器的小演示,其中包括基本循环以及使用ANTLR4 +访问者的if语句: https ://github/bkiers/Mu
Here's a small demo of an expression parser/evaluator including basic loops and if statements using ANTLR4 + a Visitor: github/bkiers/Mu
更多推荐
ANTLR 4如何处理一元/负数
发布评论