Solution
您不应复制或修改 ANTRL 树。你应该USE通过利用树访问者和侦听器模式来实现它们。
语法
首先,我们将为算术表达式准备简单的语法。
grammar expr;
WS : [ \t\r\n] -> skip;
INT : [0-9]+;
program
: expr # baseExpr
;
expr
: '(' expr ')' # exprParentheses
| left=expr '*' right=expr # exprMul
| left=expr '+' right=expr # exprAdd
| INT # exprINT
;
评估表达
为了计算表达式,我们将遍历解析树来执行计算或收集结果。
public class EvaluateExpr extends exprBaseVisitor<Integer> {
@Override
public Integer visitExprINT(exprParser.ExprINTContext ctx) {
return Integer.valueOf(ctx.INT().getText());
}
@Override
public Integer visitExprMul(exprParser.ExprMulContext ctx) {
Integer left = visit(ctx.left);
Integer right = visit(ctx.right);
return left * right;
}
@Override
public Integer visitExprAdd(exprParser.ExprAddContext ctx) {
Integer left = visit(ctx.left);
Integer right = visit(ctx.right);
return left + right;
}
@Override
public Integer visitExprParentheses(exprParser.ExprParenthesesContext ctx) {
return visit(ctx.expr());
}
}
替换表达式
为了用其计算形式替换表达式,我们将使用TokenStreamRewriter
班级。该工具可以轻松替换代币。
public class ReplaceExpr extends exprBaseListener {
private TokenStreamRewriter rewriter;
public ReplaceExpr(CommonTokenStream tokens) {
rewriter = new TokenStreamRewriter(tokens);
}
@Override
public void enterBaseExpr(exprParser.BaseExprContext ctx) {
rewriter.replace(ctx.start, ctx.stop, new EvaluateExpr().visit(ctx));
}
public String getReplacedCode() {
return rewriter.getText();
}
}
运行示例
现在我们需要执行表达式的求值和替换。
exprLexer lexer = new exprLexer(new ANTLRInputStream("2 * (3 + 1)"));
CommonTokenStream tokens = new CommonTokenStream(lexer);
exprParser parser = new exprParser(tokens);
ReplaceExpr replaceExpr = new ReplaceExpr(tokens);
ParseTreeWalker.DEFAULT.walk(replaceExpr, parser.program());
System.out.println("Replaced code: " + replaceExpr.getReplacedCode());
解析树或 AST(抽象语法树)
如果您仍然需要修改后的解析树,您可以再次解析更改后的代码。
如果您想修改树结构,请将解析树转换为AST https://www.wikiwand.com/en/Abstract_syntax_tree(抽象语法树),并致力于AST https://www.wikiwand.com/en/Abstract_syntax_tree从头开始。