#pragma once #include #include "lexer.hpp" enum NodeType { Expression = 0, Extern, FnDecl, FnCall, VarDecl, COUNT_NODES, }; class Node { public: virtual NodeType GetType() const = 0; virtual ~Node() {} }; #define NODE_TYPE(x) \ NodeType GetType() const override { return (x); } class ExpressionNode : public Node { public: ExpressionNode() : m_left(nullptr), m_right(nullptr) {} ~ExpressionNode() override { delete m_left; delete m_right; } NODE_TYPE(Expression) public: Node* left() const { return m_left; } Node* right() const { return m_right; } private: Node* m_left; Node* m_right; }; class ExternNode : public Node { public: // TODO: support multiple extern symbols ExternNode(char* symbol) : m_symbol(symbol) {} ~ExternNode() override { delete m_symbol; } NODE_TYPE(Extern) private: char* m_symbol; }; class FnDeclNode : public Node { public: // TODO: support parameters FnDeclNode(char* name, Node* body) : m_name(name), m_body(body) {} ~FnDeclNode() override { delete m_name; delete m_body; } NODE_TYPE(FnDecl) private: char* m_name; Node* m_body; }; class FnCallNode : public Node { public: // TODO: support multiple arguments FnCallNode(char* name, Node* arg) : m_name(name), m_arg(arg) {} ~FnCallNode() override { delete m_name; delete m_arg; } NODE_TYPE(FnCall) private: char* m_name; Node* m_arg; }; class VarDeclNode : public Node { public: VarDeclNode(char* name, Node* value) : m_name(name), m_value(value) {} ~VarDeclNode() override { delete m_name; delete m_value; } NODE_TYPE(VarDecl) private: char* m_name; Node* m_value; }; class AstParser { public: AstParser(Lexer* lexer) : m_lexer(lexer) {} public: Node* ParseStatement() { while (m_lexer->NextToken()) { auto token = m_lexer->token(); switch(token.token) { case Id: { if (strcmp(token.string, "extern") == 0) { // Extern m_lexer->Eat(Id); return new ExternNode(m_lexer->token().string); } else if (strcmp(token.string, "fn") == 0) { // Function Declaration m_lexer->Eat(Id); char* name = strdup(m_lexer->token().string); m_lexer->Eat('('); // TODO: parse parameters m_lexer->Eat(')'); m_lexer->Eat('{'); // TODO: parse function body m_lexer->Eat('}'); return new FnDeclNode(name, nullptr); } } break; } } // TODO: report parse error return nullptr; } private: Lexer* m_lexer; };