← index
MXVM/src/frontend/include/parser.hpp
Source: MXVM/src/frontend/include/parser.hpp
#ifndef _PARSER_H__H
#define _PARSER_H__H
#include "ast.hpp"
#include "scanner/exception.hpp"
#include "scanner/scanner.hpp"
#include "validator.hpp"
#include <memory>
#include <stdexcept>
#include <string>
#include <vector>

namespace pascal {
    class ParseException : public std::runtime_error {
      public:
        explicit ParseException(const std::string &msg) : std::runtime_error(msg) {}
    };
} // namespace pascal

namespace mxx {
    class XParser {
      public:
        XParser() = delete;
        explicit XParser(const std::string &source)
            : scanner(source), token(nullptr), index(0) {
            scanner.scan();
            scanner.removeEOL();
            if (scanner.size() > 0) {
                token = &scanner[0];
                index = 0;
            }
        }

        bool next() {
            if (index + 1 < scanner.size()) {
                index++;
                token = &scanner[index];
                return true;
            }
            token = nullptr;
            return false;
        }

        bool peekIs(const std::string &s) {
            return token && token->getTokenValue() == s;
        }
        bool peekIs(const types::TokenType &t) {
            return token && token->getTokenType() == t;
        }

        static std::string tokenTypeToString(types::TokenType t) {
            switch (t) {
            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";
            }
        }

        std::string filename;

      protected:
        scan::Scanner scanner;
        scan::TToken *token = nullptr;
        size_t index = 0;
    };
} // namespace mxx

namespace pascal {
    class PascalParser : public mxx::XParser {
      public:
        PascalParser() = delete;
        explicit PascalParser(const std::string &source) : mxx::XParser(source), validator(source) {}

        std::unique_ptr<ProgramNode> parseProgram();
        mxx::TPValidator validator;

      private:
        void error(const std::string &message);
        void expectToken(const std::string &expected);
        void expectToken(types::TokenType expected);
        bool match(const std::string &s);
        bool match(types::TokenType t);
        std::unique_ptr<ASTNode> parseLValue();
        std::unique_ptr<BlockNode> parseBlock();
        std::unique_ptr<CompoundStmtNode> parseCompoundStatement();
        std::vector<std::unique_ptr<ASTNode>> parseDeclarations();
        std::unique_ptr<ASTNode> parseVarDeclaration();
        std::unique_ptr<ASTNode> parseConstDeclaration();
        std::unique_ptr<ASTNode> parseProcedureDeclaration();
        std::unique_ptr<ASTNode> parseFunctionDeclaration();
        std::vector<std::unique_ptr<ASTNode>> parseParameterList();
        std::vector<std::unique_ptr<ASTNode>> parseStatementList();
        std::unique_ptr<ASTNode> parseParameter();
        std::unique_ptr<ASTNode> parseRecordType();
        std::unique_ptr<ASTNode> parseTypeDeclaration();
        std::unique_ptr<ASTNode> parseStatement();
        std::unique_ptr<ASTNode> parseAssignmentOrProcCall();
        std::unique_ptr<ASTNode> parseIfStatement();
        std::unique_ptr<ASTNode> parseWhileStatement();
        std::unique_ptr<ASTNode> parseForStatement();
        std::unique_ptr<ASTNode> parseRepeatStatement();
        std::unique_ptr<ASTNode> parseCaseStatement();
        std::unique_ptr<ASTNode> parseExpression();
        std::unique_ptr<ASTNode> parseSimpleExpression();
        std::unique_ptr<ASTNode> parseTerm();
        std::unique_ptr<ASTNode> parseFactor();
        std::unique_ptr<ASTNode> parseProcedureCall(const std::string &name);
        std::unique_ptr<ASTNode> parseFunctionCall(const std::string &name);
        std::vector<std::unique_ptr<ASTNode>> parseArgumentList();

        bool isRelationalOperator();
        bool isAddOperator();
        bool isMulOperator();

        std::unique_ptr<ASTNode> parseTypeSpec();

        std::string getRelationalOp();
        std::string getAddOp();
        std::string getMulOp();
        std::string getUnaryOp();
        BinaryOpNode::OpType getComparisonOperator(const std::string &op);
        BinaryOpNode::OpType getLogicalOperator(const std::string &op);
        BinaryOpNode::OpType getArithmeticOperator(const std::string &op);
        std::string tokenTypeToString(types::TokenType type);
        bool isType(const std::string &token);
        bool isBuiltinProcedure(const std::string &name);
        bool isBuiltinFunction(const std::string &name);
        bool isKeyword(const std::string &s);
        std::unique_ptr<ASTNode> parseArrayType();
        std::unique_ptr<ASTNode> parseArrayDeclaration(const std::string &varName);
        bool isArrayAccess();
    };
} // namespace pascal

#endif