commit 74eafbd39c4c622ce2ebdf699102ec7541dfe807
parent e34338219036acf103d161dfbd36fa67597d23e7
Author: Cori Barker <coribarker2@gmail.com>
Date: Mon, 19 Jan 2026 09:36:05 +0000
parser
Diffstat:
4 files changed, 282 insertions(+), 0 deletions(-)
diff --git a/include/parser/ast_node.h b/include/parser/ast_node.h
@@ -0,0 +1,70 @@
+#ifndef AST_NODE_H
+#define AST_NODE_H
+
+#include "parser/node_type.h"
+
+#include <string>
+#include <vector>
+#include <memory>
+
+class ASTNode {
+public:
+ int line;
+ int column;
+
+ virtual ~ASTNode() = default;
+};
+
+class Program : public ASTNode {
+public:
+ std::vector<std::unique_ptr<ASTNode>> declarations;
+};
+
+class Declaration : public ASTNode {
+public:
+ std::string type;
+ std::string var_name;
+ std::unique_ptr<ASTNode> value;
+
+ Declaration(std::string type, std::string var_name, std::unique_ptr<ASTNode> value = nullptr) : type(type), var_name(var_name), value(std::move(value)) {}
+};
+
+class Assignment : public ASTNode {
+public:
+ std::string variable_name;
+ std::unique_ptr<ASTNode> value;
+
+ Assignment(std::string var, std::unique_ptr<ASTNode> val) : variable_name(var), value(std::move(val)) {}
+};
+
+class NumberLiteral : public ASTNode {
+public:
+ double value;
+
+ NumberLiteral(double val) : value(val) {}
+};
+
+class StringLiteral : public ASTNode {
+public:
+ std::string value;
+
+ StringLiteral(std::string val) : value(val) {}
+};
+
+class Identifier : public ASTNode {
+public:
+ std::string name;
+
+ Identifier(std::string name) : name(name) {}
+};
+
+class BinaryOp : public ASTNode {
+public:
+ std::unique_ptr<ASTNode> left;
+ std::string value;
+ std::unique_ptr<ASTNode> right;
+
+ BinaryOp(std::unique_ptr<ASTNode> left, std::string value, std::unique_ptr<ASTNode> right) : left(std::move(left)), value(std::move(value)), right(std::move(right)) {}
+};
+
+#endif
diff --git a/include/parser/node_type.h b/include/parser/node_type.h
@@ -0,0 +1,10 @@
+#ifndef NODE_TYPE_H
+#define NODE_TYPE_H
+
+enum class NodeType {
+ PROGRAM,
+ VARIABLE_DECLARATION,
+ ASSIGNMENT,
+};
+
+#endif
diff --git a/include/parser/parser.h b/include/parser/parser.h
@@ -0,0 +1,31 @@
+#ifndef PARSER_H
+#define PARSER_H
+
+#include "lexer/token.h"
+#include "parser/ast_node.h"
+
+#include <vector>
+
+class Parser {
+public:
+ explicit Parser(const std::vector<Token>& tokens);
+ std::unique_ptr<Program> parse();
+
+private:
+ std::vector<Token> tokens_;
+ int position_;
+
+ std::unique_ptr<ASTNode> parseStatement();
+ std::unique_ptr<ASTNode> parseExpression();
+ std::unique_ptr<ASTNode> parseAddSub();
+ std::unique_ptr<ASTNode> parseMulDiv();
+ std::unique_ptr<ASTNode> parsePrimary();
+ std::unique_ptr<ASTNode> parseDeclaration();
+ std::unique_ptr<ASTNode> parseAssignment();
+ Token advance();
+ Token peek();
+ bool isAtEnd();
+ void error(std::string s);
+};
+
+#endif
diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp
@@ -0,0 +1,171 @@
+#include <iostream>
+
+#include "parser/parser.h"
+
+Parser::Parser(const std::vector<Token>& tokens) : tokens_(tokens), position_(0) {}
+
+std::unique_ptr<Program> Parser::parse() {
+ auto program = std::make_unique<Program>();
+
+ while (peek().type != TokenType::END_OF_FILE) {
+ try {
+ auto statement = parseStatement();
+ program->declarations.push_back(std::move(statement));
+
+ if (peek().type == TokenType::SEMICOLON) {
+ advance();
+ }
+ }
+
+ catch (const std::exception& e) {
+ std::cerr << " Parser error: " << e.what() << std::endl;
+ break;
+ }
+ }
+
+ return program;
+}
+
+std::unique_ptr<ASTNode> Parser::parseStatement() {
+ switch(peek().type) {
+ case TokenType::INT:
+ case TokenType::STRING:
+ {
+ return parseDeclaration();
+ break;
+ }
+
+ default:
+ {
+ error("Unexpected statement");
+ return nullptr;
+ }
+ }
+}
+
+std::unique_ptr<ASTNode> Parser::parseExpression() {
+ return parseAddSub();
+}
+
+std::unique_ptr<ASTNode> Parser::parseDeclaration() {
+ std::string type;
+
+ switch(peek().type) {
+ case TokenType::INT:
+ {
+ type = "int";
+ break;
+ }
+
+ case TokenType::STRING:
+ {
+ type = "string";
+ break;
+ }
+
+ default:
+ {
+ error("Unexpected declaration: Invalid type");
+ return nullptr;
+ }
+ }
+
+ advance();
+ std::string name = peek().value;
+ advance();
+ if (peek().type == TokenType::ASSIGN) {
+ advance();
+ auto value = parseExpression();
+ return std::make_unique<Declaration>(type, name, std::move(value));
+ }
+
+ else if (peek().type == TokenType::SEMICOLON) {
+ return std::make_unique<Declaration>(type, name);
+ }
+
+ else {
+ error("Invalid declaration");
+ return nullptr;
+ }
+}
+
+std::unique_ptr<ASTNode> Parser::parseAssignment() {
+ std::string name = peek().value;
+ advance();
+ advance(); // consume =
+ auto value = parseExpression();
+ return std::make_unique<Assignment>(name, std::move(value));
+}
+
+std::unique_ptr<ASTNode> Parser::parseAddSub() {
+ auto left = parseMulDiv();
+
+ while (peek().type == TokenType::PLUS || peek().type == TokenType::MINUS) {
+ std::string op = peek().value;
+ advance();
+ auto right = parseMulDiv();
+ left = std::make_unique<BinaryOp>(std::move(left), op, std::move(right));
+ }
+
+ return left;
+}
+
+std::unique_ptr<ASTNode> Parser::parseMulDiv() {
+ auto left = parsePrimary();
+
+ while (peek().type == TokenType::MULTIPLY || peek().type == TokenType::DIVIDE) {
+ std::string op = peek().value;
+ advance();
+ auto right = parsePrimary();
+ left = std::make_unique<BinaryOp>(std::move(left), op, std::move(right));
+ }
+
+ return left;
+}
+
+std::unique_ptr<ASTNode> Parser::parsePrimary() {
+ switch(peek().type) {
+ case TokenType::NUMBER:
+ {
+ double value = std::stod(peek().value);
+ advance();
+ return std::make_unique<NumberLiteral>(value);
+ }
+
+ case TokenType::IDENTIFIER:
+ {
+ std::string name = peek().value;
+ advance();
+ return std::make_unique<Identifier>(name);
+ }
+
+ case TokenType::STRING:
+ {
+ std::string value = peek().value;
+ advance();
+ return std::make_unique<StringLiteral>(value);
+ }
+
+ default:
+ {
+ error("Unknown keyword");
+ return nullptr;
+ }
+ }
+}
+
+Token Parser::advance() {
+ return tokens_[position_++];
+}
+
+Token Parser::peek() {
+ return tokens_[position_];
+}
+
+bool Parser::isAtEnd() {
+ return position_ >= tokens_.size();
+}
+
+void Parser::error(std::string s) {
+
+}