Files
pl/include/ast.hpp

155 lines
3.0 KiB
C++

#pragma once
#include <cstring>
#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;
};