You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解析ANTLR语法中atom ((PLUS | MINUS) atom)*模式?

解析ANTLR语法中atom ((PLUS | MINUS) atom)*模式的示例

先看你提供的原语法文件:

grammar calculator;

expression: atom ((PLUS | MINUS) atom)*;

atom: '1';

PLUS: '+';

MINUS: '-';
WS: [ \r\n\t]+ -> skip;

针对你提到的atom ((PLUS | MINUS) atom)*模式,下面分别用Visitor和Listener两种模型给出具体解析实现,解决操作符与对应atom匹配的问题:


Visitor 实现(Java示例)

ANTLR生成的Visitor类中,ExpressionContext会包含所有atom的实例,以及对应的操作符节点。我们可以通过索引定位操作符,或者遍历子节点来匹配每一组操作符+atom:

import org.antlr.v4.runtime.Token;

public class CalculatorVisitorImpl extends CalculatorBaseVisitor<Integer> {

    @Override
    public Integer visitExpression(CalculatorParser.ExpressionContext ctx) {
        // 先获取第一个atom的计算值
        int result = visitAtom(ctx.atom(0));
        
        // 遍历后续所有的atom和对应的操作符
        for (int i = 1; i < ctx.atom().size(); i++) {
            // 操作符的位置:每组(op atom)占2个节点,所以第i个atom对应的操作符索引是 2*(i-1)+1
            Token opToken = ctx.getChild(2*(i-1)+1).getSymbol();
            int nextValue = visitAtom(ctx.atom(i));
            
            // 根据操作符类型计算结果
            if (opToken.getType() == CalculatorParser.PLUS) {
                result += nextValue;
            } else if (opToken.getType() == CalculatorParser.MINUS) {
                result -= nextValue;
            }
        }
        return result;
    }

    @Override
    public Integer visitAtom(CalculatorParser.AtomContext ctx) {
        // atom规则只有'1',直接返回1即可
        return 1;
    }
}

关键说明

  • ctx.atom()返回所有atom节点的列表,第一个元素是表达式开头的atom,后续元素是每个操作符后的atom。
  • 操作符节点的索引规律:因为表达式结构是atom (op atom)*,所以第一个操作符在子节点索引1的位置,第二个在3,以此类推,对应公式2*(i-1)+1(i从1开始,对应第i个后续atom)。

Listener 实现(Java示例)

Listener基于事件回调,需要维护当前计算结果和最近匹配到的操作符,通过监听操作符和atom的回调事件来完成计算:

import org.antlr.v4.runtime.Token;

public class CalculatorListenerImpl extends CalculatorBaseListener {
    private int calculationResult;
    private Token currentOperator;

    @Override
    public void enterExpression(CalculatorParser.ExpressionContext ctx) {
        // 初始化结果为第一个atom的值
        calculationResult = 1;
    }

    @Override
    public void exitPLUS(CalculatorParser.PLUSContext ctx) {
        // 匹配到加号时记录操作符
        currentOperator = ctx.getSymbol();
    }

    @Override
    public void exitMINUS(CalculatorParser.MINUSContext ctx) {
        // 匹配到减号时记录操作符
        currentOperator = ctx.getSymbol();
    }

    @Override
    public void exitAtom(CalculatorParser.AtomContext ctx) {
        // 跳过第一个atom(已经在enterExpression中初始化)
        if (ctx.getParent() instanceof CalculatorParser.ExpressionContext) {
            CalculatorParser.ExpressionContext parentCtx = (CalculatorParser.ExpressionContext) ctx.getParent();
            if (ctx != parentCtx.atom(0)) {
                int value = 1; // atom规则只有'1'
                if (currentOperator.getType() == CalculatorParser.PLUS) {
                    calculationResult += value;
                } else if (currentOperator.getType() == CalculatorParser.MINUS) {
                    calculationResult -= value;
                }
            }
        }
    }

    // 对外提供获取计算结果的方法
    public int getResult() {
        return calculationResult;
    }
}

关键说明

  • 进入expression时先初始化结果为第一个atom的值。
  • 监听PLUS和MINUS的exit事件,记录当前匹配到的操作符。
  • 每个后续atom的exit事件触发时,使用记录的操作符更新计算结果。

内容的提问来源于stack exchange,提问作者sion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 18:35:12