修改表达式,由 Antlr 生成? [英] Modify expressions, generated by Antlr?

查看:23
本文介绍了修改表达式,由 Antlr 生成?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用 Antlr4 读取表达式并对其进行一些修改.

I would like to read expressions with Antlr4 and the perform some modifications on them.

例如,如果语法是算术,我会修改表达式,表示

For example, if grammar is arithmetic, I would modify expression, representing

2 * (3 + 1)

2 * 4

然后用

8

这是计算"或简化".为了执行这件事,我会创建一些树结构,第一个想法是使用由 Antlr 创建的完全相同的树.

This is "calculation" or "simplification". To perform this thing I would create some tree structure and the first idea is to use the very same trees, created by Antlr.

很遗憾,我没有看到任何适合儿童的二传手.

Unfortunately, I don't see any setters for children.

如何实现?我真的应该用我自己的 Antlr 树复制表达式逻辑吗?

How to accomplish? Should I really duplicate Antlr trees with my own ones for logic of expressions?

推荐答案

解决方案

您不应复制或修改 ANTRL 树.您应该通过利用树访问者和侦听器模式使用它们.

首先,我们将为算术表达式准备简单的语法.

First we will prepare simple grammar for an arithmetic expression.

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
    ;

评估表达式

为了对表达式求值,我们将遍历解析树以执行计算或收集结果.

Evaluate expression

In order to evaluate an expression, we will traverse the parse tree to perform a calculation or to collect the result.

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 类.此工具允许轻松替换令牌.

Replace expression

In order to replace an expression with its evaluated form, we will use TokenStreamRewriter class. This tool allows for an easy substitution of tokens.

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();
    }
}

运行示例

现在我们需要执行表达式的评估和替换.

Run the example

Now we need to perform evaluation and replacement of the expressions.

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 (abstract-syntax树),并从一开始就处理 AST.

The parse tree or AST (abstract-syntax tree)

If you still need a modified parse tree you can parse the altered code again. If you would like to modify the tree structure, convert the parse tree to the AST (abstract-syntax tree), and work on the AST from the start.

这篇关于修改表达式,由 Antlr 生成?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