Search code examples
javaantlr

Values are not assigned in the visitLiteral, Left: null, Right: null, Operator: <


There is a code of STInterpreter class that then gets the code:

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

and for the code

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

it's getting

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

Why assigning occurs, while not processed as the correct operation?


Solution

  • What I have to change to repair that:

    @Override
    public Object visitExpression(STParser.ExpressionContext ctx) {
        if (ctx.operator() == null) {
            // If Literal
            if (ctx.literal() != null) {
                return visit(ctx.literal());
            }
            // If identifier
            if (ctx.IDENTIFIER() != null) {
                String variable = ctx.IDENTIFIER().getText();
                if (!symbolTable.containsKey(variable)) {
                    throw new RuntimeException("Variable '" + variable + "' is not defined.");
                }
                return symbolTable.get(variable);
            }
        }
    
        // If binary expression
        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);
    }