155 lines
3.0 KiB
C++
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;
|
|
};
|