java - 如何在我的 ANTLR4 Java 扩展监听器类中实现减法表达式?
问题描述
我的任务是将使用访问者的 ANTLR4 Java 项目重新制作成使用监听器的同一个项目。我无法理解听众的工作方式。
我的访问者减法方法如下所示:
// expression '-' expression #subtractExpression
@Override
public QuickMathsValue visitSubtractExpression(SubtractExpressionContext ctx) {
QuickMathsValue lhs = this.visit(ctx.expression(0));
QuickMathsValue rhs = this.visit(ctx.expression(1));
if (lhs.isNumber() && rhs.isNumber()) {
return new QuickMathsValue(lhs.asDouble() - rhs.asDouble());
}
throw new EvalException(ctx);
}
如何制作相同的东西,但使用 Listener?如果有人有任何例子,那将是一个巨大的帮助。
解决方案
在您的侦听器中,您可以添加一个堆栈,在该堆栈上推送您的值。退出规则时,您从堆栈中弹出所需的值,然后再次将它们推回(相加或相乘或其他)。
快速演示:
表达式.g4
grammar Expression;
expression
: expression op=( MUL | DIV ) expression #expressionMul
| expression op=( ADD | MIN ) expression #expressionAdd
| '(' expression ')' #expressionNested
| NUMBER #expressionNumber
;
MUL : '*';
DIV : '/';
ADD : '+';
MIN : '-';
NUMBER : [0-9]+ ( '.' [0-9]+ )?;
SPACE : [ \t\r\n] -> skip;
主.java
public class Main {
public static void main(String[] args) {
String expression = "(1 + 2) * 14";
ExpressionLexer lexer = new ExpressionLexer(CharStreams.fromString(expression));
ExpressionParser parser = new ExpressionParser(new CommonTokenStream(lexer));
EvalListener evaluator = new EvalListener();
ParseTreeWalker.DEFAULT.walk(evaluator, parser.expression());
System.out.printf("%s = %s\n", expression, evaluator.stack.pop());
}
static class EvalListener extends ExpressionBaseListener {
final Stack<Double> stack = new Stack<>();
@Override
public void exitExpressionAdd(ExpressionParser.ExpressionAddContext ctx) {
Double rhs = stack.pop();
Double lhs = stack.pop();
this.stack.push(ctx.op.getType() == ExpressionLexer.ADD ? (lhs + rhs) : (lhs - rhs));
}
@Override
public void exitExpressionMul(ExpressionParser.ExpressionMulContext ctx) {
Double rhs = stack.pop();
Double lhs = stack.pop();
this.stack.push(ctx.op.getType() == ExpressionLexer.MUL ? (lhs * rhs) : (lhs / rhs));
}
@Override
public void enterExpressionNumber(ExpressionParser.ExpressionNumberContext ctx) {
this.stack.push(Double.valueOf(ctx.getText()));
}
}
}
运行Main
该类将产生以下输出:
(1 + 2) * 14 = 42.0
推荐阅读
- php - 为什么我不能用 composer 使用另一个 fork
- matlab - 无法加载消息目录“SimulinkCoderApp:codeperspective”。请检查文件位置和格式
- yaml - 如何在 Terraform 中使用 yaml 文件?
- windows - mongodb中的此错误“在NetworkInterface启动期间未配置TransportLayer”是什么意思?
- c# - c#中的动态绑定,我们不能使用编译数据绑定(x:bind)
- javascript - API在邮递员中工作正常,但在反应的前端部分却不行
- ios - 如何创建一个像 Apples 一样的 Popover ViewController
- javascript - 谁能告诉我为什么这没有给出任何输出?
- node.js - 如何在本机反应中从表单数据发送额外的输入值然后在后端节点js上显示
- reactjs - React Apollo 客户端未向 Apollo Server 2.0 发送 cookie 或标头