← index
MXVM/src/frontend/parser.cpp
Source: MXVM/src/frontend/parser.cpp
#include "parser.hpp"
#include <algorithm>
#include <cctype>
#include <set>

namespace pascal {

    void PascalParser::error(const std::string &message) {
        throw ParseException("Parse error: " + message + (token ? " at '" + token->getTokenValue() + "'" : " at end of input"));
    }

    void PascalParser::expectToken(const std::string &expected) {
        if (!peekIs(expected))
            error("Expected '" + expected + "'" + " on Line: " + std::to_string(token->getLine()));
    }

    void PascalParser::expectToken(types::TokenType expected) {
        if (!peekIs(expected))
            error("Expected " + tokenTypeToString(expected));
    }

    std::unique_ptr<ProgramNode> PascalParser::parseProgram() {
        expectToken("program");
        int lineNum = token->getLine();
        next();
        expectToken(types::TokenType::TT_ID);
        std::string programName = token->getTokenValue();
        next();
        expectToken(";");
        next();
        auto block = parseBlock();
        expectToken(".");
        auto programNode = std::make_unique<ProgramNode>(programName, std::move(block));
        programNode->setLineNumber(lineNum);
        return programNode;
    }

    bool PascalParser::match(const std::string &s) {
        if (peekIs(s)) {
            next();
            return true;
        }
        return false;
    }

    bool PascalParser::match(types::TokenType t) {
        if (peekIs(t)) {
            next();
            return true;
        }
        return false;
    }

    std::unique_ptr<BlockNode> PascalParser::parseBlock() {
        int lineNum = token ? token->getLine() : 1;
        auto declarations = parseDeclarations();
        auto compoundStatement = parseCompoundStatement();
        auto blockNode = std::make_unique<BlockNode>(std::move(declarations), std::move(compoundStatement));
        blockNode->setLineNumber(lineNum);
        return blockNode;
    }

    bool PascalParser::isKeyword(const std::string &tok) {
        std::string lower = tok;
        std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
        return lower == "program" || lower == "var" || lower == "begin" || lower == "end" ||
               lower == "if" || lower == "then" || lower == "else" || lower == "while" ||
               lower == "do" || lower == "for" || lower == "to" || lower == "downto" ||
               lower == "procedure" || lower == "function" || lower == "integer" ||
               lower == "real" || lower == "boolean" || lower == "string" || lower == "char" ||
               lower == "true" || lower == "false" || lower == "div" || lower == "mod" ||
               lower == "and" || lower == "or" || lower == "not" ||
               lower == "case" || lower == "of" || lower == "repeat" || lower == "until" ||
               lower == "array" || lower == "type" || lower == "record" || lower == "exit" || lower == "break" || lower == "continue";
    }

    std::unique_ptr<ASTNode> PascalParser::parseProcedureDeclaration() {
        expectToken("procedure");
        int lineNum = token->getLine();
        next();
        expectToken(types::TokenType::TT_ID);
        std::string procName = token->getTokenValue();
        next();
        std::vector<std::unique_ptr<ASTNode>> parameters;
        if (peekIs("(")) {
            next();
            parameters = parseParameterList();
            expectToken(")");
            next();
        }
        expectToken(";");
        next();
        auto block = parseBlock();
        expectToken(";");
        next();
        auto procDeclNode = std::make_unique<ProcDeclNode>(procName, std::move(parameters), std::move(block));
        procDeclNode->setLineNumber(lineNum);
        return procDeclNode;
    }

    std::unique_ptr<ASTNode> PascalParser::parseFunctionDeclaration() {
        expectToken("function");
        int lineNum = token->getLine();
        next();
        expectToken(types::TokenType::TT_ID);
        std::string funcName = token->getTokenValue();
        next();

        std::vector<std::unique_ptr<ASTNode>> parameters;
        if (peekIs("(")) {
            next();
            parameters = parseParameterList();
            expectToken(")");
            next();
        }

        expectToken(":");
        next();

        expectToken(types::TokenType::TT_ID);
        std::string returnType = token->getTokenValue();
        next();

        expectToken(";");
        next();

        auto block = parseBlock();

        expectToken(";");
        next();

        auto funcDeclNode = std::make_unique<FuncDeclNode>(
            funcName, std::move(parameters), returnType, std::move(block));
        funcDeclNode->setLineNumber(lineNum);
        return funcDeclNode;
    }

