diff options
| -rw-r--r-- | include/ast_node.hpp | 36 | ||||
| -rw-r--r-- | include/lexer.hpp (renamed from include/lexer/lexer.hpp) | 5 | ||||
| -rw-r--r-- | include/parser.hpp (renamed from include/parser/parser.hpp) | 5 | ||||
| -rw-r--r-- | include/parser/ast_node.hpp | 70 | ||||
| -rw-r--r-- | include/parser/node_type.hpp | 10 | ||||
| -rw-r--r-- | include/scope.hpp (renamed from include/semantic/scope.hpp) | 0 | ||||
| -rw-r--r-- | include/semantic_analyzer.hpp (renamed from include/semantic/semantic_analyzer.hpp) | 0 | ||||
| -rw-r--r-- | include/symbol.hpp (renamed from include/semantic/symbol.hpp) | 0 | ||||
| -rw-r--r-- | include/symbol_table.hpp (renamed from include/semantic/symbol_table.hpp) | 0 | ||||
| -rw-r--r-- | include/symbol_type.hpp (renamed from include/semantic/symbol_type.hpp) | 0 | ||||
| -rw-r--r-- | include/token.hpp (renamed from include/lexer/token.hpp) | 5 | ||||
| -rw-r--r-- | include/token_type.hpp (renamed from include/lexer/token_type.hpp) | 5 | ||||
| -rw-r--r-- | include/type.hpp | 11 | ||||
| -rw-r--r-- | src/lexer.cpp (renamed from src/lexer/lexer.cpp) | 2 | ||||
| -rw-r--r-- | src/main.cpp | 4 | ||||
| -rw-r--r-- | src/parser.cpp (renamed from src/parser/parser.cpp) | 2 | ||||
| -rw-r--r-- | src/scope.cpp (renamed from src/semantic/scope.cpp) | 2 | ||||
| -rw-r--r-- | src/semantic/semantic_analyzer.cpp | 33 | ||||
| -rw-r--r-- | src/semantic_analyzer.cpp | 235 | ||||
| -rw-r--r-- | src/symbol.cpp (renamed from src/semantic/symbol.cpp) | 2 | ||||
| -rw-r--r-- | src/symbol_table.cpp (renamed from src/semantic/symbol_table.cpp) | 2 |
21 files changed, 293 insertions, 136 deletions
diff --git a/include/ast_node.hpp b/include/ast_node.hpp new file mode 100644 index 0000000..caffb35 --- /dev/null +++ b/include/ast_node.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include "node_type.hpp" +#include "type.hpp" + +#include <string> +#include <vector> +#include <memory> + +class ASTNode { +public: + int line; + int column; + + virtual ~ASTNode() = default; +}; + +class ProgramNode : ASTNode { +public: + std::vector<ASTNode> function_declarations; + + explicit ProgramNode(std::vector<ASTNode> f) : function_declarations(f) { } +}; + +class FunctionDeclNode : ASTNode { + Type type; + std::vector<ParameterNode> parameters; + std::vector<ASTNode> body; + + FunctionDeclNode(std::string t,std::vector<ASTNode> p, std::vector<ASTNode> b) : type(t), parameters(p), body(b) { } +}; + +class ParameterNode : ASTNode { + std::string name; + std::string type; +}; diff --git a/include/lexer/lexer.hpp b/include/lexer.hpp index 2c165b6..2ef9700 100644 --- a/include/lexer/lexer.hpp +++ b/include/lexer.hpp @@ -1,5 +1,4 @@ -#ifndef LEXER_H -#define LEXER_H +#pragma once #include "token.hpp" @@ -23,5 +22,3 @@ private: void skipWhitespace(); void skipComment(); }; - -#endif diff --git a/include/parser/parser.hpp b/include/parser.hpp index 438b8fe..f986ce2 100644 --- a/include/parser/parser.hpp +++ b/include/parser.hpp @@ -1,5 +1,4 @@ -#ifndef PARSER_H -#define PARSER_H +#pragma once #include "lexer/token.hpp" #include "parser/ast_node.hpp" @@ -27,5 +26,3 @@ private: bool isAtEnd(); void error(std::string s); }; - -#endif diff --git a/include/parser/ast_node.hpp b/include/parser/ast_node.hpp deleted file mode 100644 index 6539cf6..0000000 --- a/include/parser/ast_node.hpp +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef AST_NODE_H -#define AST_NODE_H - -#include "node_type.hpp" - -#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.hpp b/include/parser/node_type.hpp deleted file mode 100644 index 1766b19..0000000 --- a/include/parser/node_type.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef NODE_TYPE_H -#define NODE_TYPE_H - -enum class NodeType { - PROGRAM, - VARIABLE_DECLARATION, - ASSIGNMENT, -}; - -#endif diff --git a/include/semantic/scope.hpp b/include/scope.hpp index ff20542..ff20542 100644 --- a/include/semantic/scope.hpp +++ b/include/scope.hpp diff --git a/include/semantic/semantic_analyzer.hpp b/include/semantic_analyzer.hpp index 0d56599..0d56599 100644 --- a/include/semantic/semantic_analyzer.hpp +++ b/include/semantic_analyzer.hpp diff --git a/include/semantic/symbol.hpp b/include/symbol.hpp index 4bee45d..4bee45d 100644 --- a/include/semantic/symbol.hpp +++ b/include/symbol.hpp diff --git a/include/semantic/symbol_table.hpp b/include/symbol_table.hpp index b2b8270..b2b8270 100644 --- a/include/semantic/symbol_table.hpp +++ b/include/symbol_table.hpp diff --git a/include/semantic/symbol_type.hpp b/include/symbol_type.hpp index a792c09..a792c09 100644 --- a/include/semantic/symbol_type.hpp +++ b/include/symbol_type.hpp diff --git a/include/lexer/token.hpp b/include/token.hpp index 86a41f6..d85ba94 100644 --- a/include/lexer/token.hpp +++ b/include/token.hpp @@ -1,5 +1,4 @@ -#ifndef TOKEN_H -#define TOKEN_H +#pragma once #include "token_type.hpp" @@ -13,5 +12,3 @@ struct Token { Token(TokenType t, const std::string& val, int line, int col) : type{t}, value{val}, line{line}, column{col} {}; }; - -#endif diff --git a/include/lexer/token_type.hpp b/include/token_type.hpp index f83c6d6..d123aaa 100644 --- a/include/lexer/token_type.hpp +++ b/include/token_type.hpp @@ -1,5 +1,4 @@ -#ifndef TOKEN_TYPE_H -#define TOKEN_TYPE_H +#pragma once enum class TokenType { INT, @@ -21,5 +20,3 @@ enum class TokenType { INVALID }; - -#endif diff --git a/include/type.hpp b/include/type.hpp new file mode 100644 index 0000000..c46ff34 --- /dev/null +++ b/include/type.hpp @@ -0,0 +1,11 @@ +#pragma once + +enum struct Type { + INT, + CHAR, + BOOL, + STRING, + FLOAT, + DOUBLE, + VOID, +}; diff --git a/src/lexer/lexer.cpp b/src/lexer.cpp index 70af4b5..3b134eb 100644 --- a/src/lexer/lexer.cpp +++ b/src/lexer.cpp @@ -1,4 +1,4 @@ -#include "lexer/lexer.hpp" +#include "lexer.hpp" Lexer::Lexer(const std::string& src) : src(src), position(0), line(1), column(1) {} diff --git a/src/main.cpp b/src/main.cpp index 9a11516..24a748d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,8 +2,8 @@ #include <sstream> #include <fstream> -#include "lexer/lexer.hpp" -#include "parser/parser.hpp" +#include "lexer.hpp" +#include "parser.hpp" std::string tokenTypeToString(TokenType type) { switch (type) { diff --git a/src/parser/parser.cpp b/src/parser.cpp index 97a1f27..6f47890 100644 --- a/src/parser/parser.cpp +++ b/src/parser.cpp @@ -1,6 +1,6 @@ #include <iostream> -#include "parser/parser.hpp" +#include "parser.hpp" Parser::Parser(const std::vector<Token>& tokens) : tokens_(tokens), position_(0) {} diff --git a/src/semantic/scope.cpp b/src/scope.cpp index ba5aa41..86e2668 100644 --- a/src/semantic/scope.cpp +++ b/src/scope.cpp @@ -1,4 +1,4 @@ -#include "semantic/scope.hpp" +#include "scope.hpp" Scope::Scope(std::string name, int level, std::unique_ptr<Scope> parent) : scope_name(name), scope_level(level), parent_scope(parent) {} diff --git a/src/semantic/semantic_analyzer.cpp b/src/semantic/semantic_analyzer.cpp deleted file mode 100644 index 57f217e..0000000 --- a/src/semantic/semantic_analyzer.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "semantic/semantic_analyzer.hpp" - -SemanticAnalyzer::SemanticAnalyzer() : symobl_table(new SemanticTable), errors(std::vector<Error>), warnings(std::vector<Error>), current_function(nullptr), current_function_return_type(""), has_main_function(false) {} - -bool SemanticAnalyzer::analyze(ASTNode* ast) { - this->symbol_table.enterScope("global") - this->visit(ast); - this->validateMainFunction(); - - if (has_main_function == false) { - //error - return false; - } - - this->symbol_table.exitScope(); - return true; -} - -std::vector<Error> SemanticAnalyzer::getErrors() { - return this->errors; -} - -std::vector<Error> SemanticAnalyzer::getWarnings() { - return this->warnings; -} - -bool SemanticAnalyzer::hasErrors() { - return !this->errors.empty(); -} - -std::string SemanticAnalyzer::visit(ASTNode* ast) { - -} diff --git a/src/semantic_analyzer.cpp b/src/semantic_analyzer.cpp new file mode 100644 index 0000000..e097e4f --- /dev/null +++ b/src/semantic_analyzer.cpp @@ -0,0 +1,235 @@ +#include "semantic_analyzer.hpp" + +SemanticAnalyzer::SemanticAnalyzer() : symobl_table(new SemanticTable), errors(std::vector<Error>), warnings(std::vector<Error>), current_function(nullptr), current_function_return_type(""), has_main_function(false) {} + +bool SemanticAnalyzer::analyze(ASTNode* ast) { + symbol_table.enterScope("global") + visit(ast); + validateMainFunction(); + + if (has_main_function == false) { + //error + return false; + } + + symbol_table.exitScope(); + return true; +} + +std::vector<Error> SemanticAnalyzer::getErrors() { + return errors; +} + +std::vector<Error> SemanticAnalyzer::getWarnings() { + return warnings; +} + +bool SemanticAnalyzer::hasErrors() { + return !errors.empty(); +} + +std::string SemanticAnalyzer::visit(ASTNode* node) { + if (ProgramNode* prog = dynamic_cast<ProgramNode*>(node)) { + return visitProgram(prog); + } + + else if (FunctionDeclNode* func = dynamic_cast<FunctionDeclNode*>(node)) { + return visitFunctionDecl(func); + } + + else if (ParameterNode* param = dynamic_cast<ParameterNode*>(node)) { + return visitParameter(param); + } + + else if (VarDeclNode* var = dynamic_cast<VarDeclNode*>(node)) { + return visitVarDeclaration(var); + } + + else if (AssignmentNode as = dynamic_cast<AssignmentNode>(node)) { + return visitAssignment(as); + } + + else if (IfStatementNode is = dynamic_cast<IfStatementNode>(node)) { + return visitIfStatement(is); + } + + else if (WhileStatementNode ws = dynamic_cast<WhileStatementNode>(node)) { + return visitWhileStatement(ws); + } + + else if (ForStatementNode fs = dynamic_cast<ForStatementNode>(node)) { + return visitForStatement(fs); + } + + else if (ReturnStatementNode rs = dynamic_cast<ReturnStatementNode>(node)) { + return visitReturnStatement(rs); + } + + else if (ExpressionStatementNode es = dynamic_cast<ExpressionStatementNode>(node)) { + return visitExpressionStatement(es); + } + + else if (BinaryExprNode bin = dynamic_cast<BinaryExprNode>(node)) { + return visitBinaryExpression(bin); + } + + else if (UnaryExprNode un = dynamic_cast<UnaryExprNode>(node)) { + return visitUnaryExpression(un); + } + + else if (FunctionCallNode func_call = dynamic_cast<FunctionCallNode>(node)) { + return visitFunctionCall(func_call); + } + + else if (IdentifierNode ident = dynamic_cast<IdentifierNode>(node)) { + return visitIdentifier(ident); + } + + else if (LiteralNode lit = dynamic_cast<LiteralNode>(node)) { + return visitLiteral(lit); + } +} + +std::string visitProgram(ProgramNode* node){ + // get list of functions + // visit each function + // return + +} + +std::string visitFunctionDecl(FunctionDeclNode* node){ + // check for dupe name + // create function symbol and insert into global scope + // check if main function + // enter function scope + // process parameters + // process function body + // verify non-void functions have return statements + // exit function scope and clear context + // return + +} + +std::string visitParameter(ParameterNode*){ + // get parameter info from node + // check for dupes + // create parameter symbol + // insert into current scope + // return parameter type + +} + +std::string visitVarDeclaration(VarDeclNode* node){ + // get variable information + // check for dupes + // if initializer exists, check type + // create variable symbol + // insert into current scope + // return + +} + +std::string visitAssignment(AssignmentNode* node){ + // get left side info + // look up target variable + // verify variable + // analyze right side info + // check type compatability + // make var as initialized + // return + +} + +std::string visitIfStatement(IfStatementNode* node){ + // analyze condition + // verify condition is bool + // analyze then branch + // analyze else branch + // return + +} + +std::string visitWhileStatement(WhileStatementNode* node){ + // analyze condition + // verify condition is bool + // analyze loop body + // return + +} + +std::string visitForStatement(ForStatementNode* node){ + // enter new scope for loop + // analyze initialization + // analyze condition + // analyze update statement + // analyze loop body + // exit for loop scope + // return + +} + +std::string visitReturnStatement(ReturnStatementNode* node){ + // check if inside function + // get return expression + // analyze return expression + // validate return type matches function + // return + +} + +std::String visitExpressionStatement(ExpressionStatementNode* node){ + // get the expression + // analyze expression + // return + +} + +std::string visitBinaryExpression(BinaryExprNode* node){ + // get operator and operands + // analyze operands + // infer result type based on operator + // return result type + +} + +std::string visitUnaryExpression(UnaryExprNode* node){ + // get operator and operand + // analyze operand + // infer result type + // return result type + +} + +std::string visitFunctionCall(FunctionCallNode* node){ + // get function name and args + // look up function + // verify its a function + // get expected parameter information + // check argument count + // check each argument type + // return functions return type + +} + +std::string visitIdentifier(IdentifierNode* node){ + // get identifier name + // look up in symbol table + // check if initialized + // return symbol type + +} + +std::string visitLiteral(LiteralNode* node){ + // determine literal type + // return appropriate type + +} + +bool checkTypeCompatibility(std::string target, std::string source){ + // determines if a value of source type can be used where target type is expected + +} + +std::string inferBinaryOpType(std::string op, std::string left, std::string right){ + +} diff --git a/src/semantic/symbol.cpp b/src/symbol.cpp index 5142ea8..ad2041d 100644 --- a/src/semantic/symbol.cpp +++ b/src/symbol.cpp @@ -1,4 +1,4 @@ -#include "semantic/symbol.hpp" +#include "symbol.hpp" Symbol::Symbol(std::string name, SymbolType type, std::string data_type, int scope) : symbol_name(name), symbol_type(type), data_type(data_type), scope_level(scope_level) {} diff --git a/src/semantic/symbol_table.cpp b/src/symbol_table.cpp index 548d6ee..81ff474 100644 --- a/src/semantic/symbol_table.cpp +++ b/src/symbol_table.cpp @@ -1,4 +1,4 @@ -#include "semantic/symbol_table.hpp" +#include "symbol_table.hpp" #include <iostream> |
