#ifndef PARSER_HPP #define PARSER_HPP #include #include #include #include "BaseException.hpp" #include "Interpreter/StatementNode.hpp" #include "Lexer/Token.hpp" #include "Lexer/TokenType.hpp" #include "Parser/ParsedExpression.hpp" #include "Symbols/ParameterContainer.hpp" #include "Symbols/Value.hpp" namespace Parser { class Parser { public: Parser() {} class Exception : public BaseException { public: using BaseException::BaseException; Exception(const std::string & msg, const std::string & expected, const Lexer::Tokens::Token & token) { rawMessage_ = msg + ": " + token.dump(); context_ = " at line: " + std::to_string(token.line_number) + ", column: " + std::to_string(token.column_number); if (expected.empty() == false) { rawMessage_ += " (expected: " + expected + ")"; } formattedMessage_ = formatMessage(); } Exception(const std::string & msg, const std::string & expected, int line, int col) { rawMessage_ = msg; if (expected.empty() == false) { rawMessage_ += " (expected: " + expected + ")"; } context_ = " at line: " + std::to_string(line) + ", column: " + std::to_string(col); formattedMessage_ = formatMessage(); } std::string formatMessage() const override { return "[Syntax ERROR] >>" + context_ + " << : " + rawMessage_; } }; void parseScript(const std::vector & tokens, std::string_view input_string, const std::string & filename); static const std::unordered_map keywords; static const std::unordered_map variable_types; private: std::vector tokens_; std::string_view input_str_view_; size_t current_token_index_; std::string current_filename_; // Token stream handling and error-reporting helper functions (unchanged) const Lexer::Tokens::Token & currentToken() const; // Look ahead in the token stream const Lexer::Tokens::Token & peekToken(size_t offset = 1) const; // Consume (advance past) the current token and return it Lexer::Tokens::Token consumeToken(); // Check if current token type matches the expected type // If so, consume it and return true; otherwise return false bool match(Lexer::Tokens::Type expected_type); // Check if current token type and value match the expected ones // Only use value checking for operators and punctuation bool match(Lexer::Tokens::Type expected_type, const std::string & expected_value); Lexer::Tokens::Token expect(Lexer::Tokens::Type expected_type); // Like expect, but also checks the token's value Lexer::Tokens::Token expect(Lexer::Tokens::Type expected_type, const std::string & expected_value); // Check if we've reached the end of relevant tokens (just before EOF) bool isAtEnd() const; [[noreturn]] void reportError(const std::string & message, const std::string & expected = "") { if (current_token_index_ < tokens_.size()) { throw Exception(message, expected, tokens_[current_token_index_]); } int line = tokens_.empty() ? 0 : tokens_.back().line_number; int col = tokens_.empty() ? 0 : tokens_.back().column_number; throw Exception(message, expected, line, col); } [[noreturn]] static void reportError(const std::string & message, const Lexer::Tokens::Token & token, const std::string & expected = "") { throw Exception(message, expected, token); } // parseStatement (updated to handle return) void parseStatement(); void parseVariableDefinition(); void parseFunctionDefinition(); // Parse a top-level function call statement (e.g., foo(arg1, arg2);) void parseCallStatement(); // Parse a top-level assignment statement (variable or object member) void parseAssignmentStatement(); // Parse a return statement (e.g., return; or return expr;) void parseReturnStatement(); // Parse an if-else conditional statement (at top-level) void parseIfStatement(); // Parse a for-in loop over object members (at top-level) void parseForStatement(); // Parse an if-else conditional block and return a StatementNode (for nested blocks) std::unique_ptr parseIfStatementNode(); // Parse a for-in loop over object members and return a StatementNode (for nested blocks) std::unique_ptr parseForStatementNode(); // Parse a statement node for use inside blocks (not added to operation container) std::unique_ptr parseStatementNode(); // --- Parsing helper functions --- // type : KEYWORD_STRING | KEYWORD_INT | KEYWORD_DOUBLE // Returns the corresponding Symbols::Variables::Type enum and consumes the token Symbols::Variables::Type parseType(); Symbols::Value parseValue(Symbols::Variables::Type expected_var_type); Symbols::Value parseNumericLiteral(const std::string & value, bool is_negative, Symbols::Variables::Type type); void parseFunctionBody(const Lexer::Tokens::Token & opening_brace, const std::string & function_name, Symbols::Variables::Type return_type, const Symbols::FunctionParameterInfo & params); ParsedExpressionPtr parseParsedExpression(const Symbols::Variables::Type & expected_var_type); }; // class Parser } // namespace Parser #endif // PARSER_HPP