    std::vector<std::unique_ptr<ASTNode>> PascalParser::parseParameterList() {
        std::vector<std::unique_ptr<ASTNode>> parameters;
        if (!peekIs(")")) {
            parameters.push_back(parseParameter());
            while (peekIs(";")) {
                next();
                parameters.push_back(parseParameter());
            }
        }
        return parameters;
    }

    std::unique_ptr<ASTNode> PascalParser::parseParameter() {
        int lineNum = token ? token->getLine() : 1;
        bool isVar = false;
        if (peekIs("var")) {
            isVar = true;
            next();
        }

        std::vector<std::string> identifiers;
        expectToken(types::TokenType::TT_ID);
        identifiers.push_back(token->getTokenValue());
        next();
        while (peekIs(",")) {
            next();
            expectToken(types::TokenType::TT_ID);
            identifiers.push_back(token->getTokenValue());
            next();
        }

        expectToken(":");
        next();

        expectToken(types::TokenType::TT_ID);
        std::string typeName = token->getTokenValue();
        next();

        auto parameterNode = std::make_unique<ParameterNode>(
            std::move(identifiers), typeName, isVar);
        parameterNode->setLineNumber(lineNum);
        return parameterNode;
    }

    std::unique_ptr<CompoundStmtNode> PascalParser::parseCompoundStatement() {
        int lineNum = token ? token->getLine() : 1;
        expectToken("begin");
        next();
        auto statements = parseStatementList();
        expectToken("end");
        next();
        auto compoundNode = std::make_unique<CompoundStmtNode>(std::move(statements));
        compoundNode->setLineNumber(lineNum);
        return compoundNode;
    }

    std::unique_ptr<ASTNode> PascalParser::parseStatement() {
        if (!token) {
            auto emptyNode = std::make_unique<EmptyStmtNode>();
            emptyNode->setLineNumber(1);
            return emptyNode;
        }
        if (peekIs("exit")) {
            int lineNum = token->getLine();
            next();
            std::unique_ptr<ASTNode> expr;
            if (peekIs("(")) {
                next();
                expr = parseExpression();
                expectToken(")");
                next();
            } else if (!peekIs(";")) {
                expr = parseExpression();
            }
            expectToken(";");
            auto exitNode = std::make_unique<ExitNode>(std::move(expr));
            exitNode->setLineNumber(lineNum);
            return exitNode;
        } else if (peekIs("break")) {
            int lineNum = token->getLine();
            next();
            expectToken(";");
            auto breakNode = std::make_unique<BreakNode>();
            breakNode->setLineNumber(lineNum);
            return breakNode;
        } else if (peekIs("continue")) {
            int lineNum = token->getLine();
            next();
            expectToken(";");
            auto continueNode = std::make_unique<ContinueNode>();
            continueNode->setLineNumber(lineNum);
            return continueNode;
        } else if (peekIs("begin")) {
            return parseCompoundStatement();
        } else if (peekIs("if")) {
            return parseIfStatement();
        } else if (peekIs("while")) {
            return parseWhileStatement();
        } else if (peekIs("for")) {
            return parseForStatement();
        } else if (peekIs("repeat")) {
            return parseRepeatStatement();
        } else if (peekIs("case")) {
            return parseCaseStatement();
        } else if (peekIs(types::TokenType::TT_ID)) {
            auto lhs = parseLValue();
            int lineNum = token ? token->getLine() : 1;
            if (peekIs(":=")) {
                next();
                auto rhs = parseExpression();
                auto assignmentNode = std::make_unique<AssignmentNode>(std::move(lhs), std::move(rhs));
                assignmentNode->setLineNumber(lineNum);
                return assignmentNode;
            }
            if (auto varNode = dynamic_cast<VariableNode *>(lhs.get())) {
                if (peekIs("(")) {
                    return parseProcedureCall(varNode->name);
                }
                return lhs;
            }
            error("Invalid statement: expected ':=' for assignment or '(' for procedure call");
            return nullptr;
        } else {
            auto emptyNode = std::make_unique<EmptyStmtNode>();
            emptyNode->setLineNumber(token ? token->getLine() : 1);
            return emptyNode;
        }
    }

