From 17b3739f756a1e713704b22cce89307308cea2d8 Mon Sep 17 00:00:00 2001
From: Ferenc Szontágh <szf@fsociety.hu>
Date: Fri, 18 Apr 2025 20:33:13 +0000
Subject: [PATCH] add else if to the if
---
src/Parser/Parser.hpp | 225 ++++++-------------------------------------------------
1 files changed, 27 insertions(+), 198 deletions(-)
diff --git a/src/Parser/Parser.hpp b/src/Parser/Parser.hpp
index b8656e5..ed08bde 100644
--- a/src/Parser/Parser.hpp
+++ b/src/Parser/Parser.hpp
@@ -47,7 +47,6 @@
void parseScript(const std::vector<Lexer::Tokens::Token> & tokens, std::string_view input_string,
const std::string & filename);
-
static const std::unordered_map<std::string, Lexer::Tokens::Type> keywords;
static const std::unordered_map<Lexer::Tokens::Type, Symbols::Variables::Type> variable_types;
@@ -58,100 +57,29 @@
std::string current_filename_;
// Token stream handling and error-reporting helper functions (unchanged)
- const Lexer::Tokens::Token & currentToken() const {
- if (isAtEnd()) {
- // Technically we should never reach this if parseScript's loop is correct
- // But it's useful as a safety check
- if (!tokens_.empty() && tokens_.back().type == Lexer::Tokens::Type::END_OF_FILE) {
- return tokens_.back(); // return the EOF token
- }
- throw std::runtime_error("Unexpected end of token stream reached.");
- }
- return tokens_[current_token_index_];
- }
+ const Lexer::Tokens::Token & currentToken() const;
// Look ahead in the token stream
- const Lexer::Tokens::Token & peekToken(size_t offset = 1) const {
- if (current_token_index_ + offset >= tokens_.size()) {
- // If at or beyond EOF, return the last token (should be EOF)
- if (!tokens_.empty()) {
- return tokens_.back();
- }
- throw std::runtime_error("Cannot peek beyond end of token stream.");
- }
- return tokens_[current_token_index_ + offset];
- }
+ const Lexer::Tokens::Token & peekToken(size_t offset = 1) const;
// Consume (advance past) the current token and return it
- Lexer::Tokens::Token consumeToken() {
- if (isAtEnd()) {
- throw std::runtime_error("Cannot consume token at end of stream.");
- }
- return tokens_[current_token_index_++];
- }
+ 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) {
- if (isAtEnd()) {
- return false;
- }
- if (currentToken().type == expected_type) {
- consumeToken();
- return true;
- }
- 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) {
- if (isAtEnd()) {
- return false;
- }
- const auto & token = currentToken();
- if (token.type == expected_type && token.value == expected_value) {
- consumeToken();
- return true;
- }
- return false;
- }
+ bool match(Lexer::Tokens::Type expected_type, const std::string & expected_value);
- Lexer::Tokens::Token expect(Lexer::Tokens::Type expected_type) {
- if (isAtEnd()) {
- reportError("Unexpected end of file, expected token type: " + Lexer::Tokens::TypeToString(expected_type));
- }
- const auto & token = currentToken();
- if (token.type == expected_type) {
- return consumeToken();
- }
- reportError("Expected token type " + Lexer::Tokens::TypeToString(expected_type));
- // reportError throws; this return is never reached, but may satisfy the compiler
- return token; // or let reportError throw
- }
+ 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) {
- if (isAtEnd()) {
- reportError("Unexpected end of file, expected token: " + Lexer::Tokens::TypeToString(expected_type) +
- " with value '" + expected_value + "'");
- }
- const auto & token = currentToken();
- if (token.type == expected_type && token.value == expected_value) {
- return consumeToken();
- }
- reportError("Expected token " + Lexer::Tokens::TypeToString(expected_type) + " with value '" + expected_value +
- "'");
- return token; // reportError throws
- }
+ 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 {
- // We're at the end if the index equals the number of tokens,
- // or if only the EOF token remains (as the last element)
- return current_token_index_ >= tokens_.size() ||
- (current_token_index_ == tokens_.size() - 1 && tokens_.back().type == Lexer::Tokens::Type::END_OF_FILE);
- }
+ bool isAtEnd() const;
[[noreturn]] void reportError(const std::string & message, const std::string & expected = "") {
if (current_token_index_ < tokens_.size()) {
@@ -168,64 +96,23 @@
}
// parseStatement (updated to handle return)
- void parseStatement() {
- const auto & token_type = currentToken().type;
- // if-else conditional
- if (token_type == Lexer::Tokens::Type::KEYWORD && currentToken().value == "if") {
- parseIfStatement();
- return;
- }
-
- if (token_type == Lexer::Tokens::Type::KEYWORD_FUNCTION_DECLARATION) {
- parseFunctionDefinition();
- return;
- }
- // Return statement
- if (token_type == Lexer::Tokens::Type::KEYWORD_RETURN) {
- parseReturnStatement();
- return;
- }
-
- // Variable definition if leading token matches a type keyword
- if (Parser::variable_types.find(token_type) != Parser::variable_types.end()) {
- parseVariableDefinition();
- return;
- }
- // Function call if identifier followed by '('
- if (currentToken().type == Lexer::Tokens::Type::IDENTIFIER &&
- peekToken().type == Lexer::Tokens::Type::PUNCTUATION && peekToken().value == "(") {
- parseCallStatement();
- return;
- }
- // Assignment statement at top-level
- if (currentToken().type == Lexer::Tokens::Type::VARIABLE_IDENTIFIER) {
- size_t offset = 1;
- // Skip member access chain
- while (peekToken(offset).type == Lexer::Tokens::Type::PUNCTUATION && peekToken(offset).value == "->") {
- offset += 2;
- }
- const auto & look = peekToken(offset);
- if (look.type == Lexer::Tokens::Type::OPERATOR_ASSIGNMENT && look.value == "=") {
- parseAssignmentStatement();
- return;
- }
- }
-
- reportError("Unexpected token at beginning of statement");
- }
-
- void parseVariableDefinition();
- void parseFunctionDefinition();
+ void parseStatement();
+ void parseVariableDefinition();
+ void parseFunctionDefinition();
// Parse a top-level function call statement (e.g., foo(arg1, arg2);)
- void parseCallStatement();
+ void parseCallStatement();
// Parse a top-level assignment statement (variable or object member)
- void parseAssignmentStatement();
+ void parseAssignmentStatement();
// Parse a return statement (e.g., return; or return expr;)
- void parseReturnStatement();
- // Parse an if-else conditional statement
- void parseIfStatement();
- // Parse a for-in loop over object members
- void parseForStatement();
+ 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<Interpreter::StatementNode> parseIfStatementNode();
+ // Parse a for-in loop over object members and return a StatementNode (for nested blocks)
+ std::unique_ptr<Interpreter::StatementNode> parseForStatementNode();
// Parse a statement node for use inside blocks (not added to operation container)
std::unique_ptr<Interpreter::StatementNode> parseStatementNode();
@@ -233,69 +120,11 @@
// type : KEYWORD_STRING | KEYWORD_INT | KEYWORD_DOUBLE
// Returns the corresponding Symbols::Variables::Type enum and consumes the token
- Symbols::Variables::Type parseType() {
- const auto & token = currentToken();
- // Direct lookup for type keyword
- auto it = Parser::variable_types.find(token.type);
- if (it != Parser::variable_types.end()) {
- consumeToken();
- return it->second;
- }
- reportError("Expected type keyword (string, int, double, float)");
- }
-
- Symbols::Value parseValue(Symbols::Variables::Type expected_var_type) {
- Lexer::Tokens::Token token = currentToken();
- bool is_negative = false;
-
- // Handle unary sign
- if (token.type == Lexer::Tokens::Type::OPERATOR_ARITHMETIC && (token.lexeme == "-" || token.lexeme == "+") &&
- peekToken().type == Lexer::Tokens::Type::NUMBER) {
- is_negative = (token.lexeme == "-");
- token = peekToken();
- consumeToken(); // consumed the sign
- }
-
- // STRING type
- if (expected_var_type == Symbols::Variables::Type::STRING) {
- if (token.type == Lexer::Tokens::Type::STRING_LITERAL) {
- consumeToken();
- return Symbols::Value(token.value);
- }
- reportError("Expected string literal value");
- }
-
- // BOOLEAN type
- if (expected_var_type == Symbols::Variables::Type::BOOLEAN) {
- if (token.type == Lexer::Tokens::Type::KEYWORD && (token.value == "true" || token.value == "false")) {
- consumeToken();
- return Symbols::Value(token.value == "true");
- }
- reportError("Expected boolean literal value (true or false)");
- }
-
- // NUMERIC types
- if (expected_var_type == Symbols::Variables::Type::INTEGER ||
- expected_var_type == Symbols::Variables::Type::DOUBLE ||
- expected_var_type == Symbols::Variables::Type::FLOAT) {
- if (token.type == Lexer::Tokens::Type::NUMBER) {
- Symbols::Value val = parseNumericLiteral(token.value, is_negative, expected_var_type);
- consumeToken();
- return val;
- }
-
- reportError("Expected numeric literal value");
- }
-
- reportError("Unsupported variable type encountered during value parsing");
- return Symbols::Value(); // compiler happy
- }
-
- 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);
-
+ 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
--
Gitblit v1.9.3