From 078e26271bd9aeb7711085e6239b4d02c38ffec4 Mon Sep 17 00:00:00 2001 From: Siddharth Maira Date: Mon, 2 Feb 2026 21:50:50 +0530 Subject: [PATCH 01/15] test commit --- test.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test.txt diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..e69de29 From 8ae90c214b98eb6cc38f7e64d85b8b3beefacb38 Mon Sep 17 00:00:00 2001 From: Sasank <213149805+sash070@users.noreply.github.com> Date: Mon, 2 Feb 2026 21:59:28 +0530 Subject: [PATCH 02/15] cahnge --- madhav.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/madhav.txt b/madhav.txt index 9012a49..51568ea 100644 --- a/madhav.txt +++ b/madhav.txt @@ -1 +1 @@ -i like madhav more than no one +i like madhav more than sujal From b220e9b507fcb9ecf600dc478eb09d3f53c6ffad Mon Sep 17 00:00:00 2001 From: Sasank <213149805+sash070@users.noreply.github.com> Date: Mon, 2 Feb 2026 22:40:44 +0530 Subject: [PATCH 03/15] change --- madhav.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/madhav.txt b/madhav.txt index 51568ea..0a1fc2e 100644 --- a/madhav.txt +++ b/madhav.txt @@ -1 +1,2 @@ i like madhav more than sujal +change From ff5f98cf02428e748ff659572db6f4ba8161b92c Mon Sep 17 00:00:00 2001 From: Siddharth Maira Date: Thu, 12 Feb 2026 12:39:07 +0530 Subject: [PATCH 04/15] Defined structure for lexing and created Makefile --- .gitignore | 3 ++ Makefile | 42 ++++++++++++++++++++++++++ test.txt => src/common/token/token.hpp | 0 src/lexer/indentation.cpp | 0 src/lexer/indentation.hpp | 0 src/lexer/keywords.hpp | 0 src/lexer/lexer.cpp | 0 src/lexer/lexer.hpp | 0 8 files changed, 45 insertions(+) create mode 100644 Makefile rename test.txt => src/common/token/token.hpp (100%) create mode 100644 src/lexer/indentation.cpp create mode 100644 src/lexer/indentation.hpp create mode 100644 src/lexer/keywords.hpp create mode 100644 src/lexer/lexer.cpp create mode 100644 src/lexer/lexer.hpp diff --git a/.gitignore b/.gitignore index d4fb281..80a6dbe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +#build directory +build/ + # Prerequisites *.d diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e82cc23 --- /dev/null +++ b/Makefile @@ -0,0 +1,42 @@ +#vars +TARGET_EXEC := executable +BUILD_DIR := build +SRC_DIR := src + +SRCS := $(shell find $(SRC_DIR) -name '*.cpp') +OBJS := $(SRCS:$(SRC_DIR)/%.cpp=$(BUILD_DIR)/%.o) +DEPS := $(OBJS:.o=.d) +INCS := $(shell find $(SRC_DIR) -type d) + +INC_FLAGS := $(addprefix -I,$(INCS)) +CPPFLAGS := $(INC_FLAGS) -MMD -MP +LDFLAGS := + +CXX := g++ + +#all +all: $(BUILD_DIR)/$(TARGET_EXEC) + +#executable dependencies +$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS) + @echo "Linking" + mkdir -p $(BUILD_DIR) + $(CXX) $(OBJS) -o $@ $(LDFLAGS) + +#object dependencies +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp + @echo "Building dependencies" + mkdir -p $(dir $@) + $(CXX) $(CPPFLAGS) -c $< -o $@ + @echo + +#for change in header files +-include $(DEPS) + +.PHONY: all clean run + +run: all + ./$(BUILD_DIR)/$(TARGET_EXEC) + +clean: + rm -rf $(BUILD_DIR) diff --git a/test.txt b/src/common/token/token.hpp similarity index 100% rename from test.txt rename to src/common/token/token.hpp diff --git a/src/lexer/indentation.cpp b/src/lexer/indentation.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/lexer/indentation.hpp b/src/lexer/indentation.hpp new file mode 100644 index 0000000..e69de29 diff --git a/src/lexer/keywords.hpp b/src/lexer/keywords.hpp new file mode 100644 index 0000000..e69de29 diff --git a/src/lexer/lexer.cpp b/src/lexer/lexer.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/lexer/lexer.hpp b/src/lexer/lexer.hpp new file mode 100644 index 0000000..e69de29 From b7544260698cb5f61862fbc855d22658e65a7fed Mon Sep 17 00:00:00 2001 From: Siddharth Maira Date: Thu, 12 Feb 2026 22:07:52 +0530 Subject: [PATCH 05/15] filled token.hpp and lexer.hpp with basic declarations(from ankit's commit) --- src/common/token/token.hpp | 57 ++++++++++++++++++++++++++++++++++++++ src/lexer/lexer.hpp | 56 +++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/src/common/token/token.hpp b/src/common/token/token.hpp index e69de29..91fb490 100644 --- a/src/common/token/token.hpp +++ b/src/common/token/token.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include + +enum class TokenType { + DEF, + RETURN, + IF, + ELSE, + FOR, + WHILE, + + IDENTIFIER, + NUMBER, + STRING, + + PLUS, // + + MINUS, // - + STAR, // * + SLASH, // / + ASSIGN, // = + MODULO, // % + GREATERTHAN, // > + LESSERTHAN, // < + + LPAREN, // ( + RPAREN, // ) + + NEWLINE, + EOF_TOKEN, + + COMMA, // , + COLON, // : + INDENT, + DEDENT, + COMMENT // # +}; + + +class Token{ +public: + // Main part of a token + TokenType type; + std::string value; + + // Used to tell user about error in case error is found + int line; + int column; + + // This constructor will allow us to easily make the tokens while coding + Token(TokenType type, std::string val, int l, int c) +}; + + + + + diff --git a/src/lexer/lexer.hpp b/src/lexer/lexer.hpp index e69de29..be04547 100644 --- a/src/lexer/lexer.hpp +++ b/src/lexer/lexer.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include +#include +#include + +#include "token.hpp" + +class Lexer{ +public: + Lexer(std::string input_string){ + this->source_code = preprocess_indents(input_string); + } + std::vector scan_Tokens(); + +private: + std::string source_code; + static inline const std::unordered_map keywords = { + {"def", TokenType::DEF}, + {"return", TokenType::RETURN}, + {"if", TokenType::IF}, + {"else", TokenType::ELSE}, + {"print", TokenType::PRINT}, + {"=", TokenType::ASSIGN}, + {"+", TokenType::PLUS}, + {"-", TokenType::MINUS}, + {"*", TokenType::STAR}, + {"/", TokenType::SLASH}, + {"(", TokenType::LPAREN}, + {")", TokenType::RPAREN}, + {":", TokenType::COLON}, + {",", TokenType::COMMA}, + {"\n", TokenType::NEWLINE}, + {"\t", TokenType::INDENT}, + {"\r", TokenType::DEDENT} + }; + std::vector tokens; + int start = 0; + int current_index = 0; + int line = 1; + + + // FUNCTIONS NEEDED FOR LEXER TO WORK + bool isAtEnd(); // Checks for last character + char advance(); // Return current char and move forward + char peek(); // Sometimes, we don't actually want to read a character and may only want to peek at it + char peekNext(); // Peak at the next character + + void addToken(TokenType type); + + // Specific scanners for complex types + void scanString(); + void scanNumber(); + void scanIdentifier(); + std::string preprocess_indents(std::string raw); +}; From 5f4b061b95aec1ae7d5ab44cfeed4b8ac8c7d564 Mon Sep 17 00:00:00 2001 From: Siddharth Maira Date: Thu, 12 Feb 2026 22:10:46 +0530 Subject: [PATCH 06/15] clean up --- src/common/token/token.hpp | 4 ++-- src/lexer/lexer.hpp | 25 +++++++++++-------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/common/token/token.hpp b/src/common/token/token.hpp index 91fb490..7489d7a 100644 --- a/src/common/token/token.hpp +++ b/src/common/token/token.hpp @@ -37,7 +37,7 @@ enum class TokenType { }; -class Token{ +class Token { public: // Main part of a token TokenType type; @@ -48,7 +48,7 @@ class Token{ int column; // This constructor will allow us to easily make the tokens while coding - Token(TokenType type, std::string val, int l, int c) + Token(TokenType type, std::string val, int l, int c); }; diff --git a/src/lexer/lexer.hpp b/src/lexer/lexer.hpp index be04547..cb547a2 100644 --- a/src/lexer/lexer.hpp +++ b/src/lexer/lexer.hpp @@ -6,12 +6,10 @@ #include "token.hpp" -class Lexer{ +class Lexer { public: - Lexer(std::string input_string){ - this->source_code = preprocess_indents(input_string); - } - std::vector scan_Tokens(); + Lexer(std::string input_string); + std::vector scan_Tokens(void); private: std::string source_code; @@ -31,8 +29,7 @@ class Lexer{ {":", TokenType::COLON}, {",", TokenType::COMMA}, {"\n", TokenType::NEWLINE}, - {"\t", TokenType::INDENT}, - {"\r", TokenType::DEDENT} + {"\t", TokenType::INDENT} }; std::vector tokens; int start = 0; @@ -41,16 +38,16 @@ class Lexer{ // FUNCTIONS NEEDED FOR LEXER TO WORK - bool isAtEnd(); // Checks for last character - char advance(); // Return current char and move forward - char peek(); // Sometimes, we don't actually want to read a character and may only want to peek at it - char peekNext(); // Peak at the next character + bool isAtEnd(void); // Checks for last character + char advance(void); // Return current char and move forward + char peek(void); // Sometimes, we don't actually want to read a character and may only want to peek at it + char peekNext(void); // Peak at the next character void addToken(TokenType type); // Specific scanners for complex types - void scanString(); - void scanNumber(); - void scanIdentifier(); + void scanString(void); + void scanNumber(void); + void scanIdentifier(void); std::string preprocess_indents(std::string raw); }; From 81b9a990832d76e8483c3a3fe921bcd1d6673e30 Mon Sep 17 00:00:00 2001 From: Sasank <213149805+sash070@users.noreply.github.com> Date: Sat, 28 Feb 2026 17:03:31 +0530 Subject: [PATCH 07/15] added basic lexer implementation except errors and indent stack --- .vscode/settings.json | 3 + src/common/token/token.cpp | 5 ++ src/common/token/token.hpp | 6 +- src/lexer/keywords.hpp | 27 +++++++++ src/lexer/lexer.cpp | 117 +++++++++++++++++++++++++++++++++++++ src/lexer/lexer.hpp | 37 ++++-------- 6 files changed, 168 insertions(+), 27 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 src/common/token/token.cpp diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ad52559 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "makefile.configureOnOpen": true +} diff --git a/src/common/token/token.cpp b/src/common/token/token.cpp new file mode 100644 index 0000000..cc33e7e --- /dev/null +++ b/src/common/token/token.cpp @@ -0,0 +1,5 @@ +#include +#include + +Token::Token(TokenType type, std::string val, int l, int c) : type(type), value(val), line(l), column(c){} + diff --git a/src/common/token/token.hpp b/src/common/token/token.hpp index 7489d7a..8f2196d 100644 --- a/src/common/token/token.hpp +++ b/src/common/token/token.hpp @@ -33,7 +33,11 @@ enum class TokenType { COLON, // : INDENT, DEDENT, - COMMENT // # + COMMENT, // # + PRINT, + AMPERSAND, // & + PIPE, // | + SPACE, }; diff --git a/src/lexer/keywords.hpp b/src/lexer/keywords.hpp index e69de29..838abd5 100644 --- a/src/lexer/keywords.hpp +++ b/src/lexer/keywords.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include + +#include "token.hpp" + +inline const std::unordered_map keywords = { + {"def", TokenType::DEF}, + {"return", TokenType::RETURN}, + {"if", TokenType::IF}, + {"else", TokenType::ELSE}, + {"print", TokenType::PRINT}, + {"=", TokenType::ASSIGN}, + {"+", TokenType::PLUS}, + {"-", TokenType::MINUS}, + {"*", TokenType::STAR}, + {"/", TokenType::SLASH}, + {"(", TokenType::LPAREN}, + {")", TokenType::RPAREN}, + {":", TokenType::COLON}, + {",", TokenType::COMMA}, + {"\n", TokenType::NEWLINE}, + {"\t", TokenType::INDENT}, + {" ", TokenType::SPACE} + }; diff --git a/src/lexer/lexer.cpp b/src/lexer/lexer.cpp index e69de29..54dcd69 100644 --- a/src/lexer/lexer.cpp +++ b/src/lexer/lexer.cpp @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include + +Lexer::Lexer(std::string input_string) : source_code(input_string){} +bool Lexer::isAtEnd(){ + if (current_index >= source_code.size()){ + return true; + } + return false; +} +char Lexer::peek(){ + if (current_index >= source_code.size()){ + return '\0'; + } + return source_code[current_index]; +} + +char Lexer::peekNext(){ + if (current_index+1 >= source_code.size()){ + return '\0'; + } + return source_code[current_index+1]; +} + +char Lexer::advance(){ + if (current_index >= source_code.size()){ + return '\0'; + } + char c = source_code[current_index++]; + if (c == '\n'){ + line++; + column=1; + } + else {column++;} + return c; +} + +void Lexer::scanNumber(std::string curr){ + int start = column-1; + while (std::isdigit(peek())){ + curr += Lexer::advance(); + } + if (std::isalnum(peek())){ + // throw an error + } + Token token(TokenType::NUMBER, curr, line, start); + tokens.push_back(token); +} + +void Lexer::scanString(std::string quote){ + int start = column-1; + while (!isAtEnd() && peek()!=quote[0] && peek()!='\n'){ + quote += advance(); + } + if (isAtEnd()){ + // throw an error + } + else if (peek()=='\n'){ + // throw an error + } + else{ + quote += advance(); + } + Token token(TokenType::STRING, quote, line, start); + tokens.push_back(token); +} + +void Lexer::scanIdentifier(std::string curr){ + int start = column-1; + while (std::isalnum(peek()) || peek()=='_'){ + curr += advance(); + } + Token token(TokenType::IDENTIFIER, curr, line, start); + if (keywords.count(curr)){ + token.type = keywords.at(curr); + } + tokens.push_back(token); +} + + +std::vector Lexer::scan_Tokens(){ + while (true){ + if (isAtEnd()){ + Token token(TokenType::EOF_TOKEN, "", line, column); + tokens.push_back(token); + break; + } + std::string curr = ""; + curr += advance(); + if (keywords.count(curr)){ + TokenType type = keywords.at(curr); + if (type == TokenType::NEWLINE){ + column = 0; + line++; + } + else if (type == TokenType::INDENT){ + column += 3; + } + else if (type == TokenType::DEDENT){ + column -= 5; + } + Token token(type, curr, line, column); + tokens.push_back(token); + } + else{ + if (std::isdigit(curr[0])){ + scanNumber(curr); + } + else if (std::isalpha(curr[0])){ + scanIdentifier(curr); + } + } +} +} diff --git a/src/lexer/lexer.hpp b/src/lexer/lexer.hpp index cb547a2..ae15f7a 100644 --- a/src/lexer/lexer.hpp +++ b/src/lexer/lexer.hpp @@ -3,51 +3,36 @@ #include #include #include +#include //to check if char is alphanumeric #include "token.hpp" class Lexer { public: Lexer(std::string input_string); - std::vector scan_Tokens(void); + std::vector scan_Tokens(); + private: std::string source_code; - static inline const std::unordered_map keywords = { - {"def", TokenType::DEF}, - {"return", TokenType::RETURN}, - {"if", TokenType::IF}, - {"else", TokenType::ELSE}, - {"print", TokenType::PRINT}, - {"=", TokenType::ASSIGN}, - {"+", TokenType::PLUS}, - {"-", TokenType::MINUS}, - {"*", TokenType::STAR}, - {"/", TokenType::SLASH}, - {"(", TokenType::LPAREN}, - {")", TokenType::RPAREN}, - {":", TokenType::COLON}, - {",", TokenType::COMMA}, - {"\n", TokenType::NEWLINE}, - {"\t", TokenType::INDENT} - }; std::vector tokens; int start = 0; int current_index = 0; int line = 1; + int column = 1; // FUNCTIONS NEEDED FOR LEXER TO WORK - bool isAtEnd(void); // Checks for last character - char advance(void); // Return current char and move forward - char peek(void); // Sometimes, we don't actually want to read a character and may only want to peek at it - char peekNext(void); // Peak at the next character + bool isAtEnd(); // Checks for last character + char advance(); // Return current char and move forward + char peek(); // Sometimes, we don't actually want to read a character and may only want to peek at it + char peekNext(); // Peak at the next character void addToken(TokenType type); // Specific scanners for complex types - void scanString(void); - void scanNumber(void); - void scanIdentifier(void); + void scanString(std::string first); + void scanNumber(std::string first); + void scanIdentifier(std::string first); std::string preprocess_indents(std::string raw); }; From fa0e7fa45bd46ee5e48087b18e594071ea02e8b0 Mon Sep 17 00:00:00 2001 From: Siddharth Maira Date: Mon, 2 Mar 2026 14:26:16 +0530 Subject: [PATCH 08/15] initial commit to work on other stuff --- src/parser/parser.cpp | 0 src/parser/parser.hpp | 3 +++ 2 files changed, 3 insertions(+) create mode 100644 src/parser/parser.cpp create mode 100644 src/parser/parser.hpp diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/parser/parser.hpp b/src/parser/parser.hpp new file mode 100644 index 0000000..ca5e5bd --- /dev/null +++ b/src/parser/parser.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "token.hpp" From edbc642ebc4d27483a6f4315441c912fe5bfc05b Mon Sep 17 00:00:00 2001 From: Siddharth Maira Date: Tue, 3 Mar 2026 22:02:35 +0530 Subject: [PATCH 09/15] added expression parsing(comments and some operations/types are TODO) --- src/common/token/ast.cpp | 24 +++++ src/common/token/ast.hpp | 93 +++++++++++++++++ src/common/token/token.cpp | 5 +- src/lexer/lexer.cpp | 4 +- src/parser/exprparser.cpp | 206 +++++++++++++++++++++++++++++++++++++ src/parser/exprparser.hpp | 38 +++++++ src/parser/parser.cpp | 0 src/parser/parser.hpp | 3 - 8 files changed, 367 insertions(+), 6 deletions(-) create mode 100644 src/common/token/ast.cpp create mode 100644 src/common/token/ast.hpp create mode 100644 src/parser/exprparser.cpp create mode 100644 src/parser/exprparser.hpp delete mode 100644 src/parser/parser.cpp delete mode 100644 src/parser/parser.hpp diff --git a/src/common/token/ast.cpp b/src/common/token/ast.cpp new file mode 100644 index 0000000..03012b0 --- /dev/null +++ b/src/common/token/ast.cpp @@ -0,0 +1,24 @@ +#include "ast.hpp" + +ASTNode::ASTNode(ASTNodeType type) + : type(type) {} + +BinaryOperatorNode::BinaryOperatorNode( + OperatorType op, + std::unique_ptr lhs, + std::unique_ptr rhs) + : ASTNode(ASTNodeType::BINARY), op(op), lhs(std::move(lhs)), rhs(std::move(rhs)) {} + +UnaryOperatorNode::UnaryOperatorNode( + OperatorType op, + std::unique_ptr rhs) + : ASTNode(ASTNodeType::UNARY), op(op), rhs(std::move(rhs)) {} + +StringNode::StringNode(std::string value) + : ASTNode(ASTNodeType::STRING), value(std::move(value)) {} + +NumberNode::NumberNode(double value) + : ASTNode(ASTNodeType::NUMBER), value(value) {} + +ReferenceNode::ReferenceNode(std::string name) + : ASTNode(ASTNodeType::REFERENCE), name(std::move(name)) {} diff --git a/src/common/token/ast.hpp b/src/common/token/ast.hpp new file mode 100644 index 0000000..ccb3477 --- /dev/null +++ b/src/common/token/ast.hpp @@ -0,0 +1,93 @@ +#pragma once + +#include +#include + +enum class ASTNodeType { + BINARY, //binary operators + UNARY, //unary operators + STRING, //string literals + NUMBER, //number literals + REFERENCE //variable(identifier) references +}; + +enum class OperatorType { + //assignment + ASSIGN, // = + + //logical + OR, // or + AND, // and + NOT, // not + + //comparisons + GREATERTHAN, // > + GREATERTHANEQ, // >= + LESSTHANEQ, // <= + LESSERTHAN, // < + EQUALS, // == + NOTEQUALS, // != + + //additive/unary + PLUS, // + + MINUS, // - + + //multiplicative + STAR, // * + SLASH, // / + DOUBLESLASH, // // + MODULO, // % + + //power + POWER, // ** +}; + +//abstract ASTNode class +class ASTNode { +public: + ASTNode(ASTNodeType type); + virtual ~ASTNode() = default; + + //type + ASTNodeType type; +}; + +class BinaryOperatorNode : public ASTNode { +public: + BinaryOperatorNode(OperatorType op, std::unique_ptr lhs, std::unique_ptr rhs); + + //operator type + OperatorType op; + std::unique_ptr lhs; + std::unique_ptr rhs; +}; + +class UnaryOperatorNode : public ASTNode { +public: + UnaryOperatorNode(OperatorType op, std::unique_ptr rhs); + + //operator type + OperatorType op; + std::unique_ptr rhs; +}; + +class StringNode : public ASTNode { +public: + StringNode(std::string value); + + std::string value; +}; + +class NumberNode : public ASTNode { +public: + NumberNode(double value); + + double value; +}; + +class ReferenceNode : public ASTNode { +public: + ReferenceNode(std::string name); + + std::string name; +}; diff --git a/src/common/token/token.cpp b/src/common/token/token.cpp index cc33e7e..4804e0a 100644 --- a/src/common/token/token.cpp +++ b/src/common/token/token.cpp @@ -1,5 +1,6 @@ -#include #include -Token::Token(TokenType type, std::string val, int l, int c) : type(type), value(val), line(l), column(c){} +#include "token.hpp" +Token::Token(TokenType type, std::string val, int l, int c) + : type(type), value(val), line(l), column(c) {} diff --git a/src/lexer/lexer.cpp b/src/lexer/lexer.cpp index 54dcd69..6c8ac35 100644 --- a/src/lexer/lexer.cpp +++ b/src/lexer/lexer.cpp @@ -4,7 +4,9 @@ #include #include -Lexer::Lexer(std::string input_string) : source_code(input_string){} +Lexer::Lexer(std::string input_string) + : source_code(input_string){} + bool Lexer::isAtEnd(){ if (current_index >= source_code.size()){ return true; diff --git a/src/parser/exprparser.cpp b/src/parser/exprparser.cpp new file mode 100644 index 0000000..a6f5224 --- /dev/null +++ b/src/parser/exprparser.cpp @@ -0,0 +1,206 @@ +#include "exprparser.hpp" + +ExprParser::ExprParser(std::vector tokens) + : tokens(tokens) {} + +Token ExprParser::peek() { + if (index < tokens.size()) return tokens[index]; + else return tokens.back(); //EOF token +} + +Token ExprParser::peekNext() { + if (index+1 < tokens.size()) return tokens[index+1]; + else return tokens.back(); //EOF token +} + +void advance() { + if (index < tokens.size()) index++; +} + +bool ExprParser::match(TokenType type) { + if (index < tokens.size() && peek().type == type) return true; + else return false; +} + +OperatorType ExprParser::toOperatorType(TokenType type) { + switch (type) { + //comparison + case TokenType::GREATERTHAN: return OperatorType::GREATERTHAN; + case TokenType::LESSTHAN: return OperatorType::LESSTHAN; + case TokenType::GREATERTHANEQ: return OperatorType::GREATERTHANEQ; + case TokenType::LESSTHANEQ: return OperatorType::LESSTHANEQ; + case TokenType::EQUALS: return OperatorType::EQUALS; + case TokenType::NOTEQUALS: return OperatorType::NOTEQUALS; + + //additive + case TokenType::PLUS: return OperatorType::PLUS; + case TokenType::MINUS: return OperatorType::MINUS; + + //multiplicative + case TokenType::STAR: return OperatorType::STAR; + case TokenType::SLASH: return OperatorType::SLASH; + case TokenType::DOUBLESLASH: return OperatorType::DOUBLESLASH; + case TokenType::MODULO: return OperatorType::MODULO; + + default: + //never supposed to happen + throw std::runtime_error("unexpected operator"); + } +} + +std::unique_ptr ExprParser::parseExprStmt() { + return parseAssignment(); +} + +std::unique_ptr ExprParser::parseExpr() { + return parseLogicalOr(); +} + +std::unique_ptr ExprParser::parseAssignment() { + auto lhs = parseLogicalOr(); + + //right associative + if (match(TokenType::ASSIGN)) { + //checking for assignable target + if (lhs->type != ASTNodeType::REFERENCE) { + //parsing error(implementation to be decided still, this is a placeholder) + throw std::runtime_error("invalid assignment target"); + } + + advance(); + auto rhs = parseAssignment(); + return std::make_unique(OperatorType::ASSIGN, std::move(lhs), std::move(rhs)); + } + + return std::move(lhs); +} + +std::unique_ptr ExprParser::parseLogicalOr() { + auto lhs = parseLogicalAnd(); + + //left associative + while (match(TokenType::OR)) { + advance(); + auto rhs = parseLogicalAnd(); + lhs = std::make_unique(OperatorType::OR, std::move(lhs), std::move(rhs)); + } + + return std::move(lhs); +} + +std::unique_ptr ExprParser::parseLogicalAnd() { + auto lhs = parseLogicalNot(); + + //left associative + while (match(TokenType::AND)) { + advance(); + auto rhs = parseLogicalNot(); + lhs = std::make_unique(OperatorType::AND, std::move(lhs), std::move(rhs)); + } + + return std::move(lhs); +} + +std::unique_ptr ExprParser::parseLogicalNot() { + //right associative + if (match(TokenType::NOT)) { + advance(); + auto rhs = parseLogicalNot(); + return std::make_unique(OperatorType::NOT, std::move(rhs)); + } + + return parseComparison(); +} + +std::unique_ptr ExprParser::parseComparison() { + auto lhs = parseAdditive(); + + //left associative + while ( + match(TokenType::GREATERTHAN) || + match(TokenType::LESSTHAN) || + match(TokenType::GREATERTHANEQ) || + match(TokenType::LESSTHANEQ) || + match(TokenType::EQUALS) || + match(TokenType::NOTEQUALS) + ) { + + } +} + +std::unique_ptr ExprParser::parseAdditive() { + auto lhs = parseMultiplicative(); + + //left associative + while ( + match(TokenType::PLUS) || + match(TokenType::MINUS) + ) { + TokenType type = peek().type; + advance(); + auto rhs = parseMultiplicative(); + lhs = std::make_unique(toOperatorType(type), std::move(lhs), std::move(rhs)); + } + + return std::move(lhs); +} + +std::unique_ptr ExprParser::parseMultiplicative() { + auto lhs = parseUnary(); + + //left associative + while ( + match(TokenType::STAR) || + match(TokenType::SLASH) || + match(TokenType::DOUBLESLASH) || + match(TokenType::MODULO) + ) { + TokenType type = peek().type; + advance(); + auto rhs = parseUnary(); + lhs = std::make_unique(toOperatorType(type), std::move(lhs), std::move(rhs)); + } + + return std::move(lhs); +} + +std::unique_ptr ExprParser::parseUnary() { + //right associative + if ( + match(TokenType::PLUS) || + match(TokenType::MINUS) + ) { + TokenType type = peek().type; + advance(); + auto rhs = parseUnary(); + return std::make_unique(toOperatorType(type), std::move(rhs)); + } + + return parsePrimary(); +} + +std::unique_ptr ExprParser::parsePrimary() { + if (match(TokenType::LPAREN)) { + advance(); + auto expr = parseExpr(); + + if (!match(TokenType::RPAREN)) { + throw std::runtime_error("expected closing parenthesis"); + } + return expr; + } + + token = peek(); + advance(); + switch (token.type) { + case TokenType::NUMBER: + double value = std::stod(token.value); + return make_unique(value); + case: TokenType::STRING: + return make_unique(std::move(token.value)); + case: TokenType::REFERENCE: + return make_unique(std::move(token.value)); + default: + throw std::runtime_error("invalid token found"); + } +} diff --git a/src/parser/exprparser.hpp b/src/parser/exprparser.hpp new file mode 100644 index 0000000..df3a739 --- /dev/null +++ b/src/parser/exprparser.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +#include "token.hpp" +#include "ast.hpp" + +class ExprParser { +public: + ExprParser(std::vector tokens); + std::unique_ptr parseExpr(); + std::unique_ptr parseExprStmt(); + +private: + //precedence parsing(from highest precedence to lowest precedence) + std::unique_ptr parsePrimary(); + std::unique_ptr parsePower(); + std::unique_ptr parseUnary(); + std::unique_ptr parseMultiplicative(); + std::unique_ptr parseAdditive(); + std::unique_ptr parseComparison(); + std::unique_ptr parseLogicalNot(); + std::unique_ptr parseLogicalAnd(); + std::unique_ptr parseLogicalOr(); + std::unique_ptr parseAssignment(); + + //helpers + Token peek(); + Token peekNext(); + void advance(); + bool match(TokenType type); + OperatorType toOperatorType(TokenType type); + + //index in the token vector + int index; +}; diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/parser/parser.hpp b/src/parser/parser.hpp deleted file mode 100644 index ca5e5bd..0000000 --- a/src/parser/parser.hpp +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#include "token.hpp" From 5ce753cf936abb3f5d5f8c7099061d4cf590c8c6 Mon Sep 17 00:00:00 2001 From: Siddharth Maira Date: Wed, 4 Mar 2026 15:26:40 +0530 Subject: [PATCH 10/15] added bool, None and comparison parsing(for now) --- src/common/ast/ast.cpp | 30 ++++++++++++ src/common/ast/ast.hpp | 107 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 src/common/ast/ast.cpp create mode 100644 src/common/ast/ast.hpp diff --git a/src/common/ast/ast.cpp b/src/common/ast/ast.cpp new file mode 100644 index 0000000..7c2cd49 --- /dev/null +++ b/src/common/ast/ast.cpp @@ -0,0 +1,30 @@ +#include "ast.hpp" + +ASTNode::ASTNode(ASTNodeType type) + : type(type) {} + +BinaryOperatorNode::BinaryOperatorNode( + OperatorType op, + std::unique_ptr lhs, + std::unique_ptr rhs) + : ASTNode(ASTNodeType::BINARY), op(op), lhs(std::move(lhs)), rhs(std::move(rhs)) {} + +UnaryOperatorNode::UnaryOperatorNode( + OperatorType op, + std::unique_ptr rhs) + : ASTNode(ASTNodeType::UNARY), op(op), rhs(std::move(rhs)) {} + +StringNode::StringNode(std::string value) + : ASTNode(ASTNodeType::STRING), value(std::move(value)) {} + +NumberNode::NumberNode(double value) + : ASTNode(ASTNodeType::NUMBER), value(value) {} + +BooleanNode::BooleanNode(bool value) + : ASTNode(ASTNodeType::BOOLEAN), value(value) {} + +NoneNode::NoneNode() + : ASTNode(ASTNodeType::NONE) {} + +ReferenceNode::ReferenceNode(std::string name) + : ASTNode(ASTNodeType::REFERENCE), name(std::move(name)) {} diff --git a/src/common/ast/ast.hpp b/src/common/ast/ast.hpp new file mode 100644 index 0000000..7910995 --- /dev/null +++ b/src/common/ast/ast.hpp @@ -0,0 +1,107 @@ +#pragma once + +#include +#include + +enum class ASTNodeType { + BINARY, //binary operators + UNARY, //unary operators + STRING, //string literals + NUMBER, //number literals + BOOLEAN, //boolean literals + NONE, //None + REFERENCE //variable(identifier) references +}; + +enum class OperatorType { + //assignment + ASSIGN, // = + + //logical + OR, // or + AND, // and + NOT, // not + + //comparisons + GREATERTHAN, // > + GREATEREQUAL, // >= + LESSEQUAL, // <= + LESSERTHAN, // < + EQEQUAL, // == + NOTEQUAL, // != + + //additive/unary + PLUS, // + + MINUS, // - + + //multiplicative + STAR, // * + SLASH, // / + DOUBLESLASH, // // + MODULO, // % + + //power + POWER, // ** +}; + +//abstract ASTNode class +class ASTNode { +public: + ASTNode(ASTNodeType type); + virtual ~ASTNode() = default; + + //type + ASTNodeType type; +}; + +class BinaryOperatorNode : public ASTNode { +public: + BinaryOperatorNode(OperatorType op, std::unique_ptr lhs, std::unique_ptr rhs); + + //operator type + OperatorType op; + std::unique_ptr lhs; + std::unique_ptr rhs; +}; + +class UnaryOperatorNode : public ASTNode { +public: + UnaryOperatorNode(OperatorType op, std::unique_ptr rhs); + + //operator type + OperatorType op; + std::unique_ptr rhs; +}; + +class StringNode : public ASTNode { +public: + StringNode(std::string value); + + std::string value; +}; + +class NumberNode : public ASTNode { +public: + NumberNode(double value); + + double value; +}; + +class BooleanNode : public ASTNode { +public: + BooleanNode(bool value); + + bool value; +} + +class NoneNode : public ASTNode { +public: + NoneNode(); +} + +class ReferenceNode : public ASTNode { +public: + ReferenceNode(std::string name); + + std::string name; +}; From 64681156ed00618a6056c796541a96b81a1e9704 Mon Sep 17 00:00:00 2001 From: Siddharth Maira Date: Wed, 4 Mar 2026 15:32:52 +0530 Subject: [PATCH 11/15] added config files(like .vscode) to gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 80a6dbe..2e590e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ #build directory build/ +# Config files +.*/ + # Prerequisites *.d From 3d468e6e87b77d057de49e356ead1e70cc6a6c15 Mon Sep 17 00:00:00 2001 From: Siddharth Maira Date: Wed, 4 Mar 2026 15:34:41 +0530 Subject: [PATCH 12/15] added .vscode to gitignore and remove the general .*/ rule --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2e590e7..b4c3726 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ build/ # Config files -.*/ +.vscode # Prerequisites *.d From e6686e5d2537fb3a8456d1597cd3d1db578bbdff Mon Sep 17 00:00:00 2001 From: Siddharth Maira Date: Fri, 6 Mar 2026 16:23:53 +0530 Subject: [PATCH 13/15] changed all ASTNode occurences to ASTExprNode to remove ambiguity --- src/common/ast/ast.cpp | 30 -------------------- src/common/ast/astexpr.cpp | 30 ++++++++++++++++++++ src/common/ast/{ast.hpp => astexpr.hpp} | 37 ++++++++++++------------- 3 files changed, 47 insertions(+), 50 deletions(-) delete mode 100644 src/common/ast/ast.cpp create mode 100644 src/common/ast/astexpr.cpp rename src/common/ast/{ast.hpp => astexpr.hpp} (60%) diff --git a/src/common/ast/ast.cpp b/src/common/ast/ast.cpp deleted file mode 100644 index 7c2cd49..0000000 --- a/src/common/ast/ast.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "ast.hpp" - -ASTNode::ASTNode(ASTNodeType type) - : type(type) {} - -BinaryOperatorNode::BinaryOperatorNode( - OperatorType op, - std::unique_ptr lhs, - std::unique_ptr rhs) - : ASTNode(ASTNodeType::BINARY), op(op), lhs(std::move(lhs)), rhs(std::move(rhs)) {} - -UnaryOperatorNode::UnaryOperatorNode( - OperatorType op, - std::unique_ptr rhs) - : ASTNode(ASTNodeType::UNARY), op(op), rhs(std::move(rhs)) {} - -StringNode::StringNode(std::string value) - : ASTNode(ASTNodeType::STRING), value(std::move(value)) {} - -NumberNode::NumberNode(double value) - : ASTNode(ASTNodeType::NUMBER), value(value) {} - -BooleanNode::BooleanNode(bool value) - : ASTNode(ASTNodeType::BOOLEAN), value(value) {} - -NoneNode::NoneNode() - : ASTNode(ASTNodeType::NONE) {} - -ReferenceNode::ReferenceNode(std::string name) - : ASTNode(ASTNodeType::REFERENCE), name(std::move(name)) {} diff --git a/src/common/ast/astexpr.cpp b/src/common/ast/astexpr.cpp new file mode 100644 index 0000000..6235666 --- /dev/null +++ b/src/common/ast/astexpr.cpp @@ -0,0 +1,30 @@ +#include "astexpr.hpp" + +ASTExprNode::ASTExprNode(ASTExprNodeType type) + : type(type) {} + +BinaryOperatorNode::BinaryOperatorNode( + OperatorType op, + std::unique_ptr lhs, + std::unique_ptr rhs) + : ASTExprNode(ASTExprNodeType::BINARY), op(op), lhs(std::move(lhs)), rhs(std::move(rhs)) {} + +UnaryOperatorNode::UnaryOperatorNode( + OperatorType op, + std::unique_ptr rhs) + : ASTExprNode(ASTExprNodeType::UNARY), op(op), rhs(std::move(rhs)) {} + +StringNode::StringNode(std::string value) + : ASTExprNode(ASTExprNodeType::STRING), value(std::move(value)) {} + +NumberNode::NumberNode(double value) + : ASTExprNode(ASTExprNodeType::NUMBER), value(value) {} + +BooleanNode::BooleanNode(bool value) + : ASTExprNode(ASTExprNodeType::BOOLEAN), value(value) {} + +NoneNode::NoneNode() + : ASTExprNode(ASTExprNodeType::NONE) {} + +ReferenceNode::ReferenceNode(std::string name) + : ASTExprNode(ASTExprNodeType::REFERENCE), name(std::move(name)) {} diff --git a/src/common/ast/ast.hpp b/src/common/ast/astexpr.hpp similarity index 60% rename from src/common/ast/ast.hpp rename to src/common/ast/astexpr.hpp index 7910995..83cbb79 100644 --- a/src/common/ast/ast.hpp +++ b/src/common/ast/astexpr.hpp @@ -3,7 +3,7 @@ #include #include -enum class ASTNodeType { +enum class ASTExprNodeType { BINARY, //binary operators UNARY, //unary operators STRING, //string literals @@ -14,9 +14,6 @@ enum class ASTNodeType { }; enum class OperatorType { - //assignment - ASSIGN, // = - //logical OR, // or AND, // and @@ -44,62 +41,62 @@ enum class OperatorType { POWER, // ** }; -//abstract ASTNode class -class ASTNode { +//abstract ASTExprNode class +class ASTExprNode { public: - ASTNode(ASTNodeType type); + ASTExprNode(ASTExprNodeType type); virtual ~ASTNode() = default; //type - ASTNodeType type; + ASTExprNodeType type; }; -class BinaryOperatorNode : public ASTNode { +class BinaryOperatorNode : public ASTExprNode { public: - BinaryOperatorNode(OperatorType op, std::unique_ptr lhs, std::unique_ptr rhs); + BinaryOperatorNode(OperatorType op, std::unique_ptr lhs, std::unique_ptr rhs); //operator type OperatorType op; - std::unique_ptr lhs; - std::unique_ptr rhs; + std::unique_ptr lhs; + std::unique_ptr rhs; }; -class UnaryOperatorNode : public ASTNode { +class UnaryOperatorNode : public ASTExprNode { public: - UnaryOperatorNode(OperatorType op, std::unique_ptr rhs); + UnaryOperatorNode(OperatorType op, std::unique_ptr rhs); //operator type OperatorType op; - std::unique_ptr rhs; + std::unique_ptr rhs; }; -class StringNode : public ASTNode { +class StringNode : public ASTExprNode { public: StringNode(std::string value); std::string value; }; -class NumberNode : public ASTNode { +class NumberNode : public ASTExprNode { public: NumberNode(double value); double value; }; -class BooleanNode : public ASTNode { +class BooleanNode : public ASTExprNode { public: BooleanNode(bool value); bool value; } -class NoneNode : public ASTNode { +class NoneNode : public ASTExprNode { public: NoneNode(); } -class ReferenceNode : public ASTNode { +class ReferenceNode : public ASTExprNode { public: ReferenceNode(std::string name); From 5b22b69da8ad8e5fdba146a557ae3177bfd3087b Mon Sep 17 00:00:00 2001 From: Siddharth Maira Date: Fri, 6 Mar 2026 16:32:31 +0530 Subject: [PATCH 14/15] remove assignment from expression parsing --- src/common/token/ast.cpp | 24 ---------- src/common/token/ast.hpp | 93 --------------------------------------- src/parser/exprparser.cpp | 78 +++++++++++++++----------------- src/parser/exprparser.hpp | 24 +++++----- 4 files changed, 46 insertions(+), 173 deletions(-) delete mode 100644 src/common/token/ast.cpp delete mode 100644 src/common/token/ast.hpp diff --git a/src/common/token/ast.cpp b/src/common/token/ast.cpp deleted file mode 100644 index 03012b0..0000000 --- a/src/common/token/ast.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "ast.hpp" - -ASTNode::ASTNode(ASTNodeType type) - : type(type) {} - -BinaryOperatorNode::BinaryOperatorNode( - OperatorType op, - std::unique_ptr lhs, - std::unique_ptr rhs) - : ASTNode(ASTNodeType::BINARY), op(op), lhs(std::move(lhs)), rhs(std::move(rhs)) {} - -UnaryOperatorNode::UnaryOperatorNode( - OperatorType op, - std::unique_ptr rhs) - : ASTNode(ASTNodeType::UNARY), op(op), rhs(std::move(rhs)) {} - -StringNode::StringNode(std::string value) - : ASTNode(ASTNodeType::STRING), value(std::move(value)) {} - -NumberNode::NumberNode(double value) - : ASTNode(ASTNodeType::NUMBER), value(value) {} - -ReferenceNode::ReferenceNode(std::string name) - : ASTNode(ASTNodeType::REFERENCE), name(std::move(name)) {} diff --git a/src/common/token/ast.hpp b/src/common/token/ast.hpp deleted file mode 100644 index ccb3477..0000000 --- a/src/common/token/ast.hpp +++ /dev/null @@ -1,93 +0,0 @@ -#pragma once - -#include -#include - -enum class ASTNodeType { - BINARY, //binary operators - UNARY, //unary operators - STRING, //string literals - NUMBER, //number literals - REFERENCE //variable(identifier) references -}; - -enum class OperatorType { - //assignment - ASSIGN, // = - - //logical - OR, // or - AND, // and - NOT, // not - - //comparisons - GREATERTHAN, // > - GREATERTHANEQ, // >= - LESSTHANEQ, // <= - LESSERTHAN, // < - EQUALS, // == - NOTEQUALS, // != - - //additive/unary - PLUS, // + - MINUS, // - - - //multiplicative - STAR, // * - SLASH, // / - DOUBLESLASH, // // - MODULO, // % - - //power - POWER, // ** -}; - -//abstract ASTNode class -class ASTNode { -public: - ASTNode(ASTNodeType type); - virtual ~ASTNode() = default; - - //type - ASTNodeType type; -}; - -class BinaryOperatorNode : public ASTNode { -public: - BinaryOperatorNode(OperatorType op, std::unique_ptr lhs, std::unique_ptr rhs); - - //operator type - OperatorType op; - std::unique_ptr lhs; - std::unique_ptr rhs; -}; - -class UnaryOperatorNode : public ASTNode { -public: - UnaryOperatorNode(OperatorType op, std::unique_ptr rhs); - - //operator type - OperatorType op; - std::unique_ptr rhs; -}; - -class StringNode : public ASTNode { -public: - StringNode(std::string value); - - std::string value; -}; - -class NumberNode : public ASTNode { -public: - NumberNode(double value); - - double value; -}; - -class ReferenceNode : public ASTNode { -public: - ReferenceNode(std::string name); - - std::string name; -}; diff --git a/src/parser/exprparser.cpp b/src/parser/exprparser.cpp index a6f5224..6888292 100644 --- a/src/parser/exprparser.cpp +++ b/src/parser/exprparser.cpp @@ -1,3 +1,5 @@ +#include + #include "exprparser.hpp" ExprParser::ExprParser(std::vector tokens) @@ -27,10 +29,10 @@ OperatorType ExprParser::toOperatorType(TokenType type) { //comparison case TokenType::GREATERTHAN: return OperatorType::GREATERTHAN; case TokenType::LESSTHAN: return OperatorType::LESSTHAN; - case TokenType::GREATERTHANEQ: return OperatorType::GREATERTHANEQ; - case TokenType::LESSTHANEQ: return OperatorType::LESSTHANEQ; - case TokenType::EQUALS: return OperatorType::EQUALS; - case TokenType::NOTEQUALS: return OperatorType::NOTEQUALS; + case TokenType::GREATEREQUAL: return OperatorType::GREATEREQUAL; + case TokenType::LESSEQUAL: return OperatorType::LESSEQUAL; + case TokenType::EQEQUAL: return OperatorType::EQEQUAL; + case TokenType::NOTEQUAL: return OperatorType::NOTEQUAL; //additive case TokenType::PLUS: return OperatorType::PLUS; @@ -48,34 +50,11 @@ OperatorType ExprParser::toOperatorType(TokenType type) { } } -std::unique_ptr ExprParser::parseExprStmt() { - return parseAssignment(); -} - -std::unique_ptr ExprParser::parseExpr() { +std::unique_ptr ExprParser::parseExpr() { return parseLogicalOr(); } -std::unique_ptr ExprParser::parseAssignment() { - auto lhs = parseLogicalOr(); - - //right associative - if (match(TokenType::ASSIGN)) { - //checking for assignable target - if (lhs->type != ASTNodeType::REFERENCE) { - //parsing error(implementation to be decided still, this is a placeholder) - throw std::runtime_error("invalid assignment target"); - } - - advance(); - auto rhs = parseAssignment(); - return std::make_unique(OperatorType::ASSIGN, std::move(lhs), std::move(rhs)); - } - - return std::move(lhs); -} - -std::unique_ptr ExprParser::parseLogicalOr() { +std::unique_ptr ExprParser::parseLogicalOr() { auto lhs = parseLogicalAnd(); //left associative @@ -88,7 +67,7 @@ std::unique_ptr ExprParser::parseLogicalOr() { return std::move(lhs); } -std::unique_ptr ExprParser::parseLogicalAnd() { +std::unique_ptr ExprParser::parseLogicalAnd() { auto lhs = parseLogicalNot(); //left associative @@ -101,7 +80,7 @@ std::unique_ptr ExprParser::parseLogicalAnd() { return std::move(lhs); } -std::unique_ptr ExprParser::parseLogicalNot() { +std::unique_ptr ExprParser::parseLogicalNot() { //right associative if (match(TokenType::NOT)) { advance(); @@ -112,23 +91,28 @@ std::unique_ptr ExprParser::parseLogicalNot() { return parseComparison(); } -std::unique_ptr ExprParser::parseComparison() { +std::unique_ptr ExprParser::parseComparison() { auto lhs = parseAdditive(); //left associative while ( match(TokenType::GREATERTHAN) || match(TokenType::LESSTHAN) || - match(TokenType::GREATERTHANEQ) || - match(TokenType::LESSTHANEQ) || - match(TokenType::EQUALS) || - match(TokenType::NOTEQUALS) + match(TokenType::GREATEREQUAL) || + match(TokenType::LESSEQUAL) || + match(TokenType::EQEQUAL) || + match(TokenType::NOTEQUAL) ) { - + TokenType type = peek().type; + advance(); + auto rhs = parseAdditive(); + lhs = std::make_unique(toOperatorType(type), std::move(lhs), std::move(rhs)); } + + return std::move(lhs); } -std::unique_ptr ExprParser::parseAdditive() { +std::unique_ptr ExprParser::parseAdditive() { auto lhs = parseMultiplicative(); //left associative @@ -145,7 +129,7 @@ std::unique_ptr ExprParser::parseAdditive() { return std::move(lhs); } -std::unique_ptr ExprParser::parseMultiplicative() { +std::unique_ptr ExprParser::parseMultiplicative() { auto lhs = parseUnary(); //left associative @@ -164,7 +148,7 @@ std::unique_ptr ExprParser::parseMultiplicative() { return std::move(lhs); } -std::unique_ptr ExprParser::parseUnary() { +std::unique_ptr ExprParser::parseUnary() { //right associative if ( match(TokenType::PLUS) || @@ -179,7 +163,7 @@ std::unique_ptr ExprParser::parseUnary() { return parsePrimary(); } -std::unique_ptr ExprParser::parsePrimary() { +std::unique_ptr ExprParser::parsePrimary() { if (match(TokenType::LPAREN)) { advance(); auto expr = parseExpr(); @@ -187,6 +171,8 @@ std::unique_ptr ExprParser::parsePrimary() { if (!match(TokenType::RPAREN)) { throw std::runtime_error("expected closing parenthesis"); } + advance(); + return expr; } @@ -196,9 +182,15 @@ std::unique_ptr ExprParser::parsePrimary() { case TokenType::NUMBER: double value = std::stod(token.value); return make_unique(value); - case: TokenType::STRING: + case TokenType::STRING: return make_unique(std::move(token.value)); - case: TokenType::REFERENCE: + case TokenType::TRUE: + return make_unique(true); + case TokenType::FALSE: + return make_unique(false); + case TokenType::NONE: + return make_unique(); + case TokenType::REFERENCE: return make_unique(std::move(token.value)); default: throw std::runtime_error("invalid token found"); diff --git a/src/parser/exprparser.hpp b/src/parser/exprparser.hpp index df3a739..5694052 100644 --- a/src/parser/exprparser.hpp +++ b/src/parser/exprparser.hpp @@ -5,26 +5,24 @@ #include #include "token.hpp" -#include "ast.hpp" +#include "astexpr.hpp" class ExprParser { public: ExprParser(std::vector tokens); - std::unique_ptr parseExpr(); - std::unique_ptr parseExprStmt(); + std::unique_ptr parseExpr(); private: //precedence parsing(from highest precedence to lowest precedence) - std::unique_ptr parsePrimary(); - std::unique_ptr parsePower(); - std::unique_ptr parseUnary(); - std::unique_ptr parseMultiplicative(); - std::unique_ptr parseAdditive(); - std::unique_ptr parseComparison(); - std::unique_ptr parseLogicalNot(); - std::unique_ptr parseLogicalAnd(); - std::unique_ptr parseLogicalOr(); - std::unique_ptr parseAssignment(); + std::unique_ptr parsePrimary(); + std::unique_ptr parsePower(); + std::unique_ptr parseUnary(); + std::unique_ptr parseMultiplicative(); + std::unique_ptr parseAdditive(); + std::unique_ptr parseComparison(); + std::unique_ptr parseLogicalNot(); + std::unique_ptr parseLogicalAnd(); + std::unique_ptr parseLogicalOr(); //helpers Token peek(); From 342fcd2f53a389de100a57ad85b9b52db26d67f4 Mon Sep 17 00:00:00 2001 From: Siddharth Maira Date: Fri, 6 Mar 2026 16:52:31 +0530 Subject: [PATCH 15/15] copied formatting from remote main --- .clang-format | 28 ++++++++ Makefile | 8 ++- src/common/ast/astexpr.cpp | 22 ++---- src/common/token/token.cpp | 4 +- src/lexer/lexer.cpp | 119 ++++++++++++++++---------------- src/parser/exprparser.cpp | 134 ++++++++++++++++++++----------------- 6 files changed, 171 insertions(+), 144 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..e7dbe41 --- /dev/null +++ b/.clang-format @@ -0,0 +1,28 @@ +--- +Language: Cpp +BasedOnStyle: Google + +# Basic Formatting +IndentWidth: 4 +ColumnLimit: 100 +TabWidth: 4 +UseTab: Never + +# Braces and Spacing +BreakBeforeBraces: Attach +AllowShortBlocksOnASingleLine: Empty +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false + +# Pointers and References (e.g., int* ptr instead of int *ptr) +PointerAlignment: Left + +# Alignment for readability +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: false +AlignOperands: Align +AlignTrailingComments: true + +# Includes +SortIncludes: true diff --git a/Makefile b/Makefile index e82cc23..c2b3da2 100644 --- a/Makefile +++ b/Makefile @@ -33,10 +33,16 @@ $(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp #for change in header files -include $(DEPS) -.PHONY: all clean run +.PHONY: all clean run format check-format run: all ./$(BUILD_DIR)/$(TARGET_EXEC) clean: rm -rf $(BUILD_DIR) + +format: + find $(SRC_DIR)/ -name '*.cpp' -o -name '*.h' | xargs clang-format -i + +check-format: + find $(SRC_DIR)/ -name '*.cpp' -o -name '*.h' | xargs clang-format --dry-run --Werror diff --git a/src/common/ast/astexpr.cpp b/src/common/ast/astexpr.cpp index 6235666..996bafa 100644 --- a/src/common/ast/astexpr.cpp +++ b/src/common/ast/astexpr.cpp @@ -1,30 +1,22 @@ #include "astexpr.hpp" -ASTExprNode::ASTExprNode(ASTExprNodeType type) - : type(type) {} +ASTExprNode::ASTExprNode(ASTExprNodeType type) : type(type) {} -BinaryOperatorNode::BinaryOperatorNode( - OperatorType op, - std::unique_ptr lhs, - std::unique_ptr rhs) +BinaryOperatorNode::BinaryOperatorNode(OperatorType op, std::unique_ptr lhs, + std::unique_ptr rhs) : ASTExprNode(ASTExprNodeType::BINARY), op(op), lhs(std::move(lhs)), rhs(std::move(rhs)) {} -UnaryOperatorNode::UnaryOperatorNode( - OperatorType op, - std::unique_ptr rhs) +UnaryOperatorNode::UnaryOperatorNode(OperatorType op, std::unique_ptr rhs) : ASTExprNode(ASTExprNodeType::UNARY), op(op), rhs(std::move(rhs)) {} StringNode::StringNode(std::string value) : ASTExprNode(ASTExprNodeType::STRING), value(std::move(value)) {} -NumberNode::NumberNode(double value) - : ASTExprNode(ASTExprNodeType::NUMBER), value(value) {} +NumberNode::NumberNode(double value) : ASTExprNode(ASTExprNodeType::NUMBER), value(value) {} -BooleanNode::BooleanNode(bool value) - : ASTExprNode(ASTExprNodeType::BOOLEAN), value(value) {} +BooleanNode::BooleanNode(bool value) : ASTExprNode(ASTExprNodeType::BOOLEAN), value(value) {} -NoneNode::NoneNode() - : ASTExprNode(ASTExprNodeType::NONE) {} +NoneNode::NoneNode() : ASTExprNode(ASTExprNodeType::NONE) {} ReferenceNode::ReferenceNode(std::string name) : ASTExprNode(ASTExprNodeType::REFERENCE), name(std::move(name)) {} diff --git a/src/common/token/token.cpp b/src/common/token/token.cpp index 4804e0a..59c1123 100644 --- a/src/common/token/token.cpp +++ b/src/common/token/token.cpp @@ -1,6 +1,6 @@ -#include - #include "token.hpp" +#include + Token::Token(TokenType type, std::string val, int l, int c) : type(type), value(val), line(l), column(c) {} diff --git a/src/lexer/lexer.cpp b/src/lexer/lexer.cpp index 6c8ac35..bcc8a7a 100644 --- a/src/lexer/lexer.cpp +++ b/src/lexer/lexer.cpp @@ -1,119 +1,112 @@ -#include #include #include -#include #include +#include +#include -Lexer::Lexer(std::string input_string) - : source_code(input_string){} +Lexer::Lexer(std::string input_string) : source_code(input_string) {} -bool Lexer::isAtEnd(){ - if (current_index >= source_code.size()){ +bool Lexer::isAtEnd() { + if (current_index >= source_code.size()) { return true; } return false; } -char Lexer::peek(){ - if (current_index >= source_code.size()){ +char Lexer::peek() { + if (current_index >= source_code.size()) { return '\0'; } return source_code[current_index]; } -char Lexer::peekNext(){ - if (current_index+1 >= source_code.size()){ +char Lexer::peekNext() { + if (current_index + 1 >= source_code.size()) { return '\0'; } - return source_code[current_index+1]; + return source_code[current_index + 1]; } -char Lexer::advance(){ - if (current_index >= source_code.size()){ +char Lexer::advance() { + if (current_index >= source_code.size()) { return '\0'; } char c = source_code[current_index++]; - if (c == '\n'){ + if (c == '\n') { line++; - column=1; + column = 1; + } else { + column++; } - else {column++;} return c; } -void Lexer::scanNumber(std::string curr){ - int start = column-1; - while (std::isdigit(peek())){ +void Lexer::scanNumber(std::string curr) { + int start = column - 1; + while (std::isdigit(peek())) { curr += Lexer::advance(); } - if (std::isalnum(peek())){ + if (std::isalnum(peek())) { // throw an error } Token token(TokenType::NUMBER, curr, line, start); tokens.push_back(token); } -void Lexer::scanString(std::string quote){ - int start = column-1; - while (!isAtEnd() && peek()!=quote[0] && peek()!='\n'){ +void Lexer::scanString(std::string quote) { + int start = column - 1; + while (!isAtEnd() && peek() != quote[0] && peek() != '\n') { quote += advance(); } - if (isAtEnd()){ + if (isAtEnd()) { // throw an error - } - else if (peek()=='\n'){ + } else if (peek() == '\n') { // throw an error - } - else{ + } else { quote += advance(); } Token token(TokenType::STRING, quote, line, start); tokens.push_back(token); } -void Lexer::scanIdentifier(std::string curr){ - int start = column-1; - while (std::isalnum(peek()) || peek()=='_'){ +void Lexer::scanIdentifier(std::string curr) { + int start = column - 1; + while (std::isalnum(peek()) || peek() == '_') { curr += advance(); } Token token(TokenType::IDENTIFIER, curr, line, start); - if (keywords.count(curr)){ + if (keywords.count(curr)) { token.type = keywords.at(curr); } tokens.push_back(token); } - -std::vector Lexer::scan_Tokens(){ - while (true){ - if (isAtEnd()){ - Token token(TokenType::EOF_TOKEN, "", line, column); - tokens.push_back(token); - break; - } - std::string curr = ""; - curr += advance(); - if (keywords.count(curr)){ - TokenType type = keywords.at(curr); - if (type == TokenType::NEWLINE){ - column = 0; - line++; - } - else if (type == TokenType::INDENT){ - column += 3; +std::vector Lexer::scan_Tokens() { + while (true) { + if (isAtEnd()) { + Token token(TokenType::EOF_TOKEN, "", line, column); + tokens.push_back(token); + break; } - else if (type == TokenType::DEDENT){ - column -= 5; + std::string curr = ""; + curr += advance(); + if (keywords.count(curr)) { + TokenType type = keywords.at(curr); + if (type == TokenType::NEWLINE) { + column = 0; + line++; + } else if (type == TokenType::INDENT) { + column += 3; + } else if (type == TokenType::DEDENT) { + column -= 5; + } + Token token(type, curr, line, column); + tokens.push_back(token); + } else { + if (std::isdigit(curr[0])) { + scanNumber(curr); + } else if (std::isalpha(curr[0])) { + scanIdentifier(curr); + } } - Token token(type, curr, line, column); - tokens.push_back(token); } - else{ - if (std::isdigit(curr[0])){ - scanNumber(curr); - } - else if (std::isalpha(curr[0])){ - scanIdentifier(curr); - } - } -} } diff --git a/src/parser/exprparser.cpp b/src/parser/exprparser.cpp index 6888292..4a442cd 100644 --- a/src/parser/exprparser.cpp +++ b/src/parser/exprparser.cpp @@ -1,51 +1,69 @@ -#include - #include "exprparser.hpp" -ExprParser::ExprParser(std::vector tokens) - : tokens(tokens) {} +#include + +ExprParser::ExprParser(std::vector tokens) : tokens(tokens) {} Token ExprParser::peek() { - if (index < tokens.size()) return tokens[index]; - else return tokens.back(); //EOF token + if (index < tokens.size()) + return tokens[index]; + else + return tokens.back(); // EOF token } Token ExprParser::peekNext() { - if (index+1 < tokens.size()) return tokens[index+1]; - else return tokens.back(); //EOF token + if (index + 1 < tokens.size()) + return tokens[index + 1]; + else + return tokens.back(); // EOF token } void advance() { - if (index < tokens.size()) index++; + if (index < tokens.size()) + index++; } bool ExprParser::match(TokenType type) { - if (index < tokens.size() && peek().type == type) return true; - else return false; + if (index < tokens.size() && peek().type == type) + return true; + else + return false; } OperatorType ExprParser::toOperatorType(TokenType type) { switch (type) { - //comparison - case TokenType::GREATERTHAN: return OperatorType::GREATERTHAN; - case TokenType::LESSTHAN: return OperatorType::LESSTHAN; - case TokenType::GREATEREQUAL: return OperatorType::GREATEREQUAL; - case TokenType::LESSEQUAL: return OperatorType::LESSEQUAL; - case TokenType::EQEQUAL: return OperatorType::EQEQUAL; - case TokenType::NOTEQUAL: return OperatorType::NOTEQUAL; - - //additive - case TokenType::PLUS: return OperatorType::PLUS; - case TokenType::MINUS: return OperatorType::MINUS; - - //multiplicative - case TokenType::STAR: return OperatorType::STAR; - case TokenType::SLASH: return OperatorType::SLASH; - case TokenType::DOUBLESLASH: return OperatorType::DOUBLESLASH; - case TokenType::MODULO: return OperatorType::MODULO; + // comparison + case TokenType::GREATERTHAN: + return OperatorType::GREATERTHAN; + case TokenType::LESSTHAN: + return OperatorType::LESSTHAN; + case TokenType::GREATEREQUAL: + return OperatorType::GREATEREQUAL; + case TokenType::LESSEQUAL: + return OperatorType::LESSEQUAL; + case TokenType::EQEQUAL: + return OperatorType::EQEQUAL; + case TokenType::NOTEQUAL: + return OperatorType::NOTEQUAL; + + // additive + case TokenType::PLUS: + return OperatorType::PLUS; + case TokenType::MINUS: + return OperatorType::MINUS; + + // multiplicative + case TokenType::STAR: + return OperatorType::STAR; + case TokenType::SLASH: + return OperatorType::SLASH; + case TokenType::DOUBLESLASH: + return OperatorType::DOUBLESLASH; + case TokenType::MODULO: + return OperatorType::MODULO; default: - //never supposed to happen + // never supposed to happen throw std::runtime_error("unexpected operator"); } } @@ -57,11 +75,12 @@ std::unique_ptr ExprParser::parseExpr() { std::unique_ptr ExprParser::parseLogicalOr() { auto lhs = parseLogicalAnd(); - //left associative + // left associative while (match(TokenType::OR)) { advance(); auto rhs = parseLogicalAnd(); - lhs = std::make_unique(OperatorType::OR, std::move(lhs), std::move(rhs)); + lhs = + std::make_unique(OperatorType::OR, std::move(lhs), std::move(rhs)); } return std::move(lhs); @@ -70,18 +89,19 @@ std::unique_ptr ExprParser::parseLogicalOr() { std::unique_ptr ExprParser::parseLogicalAnd() { auto lhs = parseLogicalNot(); - //left associative + // left associative while (match(TokenType::AND)) { advance(); auto rhs = parseLogicalNot(); - lhs = std::make_unique(OperatorType::AND, std::move(lhs), std::move(rhs)); + lhs = + std::make_unique(OperatorType::AND, std::move(lhs), std::move(rhs)); } return std::move(lhs); } std::unique_ptr ExprParser::parseLogicalNot() { - //right associative + // right associative if (match(TokenType::NOT)) { advance(); auto rhs = parseLogicalNot(); @@ -94,19 +114,15 @@ std::unique_ptr ExprParser::parseLogicalNot() { std::unique_ptr ExprParser::parseComparison() { auto lhs = parseAdditive(); - //left associative - while ( - match(TokenType::GREATERTHAN) || - match(TokenType::LESSTHAN) || - match(TokenType::GREATEREQUAL) || - match(TokenType::LESSEQUAL) || - match(TokenType::EQEQUAL) || - match(TokenType::NOTEQUAL) - ) { + // left associative + while (match(TokenType::GREATERTHAN) || match(TokenType::LESSTHAN) || + match(TokenType::GREATEREQUAL) || match(TokenType::LESSEQUAL) || + match(TokenType::EQEQUAL) || match(TokenType::NOTEQUAL)) { TokenType type = peek().type; advance(); auto rhs = parseAdditive(); - lhs = std::make_unique(toOperatorType(type), std::move(lhs), std::move(rhs)); + lhs = std::make_unique(toOperatorType(type), std::move(lhs), + std::move(rhs)); } return std::move(lhs); @@ -115,15 +131,13 @@ std::unique_ptr ExprParser::parseComparison() { std::unique_ptr ExprParser::parseAdditive() { auto lhs = parseMultiplicative(); - //left associative - while ( - match(TokenType::PLUS) || - match(TokenType::MINUS) - ) { + // left associative + while (match(TokenType::PLUS) || match(TokenType::MINUS)) { TokenType type = peek().type; advance(); auto rhs = parseMultiplicative(); - lhs = std::make_unique(toOperatorType(type), std::move(lhs), std::move(rhs)); + lhs = std::make_unique(toOperatorType(type), std::move(lhs), + std::move(rhs)); } return std::move(lhs); @@ -132,28 +146,22 @@ std::unique_ptr ExprParser::parseAdditive() { std::unique_ptr ExprParser::parseMultiplicative() { auto lhs = parseUnary(); - //left associative - while ( - match(TokenType::STAR) || - match(TokenType::SLASH) || - match(TokenType::DOUBLESLASH) || - match(TokenType::MODULO) - ) { + // left associative + while (match(TokenType::STAR) || match(TokenType::SLASH) || match(TokenType::DOUBLESLASH) || + match(TokenType::MODULO)) { TokenType type = peek().type; advance(); auto rhs = parseUnary(); - lhs = std::make_unique(toOperatorType(type), std::move(lhs), std::move(rhs)); + lhs = std::make_unique(toOperatorType(type), std::move(lhs), + std::move(rhs)); } return std::move(lhs); } std::unique_ptr ExprParser::parseUnary() { - //right associative - if ( - match(TokenType::PLUS) || - match(TokenType::MINUS) - ) { + // right associative + if (match(TokenType::PLUS) || match(TokenType::MINUS)) { TokenType type = peek().type; advance(); auto rhs = parseUnary();