    std::unique_ptr<ASTNode> PascalParser::parseAssignmentOrProcCall() {
        expectToken(types::TokenType::TT_ID);
        std::string name = token->getTokenValue();
        int lineNum = token->getLine();
        next();
        if (peekIs(":=")) {
            next();
            auto variable = std::make_unique<VariableNode>(name);
            variable->setLineNumber(lineNum);
            auto expression = parseExpression();
            auto assignmentNode = std::make_unique<AssignmentNode>(std::move(variable), std::move(expression));
            assignmentNode->setLineNumber(lineNum);
            return assignmentNode;
        } else {
            return parseProcedureCall(name);
        }
    }

    std::unique_ptr<ASTNode> PascalParser::parseIfStatement() {
        expectToken("if");
        int lineNum = token->getLine();
        next();
        auto condition = parseExpression();
        expectToken("then");
        next();
        auto thenStatement = parseStatement();
        std::unique_ptr<ASTNode> elseStatement = nullptr;
        if (peekIs("else")) {
            next();
            elseStatement = parseStatement();
        }
        auto ifStmtNode = std::make_unique<IfStmtNode>(std::move(condition), std::move(thenStatement), std::move(elseStatement));
        ifStmtNode->setLineNumber(lineNum);
        return ifStmtNode;
    }

    std::unique_ptr<ASTNode> PascalParser::parseWhileStatement() {
        expectToken("while");
        int lineNum = token->getLine();
        next();
        auto condition = parseExpression();
        expectToken("do");
        next();
        auto statement = parseStatement();
        auto whileStmtNode = std::make_unique<WhileStmtNode>(std::move(condition), std::move(statement));
        whileStmtNode->setLineNumber(lineNum);
        return whileStmtNode;
    }

    std::unique_ptr<ASTNode> PascalParser::parseForStatement() {
        expectToken("for");
        int lineNum = token->getLine();
        next();
        expectToken(types::TokenType::TT_ID);
        std::string variable = token->getTokenValue();
        next();
        expectToken(":=");
        next();
        auto startValue = parseExpression();
        bool isDownto = false;
        if (peekIs("to")) {
            next();
        } else if (peekIs("downto")) {
            isDownto = true;
            next();
        } else {
            error("Expected 'to' or 'downto' in for loop");
        }
        auto endValue = parseExpression();
        expectToken("do");
        next();
        auto statement = parseStatement();
        auto forStmtNode = std::make_unique<ForStmtNode>(variable, std::move(startValue), std::move(endValue), isDownto, std::move(statement));
        forStmtNode->setLineNumber(lineNum);
        return forStmtNode;
    }

    std::unique_ptr<ASTNode> PascalParser::parseRepeatStatement() {
        expectToken("repeat");
        int lineNum = token->getLine();
        next();
        std::vector<std::unique_ptr<ASTNode>> statements;
        while (!peekIs("until")) {
            statements.push_back(parseStatement());
            if (peekIs(";")) {
                next();
            } else if (!peekIs("until")) {
                error("Expected ';' or 'until'");
            }
        }
        expectToken("until");
        next();
        auto condition = parseExpression();
        auto repeatStmtNode = std::make_unique<RepeatStmtNode>(std::move(statements), std::move(condition));
        repeatStmtNode->setLineNumber(lineNum);
        return repeatStmtNode;
    }

