我试图用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'。当我在方法中放置一个调试点时,永远不会进入。
我的语法设置不应该是它应该始终考虑一元减去第一吗?
编辑:当实现一元和上瘾的表达时,似乎出现了这个错误。在这种情况下,程序不会使用输入' 2 - -2'
进入一元方法答案 0 :(得分:1)
我的语法设置不应该是它应该始终考虑一元减去第一个吗?
是的,应该(而且确实如此)。
我猜你最近没有重新生成你的解析器和词法分析器类,因为你给我的语法(我只添加了SPACE : [ \t\r\n] -> skip;
),当我运行这个类时:
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
对于访问者,您需要实现所有访问方法,如下所示:
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.com/bkiers/Mu