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

Antlr4 Visitor代码计算结果错误,求排查运算符判断问题

解决Antlr4 Visitor算术表达式计算错误问题

Antlr4 Visitor代码运行后输出错误结果,无法定位问题。以下是简单算术表达式语法:

grammar Arithmetics;

expr : term (PLUS term | MINUS term)*;
term : factor (MULT factor | DIV factor)*;
factor : INT;

PLUS : '+';
MINUS : '-';
MULT : '*';
DIV : '/';

INT : [0-9]+;
WS : [ \t\r\n]+ -> skip;

C#代码实现:

class Program
{
    static void Main(string[] args)
    {
        string input = "1 + 2 * 3 - 8 / 4";
        var lexer = new ArithmeticsLexer(new AntlrInputStream(input));
        var tokens = new CommonTokenStream(lexer);
        var parser = new ArithmeticsParser(tokens);

        var tree = parser.expr();

        Console.WriteLine(tree.ToStringTree(parser));

        var visitor = new MyArithmeticsVisitor();
        int result = visitor.Visit(tree);

        Console.WriteLine($"Result: {result}");
    }
}

public class MyArithmeticsVisitor : ArithmeticsBaseVisitor<int>
{
    public override int VisitExpr(ArithmeticsParser.ExprContext context)
    {
        Console.WriteLine($"Expr:{context.GetText()}");
        int result = VisitTerm(context.term(0));
        for (int i = 1; i < context.term().Length; i++)
        {
            String s = context.term(i).GetText();
            Console.WriteLine($"Visiting term {s}");

            if (context.PLUS(i) != null)
                result += VisitTerm(context.term(i));
            else if (context.MINUS(i) != null)
                result -= VisitTerm(context.term(i));
        }
        return result;
    }

    public override int VisitTerm(ArithmeticsParser.TermContext context)
    {
        int result = VisitFactor(context.factor(0));
        for (int i = 1; i < context.factor().Length; i++)
        {
            if (context.MULT(i - 1) != null)
                result *= VisitFactor(context.factor(i));
            else if (context.DIV(i - 1) != null)
                result /= VisitFactor(context.factor(i));
        }
        return result;
    }

    public override int VisitFactor(ArithmeticsParser.FactorContext context)
    {
        string strFactor = context.INT().GetText();
        Console.WriteLine($"factor {strFactor}");
        return int.Parse(strFactor);
    }
}

运行输出:

(expr (term (factor 1)) + (term (factor 2) * (factor 3)) - (term (factor 8) / (factor 4)))
Expr:1+2*3-8/4
factor 1
Visiting term 2*3
Visiting term 8/4
Result: 1

问题分析

VisitExpr方法中运算符判断逻辑错误:语法规则expr : term (PLUS term | MINUS term)*生成的上下文里,PLUS()和MINUS()的数组长度等于term()数组长度减1(第一个term没有前置运算符)。原代码中用循环变量i(从1开始)去访问context.PLUS(i)或context.MINUS(i),会导致索引越界,所有运算符判断都不成立,最终结果仅保留第一个term的值。

修正后的VisitExpr方法

public override int VisitExpr(ArithmeticsParser.ExprContext context)
{
    Console.WriteLine($"Expr:{context.GetText()}");
    int result = VisitTerm(context.term(0));
    // 运算符数量等于term数量减1
    int opCount = context.term().Length - 1;
    for (int i = 0; i < opCount; i++)
    {
        var currentTerm = context.term(i + 1);
        Console.WriteLine($"Visiting term {currentTerm.GetText()}");

        // 用i作为运算符的索引,对应第i个PLUS或MINUS
        if (context.PLUS(i) != null)
        {
            result += VisitTerm(currentTerm);
        }
        else if (context.MINUS(i) != null)
        {
            result -= VisitTerm(currentTerm);
        }
    }
    return result;
}

修正后运行结果

修正后重新运行,输出结果为Result: 5,符合算术表达式1 + 2*3 - 8/4 = 1+6-2=5的预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 12:48:20