    std::unique_ptr<ASTNode> PascalParser::parseExpression() {
        int lineNum = token ? token->getLine() : 1;
        auto left = parseSimpleExpression();
        if (isRelationalOperator()) {
            std::string op = getRelationalOp();
            next();
            auto right = parseSimpleExpression();
            BinaryOpNode::OpType enumOp = BinaryOpNode::EQUAL;
            if (op == "=")
                enumOp = BinaryOpNode::EQUAL;
            else if (op == "<>")
                enumOp = BinaryOpNode::NOT_EQUAL;
            else if (op == "<")
                enumOp = BinaryOpNode::LESS;
            else if (op == "<=")
                enumOp = BinaryOpNode::LESS_EQUAL;
            else if (op == ">")
                enumOp = BinaryOpNode::GREATER;
            else if (op == ">=")
                enumOp = BinaryOpNode::GREATER_EQUAL;
            left = std::make_unique<BinaryOpNode>(std::move(left), enumOp, std::move(right));
            left->setLineNumber(lineNum);
        }
        while (peekIs("and") || peekIs("or")) {
            BinaryOpNode::OpType op;
            if (peekIs("and")) {
                op = BinaryOpNode::AND;
                next();
            } else {
                op = BinaryOpNode::OR;
                next();
            }
            auto right = parseSimpleExpression();
            left = std::make_unique<BinaryOpNode>(std::move(left), op, std::move(right));
            left->setLineNumber(lineNum);
        }
        return left;
    }

    std::unique_ptr<ASTNode> PascalParser::parseSimpleExpression() {
        std::unique_ptr<ASTNode> result;
        int lineNum = token ? token->getLine() : 1;
        if (peekIs("+") || peekIs("-") || peekIs("not")) {
            UnaryOpNode::Operator op = UnaryOpNode::PLUS;
            if (peekIs("+"))
                op = UnaryOpNode::PLUS;
            else if (peekIs("-"))
                op = UnaryOpNode::MINUS;
            else if (peekIs("not"))
                op = UnaryOpNode::NOT;
            next();
            auto operand = parseTerm();
            result = std::make_unique<UnaryOpNode>(op, std::move(operand));
            result->setLineNumber(lineNum);
        } else {
            result = parseTerm();
        }
        while (peekIs("+") || peekIs("-")) {
            BinaryOpNode::OpType op;
            if (peekIs("+"))
                op = BinaryOpNode::PLUS;
            else
                op = BinaryOpNode::MINUS;
            next();
            auto right = parseTerm();
            result = std::make_unique<BinaryOpNode>(std::move(result), op, std::move(right));
            result->setLineNumber(lineNum);
        }
        return result;
    }

    std::unique_ptr<ASTNode> PascalParser::parseTerm() {
        int lineNum = token ? token->getLine() : 1;
        auto result = parseFactor();
        while (isMulOperator()) {
            BinaryOpNode::OpType op = BinaryOpNode::MULTIPLY;
            if (peekIs("*"))
                op = BinaryOpNode::MULTIPLY;
            else if (peekIs("/"))
                op = BinaryOpNode::DIVIDE;
            else if (peekIs("div"))
                op = BinaryOpNode::DIV;
            else if (peekIs("mod"))
                op = BinaryOpNode::MOD;
            next();
            auto right = parseFactor();
            result = std::make_unique<BinaryOpNode>(std::move(result), op, std::move(right));
            result->setLineNumber(lineNum);
        }
        return result;
    }

