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

STInterpreter条件判断时变量取值为null的原因分析

基于ANTLR4的STInterpreter条件判断时变量值为null的问题

我们实现了基于ANTLR4的STInterpreter解释器类,测试代码中完成了变量x、y的赋值,随后进行x < y的条件判断。执行后输出显示赋值成功,但条件判断时出现Left: null, Right: null, Operator: <的结果,未正确执行运算。


相关代码

STInterpreter类代码

package com.jdcs.st;

import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
import java.util.HashMap;
import java.util.Map;
import com.jdcs.st.generated.*;

public class STInterpreter {
    private final Map<String, Object> symbolTable = new HashMap<>();

    public void execute(String code) {
        STLexer lexer = new STLexer(CharStreams.fromString(code));
        STParser parser = new STParser(new CommonTokenStream(lexer));
        ParseTree tree = parser.program();

        new STVisitor().visit(tree);
    }

    private class STVisitor extends STBaseVisitor<Object> {
        @Override
        public Object visitAssignment(STParser.AssignmentContext ctx) {
            String variable = ctx.IDENTIFIER().getText();
            Object value = visit(ctx.expression());

            System.out.println("Assigning " + value + " to " + variable); // 调试信息

            symbolTable.put(variable, value);

            // 打印当前符号表状态
            System.out.println("Symbol Table: " + symbolTable);
            return null;
        }

        @Override
        public Object visitLiteral(STParser.LiteralContext ctx) {
            if (ctx.INT() != null) return Integer.parseInt(ctx.INT().getText());
            if (ctx.BOOL() != null) return Boolean.parseBoolean(ctx.BOOL().getText());
            return null;
        }

        @Override
        public Object visitExpression(STParser.ExpressionContext ctx) {
            if (ctx.operator() == null) {
                return visit(ctx.literal() != null ? ctx.literal() : ctx.IDENTIFIER());
            }

            Object left = visit(ctx.expression(0));
            Object right = visit(ctx.expression(1));
            String operator = ctx.operator().getText();

            System.out.println("Left: " + left + ", Right: " + right + ", Operator: " + operator);

            return evaluate(left, right, operator);
        }

        private Object evaluate(Object left, Object right, String operator) {
            switch (operator) {
                case "+": -> {
                    return (int) left + (int) right;
                }
                case "-": -> {
                    return (int) left - (int) right;
                }
                case "*": -> {
                    return (int) left * (int) right;
                }
                case "/": -> {
                    return (int) left / (int) right;
                }
                case "=": -> {
                    return left.equals(right);
                }
                case "<": -> {
                    return (int) left < (int) right;
                }
                case ">": -> {
                    return (int) left > (int) right;
                }
            }
            throw new RuntimeException("Unsupported operator: " + operator);
        }

        @Override
        public Object visitCondition(STParser.ConditionContext ctx) {
            return visit(ctx.expression());
        }

        @Override
        public Object visitIfStatement(STParser.IfStatementContext ctx) {
            boolean condition = (boolean) visit(ctx.condition());
            if (condition) {
                ctx.statement().forEach(this::visit);
            } else if (ctx.statement().size() > 1) {
                visit(ctx.statement(1));
            }
            return null;
        }
    }
}

测试代码

STInterpreter interpreter = new STInterpreter();
String code = """
    x := 10;
    y := 20;
    IF x < y THEN
        z := x + y;
    END_IF;
""";
interpreter.execute(code);

执行输出

Assigning 10 to x
Assigning 20 to y
Left: null, Right: null, Operator: <

问题原因

核心问题是访问变量标识符时,没有从符号表中读取已赋值的变量值。

在visitExpression方法中,当表达式是单个标识符(比如x或y)时,代码调用visit(ctx.IDENTIFIER()),但STVisitor类并没有重写visitIDENTIFIER方法。而ANTLR4的STBaseVisitor默认实现中,未重写的访问方法会返回null,导致变量值无法被正确获取,最终条件判断时left和right都为null。


解决方案

在STVisitor类中添加visitIDENTIFIER方法,从符号表中读取对应变量的值:

@Override
public Object visitIDENTIFIER(STParser.IDENTIFIERContext ctx) {
    String varName = ctx.getText();
    Object value = symbolTable.get(varName);
    if (value == null) {
        throw new RuntimeException("未定义的变量: " + varName);
    }
    return value;
}

添加该方法后,当解释器访问到变量标识符节点时,会从之前赋值的symbolTable中取出对应的值,条件判断就能正确获取x=10和y=20,执行10 < 20的比较运算,进而进入IF分支执行z := x + y的赋值操作。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 19:56:00