bl-compiler

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 74eafbd39c4c622ce2ebdf699102ec7541dfe807
parent e34338219036acf103d161dfbd36fa67597d23e7
Author: Cori Barker <coribarker2@gmail.com>
Date:   Mon, 19 Jan 2026 09:36:05 +0000

parser

Diffstat:
Ainclude/parser/ast_node.h | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/parser/node_type.h | 10++++++++++
Ainclude/parser/parser.h | 31+++++++++++++++++++++++++++++++
Asrc/parser/parser.cpp | 171+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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) { + +}