    std::unique_ptr<ASTNode> PascalParser::parseFactor() {
        int lineNum = token ? token->getLine() : 1;
        if (peekIs(types::TokenType::TT_NUM)) {
            std::string value = token->getTokenValue();
            next();
            bool isReal = value.find('.') != std::string::npos || value.find('e') != std::string::npos || value.find('E') != std::string::npos;
            auto numberNode = std::make_unique<NumberNode>(value, !isReal, isReal);
            numberNode->setLineNumber(lineNum);
            return numberNode;
        } else if (peekIs(types::TokenType::TT_STR)) {
            std::string value = token->getTokenValue();
            next();
            auto stringNode = std::make_unique<StringNode>(value);
            stringNode->setLineNumber(lineNum);
            return stringNode;
        } else if (peekIs("true") || peekIs("false")) {
            bool value = (token->getTokenValue() == "true");
            next();
            auto booleanNode = std::make_unique<BooleanNode>(value);
            booleanNode->setLineNumber(lineNum);
            return booleanNode;
        } else if (peekIs("(")) {
            next();
            auto expr = parseExpression();
            expectToken(")");
            next();
            return expr;
        } else if (peekIs(types::TokenType::TT_ID)) {
            std::string name = token->getTokenValue();
            next();
            std::unique_ptr<ASTNode> left = std::make_unique<VariableNode>(name);
            left->setLineNumber(lineNum);
            while (true) {
                if (peekIs("[")) {
                    next();
                    auto index = parseExpression();
                    expectToken("]");
                    next();
                    left = std::make_unique<ArrayAccessNode>(std::move(left), std::move(index));
                    left->setLineNumber(lineNum);
                } else if (peekIs(".")) {
                    next();
                    expectToken(types::TokenType::TT_ID);
                    std::string fieldName = token->getTokenValue();
                    next();
                    left = std::make_unique<FieldAccessNode>(std::move(left), fieldName);
                    left->setLineNumber(lineNum);
                } else if (peekIs("(")) {
                    if (auto varNode = dynamic_cast<VariableNode *>(left.get())) {
                        return parseFunctionCall(varNode->name);
                    } else {
                        error("Function call must be on a simple identifier");
                    }
                } else {
                    break;
                }
            }
            return left;
        } else {
            error("Expected factor");
            return nullptr;
        }
    }

    std::unique_ptr<ASTNode> PascalParser::parseProcedureCall(const std::string &name) {
        int lineNum = token ? token->getLine() : 1;
        std::vector<std::unique_ptr<ASTNode>> arguments;
        if (peekIs("(")) {
            next();
            arguments = parseArgumentList();
            expectToken(")");
            next();
        }
        auto procCallNode = std::make_unique<ProcCallNode>(name, std::move(arguments));
        procCallNode->setLineNumber(lineNum);
        return procCallNode;
    }

    std::unique_ptr<ASTNode> PascalParser::parseFunctionCall(const std::string &name) {
        int lineNum = token ? token->getLine() : 1;
        std::vector<std::unique_ptr<ASTNode>> arguments;
        expectToken("(");
        next();
        arguments = parseArgumentList();
        expectToken(")");
        next();
        auto funcCallNode = std::make_unique<FuncCallNode>(name, std::move(arguments));
        funcCallNode->setLineNumber(lineNum);
        return funcCallNode;
    }

    std::unique_ptr<ASTNode> PascalParser::parseCaseStatement() {
        expectToken("case");
        int lineNum = token->getLine();
        next();
        auto expression = parseExpression();
        expectToken("of");
        next();
        std::vector<std::unique_ptr<CaseStmtNode::CaseBranch>> branches;
        while (!peekIs("end") && !peekIs("else")) {
            std::vector<std::unique_ptr<ASTNode>> values;
            values.push_back(parseExpression());
            while (peekIs(",")) {
                next();
                values.push_back(parseExpression());
            }
            expectToken(":");
            next();
            auto statement = parseStatement();
            branches.push_back(std::make_unique<CaseStmtNode::CaseBranch>(std::move(values), std::move(statement)));
            if (peekIs(";"))
                next();
        }
        std::unique_ptr<ASTNode> elseStatement = nullptr;
        if (peekIs("else")) {
            next();
            elseStatement = parseStatement();
            if (peekIs(";"))
                next();
        }
        expectToken("end");
        next();
        auto caseStmtNode = std::make_unique<CaseStmtNode>(std::move(expression), std::move(branches), std::move(elseStatement));
        caseStmtNode->setLineNumber(lineNum);
        return caseStmtNode;
    }

    std::unique_ptr<ASTNode> PascalParser::parseConstDeclaration() {
        expectToken("const");
        int lineNum = token->getLine();
        next();
        std::vector<std::unique_ptr<ConstDeclNode::ConstAssignment>> assignments;
        do {
            expectToken(types::TokenType::TT_ID);
            std::string identifier = token->getTokenValue();
            next();
            expectToken("=");
            next();
            auto value = parseExpression();
            assignments.push_back(std::make_unique<ConstDeclNode::ConstAssignment>(identifier, std::move(value)));
            expectToken(";");
            next();
        } while (peekIs(types::TokenType::TT_ID) && !isKeyword(token->getTokenValue()));
        auto constDeclNode = std::make_unique<ConstDeclNode>(std::move(assignments));
        constDeclNode->setLineNumber(lineNum);
        return constDeclNode;
    }

    std::vector<std::unique_ptr<ASTNode>> PascalParser::parseDeclarations() {
        std::vector<std::unique_ptr<ASTNode>> declarations;
        while (peekIs("type") || peekIs("const") || peekIs("var") || peekIs("procedure") || peekIs("function")) {
            if (peekIs("type")) {
                declarations.push_back(parseTypeDeclaration());
            } else if (peekIs("const")) {
                declarations.push_back(parseConstDeclaration());
            } else if (peekIs("var")) {
                if (match("var")) {
                    while (peekIs(types::TokenType::TT_ID) && !isKeyword(token->getTokenValue())) {
                        auto decl = parseVarDeclaration();
                        declarations.push_back(std::move(decl));
                    }
                }
            } else if (peekIs("procedure")) {
                declarations.push_back(parseProcedureDeclaration());
            } else if (peekIs("function")) {
                declarations.push_back(parseFunctionDeclaration());
            }
        }
        return declarations;
    }

    std::vector<std::unique_ptr<ASTNode>> PascalParser::parseStatementList() {
        std::vector<std::unique_ptr<ASTNode>> statements;
        while (!peekIs("end") && !peekIs("else") && !peekIs("until")) {
            statements.push_back(parseStatement());
            if (peekIs(";")) {
                next();
                if (peekIs("end") || peekIs("else") || peekIs("until"))
                    break;
            } else {
                break;
            }
        }
        return statements;
    }

    std::vector<std::unique_ptr<ASTNode>> PascalParser::parseArgumentList() {
        std::vector<std::unique_ptr<ASTNode>> arguments;
        if (!peekIs(")")) {
            arguments.push_back(parseExpression());
            while (peekIs(",")) {
                next();
                arguments.push_back(parseExpression());
            }
        }
        return arguments;
    }

    bool PascalParser::isMulOperator() {
        return peekIs("*") || peekIs("/") || peekIs("div") || peekIs("mod");
    }

    bool PascalParser::isRelationalOperator() {
        return peekIs("=") || peekIs("<>") || peekIs("<") || peekIs("<=") || peekIs(">") || peekIs(">=");
    }

    std::string PascalParser::getRelationalOp() {
        if (peekIs("="))
            return "=";
        if (peekIs("<>"))
            return "<>";
        if (peekIs("<="))
            return "<=";
        if (peekIs(">="))
            return ">=";
        if (peekIs("<"))
            return "<";
        if (peekIs(">"))
            return ">";
        error("Invalid relational operator");
        return "";
    }

    std::unique_ptr<ASTNode> PascalParser::parseTypeDeclaration() {
        expectToken("type");
        int lineNum = token->getLine();
        next();

        std::vector<std::unique_ptr<ASTNode>> typeDeclarations;

        do {
            expectToken(types::TokenType::TT_ID);
            std::string typeName = token->getTokenValue();
            next();
            expectToken("=");
            next();

            std::unique_ptr<ASTNode> typeDefinition;

            if (peekIs("record")) {
                auto recordType = parseRecordType();
                typeDefinition = std::make_unique<RecordDeclarationNode>(
                    typeName,
                    std::unique_ptr<RecordTypeNode>(static_cast<RecordTypeNode *>(recordType.release())));
            } else if (peekIs("array")) {
                auto arrayType = parseArrayType();
                typeDefinition = std::make_unique<ArrayTypeDeclarationNode>(
                    typeName,
                    std::unique_ptr<ArrayTypeNode>(static_cast<ArrayTypeNode *>(arrayType.release())));
            } else {
                expectToken(types::TokenType::TT_ID);
                std::string baseType = token->getTokenValue();
                next();
                typeDefinition = std::make_unique<TypeAliasNode>(typeName, baseType);
            }

            expectToken(";");
            next();

            typeDeclarations.push_back(std::move(typeDefinition));
        } while (peekIs(types::TokenType::TT_ID) && !isKeyword(token->getTokenValue()));

        auto typeDeclNode = std::make_unique<TypeDeclNode>(std::move(typeDeclarations));
        typeDeclNode->setLineNumber(lineNum);
        return typeDeclNode;
    }

    std::unique_ptr<ASTNode> PascalParser::parseRecordType() {
        expectToken("record");
        next();
        std::vector<std::unique_ptr<ASTNode>> fields;
        while (!peekIs("end")) {
            std::vector<std::string> ids;
            expectToken(types::TokenType::TT_ID);
            ids.push_back(token->getTokenValue());
            next();
            while (peekIs(",")) {
                next();
                expectToken(types::TokenType::TT_ID);
                ids.push_back(token->getTokenValue());
                next();
            }
            expectToken(":");
            next();
            auto fieldType = parseTypeSpec();
            fields.push_back(std::make_unique<VarDeclNode>(
                std::move(ids),
                std::move(fieldType),
                std::vector<std::unique_ptr<ASTNode>>{}));
            expectToken(";");
            next();
        }
        expectToken("end");
        next();
        return std::make_unique<RecordTypeNode>(std::move(fields));
    }

    std::unique_ptr<ASTNode> PascalParser::parseVarDeclaration() {
        std::vector<std::string> identifiers;
        std::vector<std::unique_ptr<ASTNode>> initializers;

        do {
            expectToken(types::TokenType::TT_ID);
            identifiers.push_back(token->getTokenValue());
            next();
            if (peekIs(","))
                next();
            else
                break;
        } while (true);

        expectToken(":");
        next();

        auto typeAst = parseTypeSpec();

        if (peekIs(":=")) {
            next();
            initializers.push_back(parseExpression());
        }

        expectToken(";");
        next();

        return std::make_unique<VarDeclNode>(
            std::move(identifiers),
            std::move(typeAst),
            std::move(initializers));
    }

    std::unique_ptr<ASTNode> PascalParser::parseTypeSpec() {
        if (peekIs("array"))
            return parseArrayType();
        if (peekIs("record"))
            return parseRecordType();
        expectToken(types::TokenType::TT_ID);
        auto t = std::make_unique<SimpleTypeNode>(token->getTokenValue());
        next();
        return t;
    }

    std::unique_ptr<ASTNode> PascalParser::parseArrayType() {
        expectToken("array");
        next();
        expectToken("[");
        next();
        auto lowerBound = parseExpression();
        expectToken("..");
        next();
        auto upperBound = parseExpression();
        expectToken("]");
        next();
        expectToken("of");
        next();
        auto elementType = parseTypeSpec();
        return std::make_unique<ArrayTypeNode>(
            std::move(elementType),
            std::move(lowerBound),
            std::move(upperBound));
    }

    std::string PascalParser::tokenTypeToString(types::TokenType type) {
        switch (type) {
        case types::TokenType::TT_ID:
            return "identifier";
        case types::TokenType::TT_NUM:
            return "number";
        case types::TokenType::TT_STR:
            return "string";
        case types::TokenType::TT_SYM:
            return "symbol";
        default:
            return "unknown token";
        }
    }

    std::unique_ptr<ASTNode> PascalParser::parseLValue() {
        int lineNum = token ? token->getLine() : 1;
        expectToken(types::TokenType::TT_ID);
        std::string name = token->getTokenValue();
        next();

        std::unique_ptr<ASTNode> left = std::make_unique<VariableNode>(name);
        left->setLineNumber(lineNum);

        while (true) {
            if (peekIs("[")) {
                next();
                auto index = parseExpression();
                expectToken("]");
                next();
                left = std::make_unique<ArrayAccessNode>(std::move(left), std::move(index));
                left->setLineNumber(lineNum);
            } else if (peekIs(".")) {
                next();
                expectToken(types::TokenType::TT_ID);
                std::string fieldName = token->getTokenValue();
                next();
                left = std::make_unique<FieldAccessNode>(std::move(left), fieldName);
                left->setLineNumber(lineNum);
            } else {
                break;
            }
        }
        return left;
    }
} // namespace pascal