add: introduce AST
This commit is contained in:
parent
aa457f917e
commit
8be5386075
|
|
@ -0,0 +1,7 @@
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "AST.h"
|
||||||
|
|
||||||
|
namespace DragonLisp {
|
||||||
|
|
||||||
|
} // end of namespace DragonLisp
|
||||||
|
|
@ -0,0 +1,226 @@
|
||||||
|
#ifndef __DRAGON_LISP_AST_H__
|
||||||
|
#define __DRAGON_LISP_AST_H__
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "token.h"
|
||||||
|
#include "context.h"
|
||||||
|
|
||||||
|
namespace DragonLisp {
|
||||||
|
|
||||||
|
enum ASTType {
|
||||||
|
T_ArrayRefAST,
|
||||||
|
T_IdentifierAST,
|
||||||
|
T_FuncDefAST,
|
||||||
|
T_FuncCallAST,
|
||||||
|
T_IfAST,
|
||||||
|
T_LoopAST,
|
||||||
|
T_UnaryAST,
|
||||||
|
T_BinaryAST,
|
||||||
|
T_ListAST,
|
||||||
|
T_VarOpAST,
|
||||||
|
T_LValOpAST,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// BaseAST - Base class for all AST nodes.
|
||||||
|
class BaseAST {
|
||||||
|
public:
|
||||||
|
virtual ~BaseAST() = default;
|
||||||
|
|
||||||
|
virtual ASTType getType() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExprAST : public BaseAST {
|
||||||
|
public:
|
||||||
|
virtual std::shared_ptr<Value> eval(Context* parent) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LValueAST : public ExprAST {
|
||||||
|
public:
|
||||||
|
virtual std::shared_ptr<Value> set(Context* parent, std::shared_ptr<Value> value) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArrayRefAST : public LValueAST {
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
std::shared_ptr<ExprAST> index;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ArrayRefAST(std::string name, std::shared_ptr<ExprAST> index) : name(std::move(name)), index(std::move(index)) {}
|
||||||
|
|
||||||
|
ASTType getType() const override final {
|
||||||
|
return T_ArrayRefAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Value> eval(Context* parent) override final;
|
||||||
|
|
||||||
|
std::shared_ptr<Value> set(Context* parent, std::shared_ptr<Value> value) override final;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IdentifierAST : public LValueAST {
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit IdentifierAST(std::string name) : name(std::move(name)) {}
|
||||||
|
|
||||||
|
ASTType getType() const override final {
|
||||||
|
return T_IdentifierAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Value> eval(Context* parent) override final;
|
||||||
|
|
||||||
|
std::shared_ptr<Value> set(Context* parent, std::shared_ptr<Value> value) override final;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FuncDefAST : public BaseAST {
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
std::vector<std::string> args;
|
||||||
|
std::vector<std::shared_ptr<ExprAST>> body;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FuncDefAST(std::string name, std::vector<std::string> args, std::vector<std::shared_ptr<ExprAST>> body) : name(std::move(name)), args(std::move(args)), body(std::move(body)) {}
|
||||||
|
|
||||||
|
std::shared_ptr<Value> eval(Context* parent, std::vector<std::shared_ptr<Value>> arg);
|
||||||
|
|
||||||
|
inline ASTType getType() const override final {
|
||||||
|
return T_FuncDefAST;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FuncCallAST : public ExprAST {
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
std::vector<std::shared_ptr<ExprAST>> args;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FuncCallAST(std::string name, std::vector<std::unique_ptr<ExprAST>> args);
|
||||||
|
|
||||||
|
std::shared_ptr<Value> eval(Context* parent) override final;
|
||||||
|
|
||||||
|
inline ASTType getType() const override final {
|
||||||
|
return T_FuncCallAST;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class IfAST : public ExprAST {
|
||||||
|
private:
|
||||||
|
std::shared_ptr<ExprAST> cond;
|
||||||
|
std::shared_ptr<ExprAST> then;
|
||||||
|
std::shared_ptr<ExprAST> els;
|
||||||
|
|
||||||
|
public:
|
||||||
|
IfAST(std::unique_ptr<ExprAST> cond, std::unique_ptr<ExprAST> then, std::unique_ptr<ExprAST> els);
|
||||||
|
|
||||||
|
std::shared_ptr<Value> eval(Context* parent) override final {
|
||||||
|
throw std::runtime_error("You should use IfAST::getResult() instead of IfAST::eval()");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ExprAST> getResult(Context* parent);
|
||||||
|
|
||||||
|
inline ASTType getType() const override final {
|
||||||
|
return T_IfAST;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LoopAST : public ExprAST {
|
||||||
|
private:
|
||||||
|
std::string loopVar;
|
||||||
|
std::shared_ptr<ExprAST> start;
|
||||||
|
std::shared_ptr<ExprAST> end;
|
||||||
|
std::shared_ptr<FuncDefAST> body;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LoopAST(std::string loopVar, std::unique_ptr<ExprAST> start, std::unique_ptr<ExprAST> end, std::unique_ptr<FuncDefAST> body);
|
||||||
|
|
||||||
|
std::shared_ptr<Value> eval(Context* parent) override final;
|
||||||
|
|
||||||
|
inline ASTType getType() const override final {
|
||||||
|
return T_LoopAST;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class UnaryAST : public ExprAST {
|
||||||
|
private:
|
||||||
|
std::shared_ptr<ExprAST> expr;
|
||||||
|
Token op;
|
||||||
|
|
||||||
|
public:
|
||||||
|
UnaryAST(std::unique_ptr<ExprAST> expr, Token op);
|
||||||
|
|
||||||
|
std::shared_ptr<Value> eval(Context* parent) override final;
|
||||||
|
|
||||||
|
inline ASTType getType() const override final {
|
||||||
|
return T_UnaryAST;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BinaryAST : public ExprAST {
|
||||||
|
private:
|
||||||
|
std::shared_ptr<ExprAST> lhs;
|
||||||
|
std::shared_ptr<ExprAST> rhs;
|
||||||
|
Token op;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BinaryAST(std::unique_ptr<ExprAST> lhs, std::unique_ptr<ExprAST> rhs, Token op);
|
||||||
|
|
||||||
|
std::shared_ptr<Value> eval(Context* parent) override final;
|
||||||
|
|
||||||
|
inline ASTType getType() const override final {
|
||||||
|
return T_BinaryAST;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ListAST : public ExprAST {
|
||||||
|
private:
|
||||||
|
std::vector<std::shared_ptr<ExprAST>> exprs;
|
||||||
|
Token op;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ListAST(std::vector<std::unique_ptr<ExprAST>> exprs, Token op);
|
||||||
|
|
||||||
|
std::shared_ptr<Value> eval(Context* parent) override final;
|
||||||
|
|
||||||
|
inline ASTType getType() const override final {
|
||||||
|
return T_ListAST;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class VarOpAST : public ExprAST {
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
std::shared_ptr<ExprAST> expr;
|
||||||
|
Token op;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VarOpAST(std::string name, std::unique_ptr<ExprAST> expr, Token op);
|
||||||
|
|
||||||
|
std::shared_ptr<Value> eval(Context* parent) override final;
|
||||||
|
|
||||||
|
inline ASTType getType() const override final {
|
||||||
|
return T_VarOpAST;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LValOpAST : public ExprAST {
|
||||||
|
private:
|
||||||
|
std::shared_ptr<ExprAST> lval;
|
||||||
|
std::shared_ptr<ExprAST> expr;
|
||||||
|
Token op;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LValOpAST(std::unique_ptr<ExprAST> lval, std::unique_ptr<ExprAST> expr, Token op);
|
||||||
|
|
||||||
|
std::shared_ptr<Value> eval(Context* parent) override final;
|
||||||
|
|
||||||
|
inline ASTType getType() const override final {
|
||||||
|
return T_LValOpAST;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __DRAGON_LISP_AST_H__
|
||||||
3
Makefile
3
Makefile
|
|
@ -22,7 +22,7 @@ COMMONFLAGS ?= -g -Wall
|
||||||
CFLAGS ?= $(COMMONFLAGS) -std=c18
|
CFLAGS ?= $(COMMONFLAGS) -std=c18
|
||||||
CXXFLAGS ?= $(COMMONFLAGS) -std=c++20
|
CXXFLAGS ?= $(COMMONFLAGS) -std=c++20
|
||||||
|
|
||||||
MISCOBJ = main DragonLispDriver
|
MISCOBJ = main DragonLispDriver AST
|
||||||
OBJS = $(addsuffix .o, $(MISCOBJ))
|
OBJS = $(addsuffix .o, $(MISCOBJ))
|
||||||
|
|
||||||
all: compile
|
all: compile
|
||||||
|
|
@ -49,6 +49,7 @@ compile_debug: lexer parser
|
||||||
$(CXX) $(CXXFLAGS) -o $(OUTPUT) \
|
$(CXX) $(CXXFLAGS) -o $(OUTPUT) \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
DragonLispDriver.cpp \
|
DragonLispDriver.cpp \
|
||||||
|
AST.cpp \
|
||||||
DragonLisp.tab.cc \
|
DragonLisp.tab.cc \
|
||||||
lex.yy.cc
|
lex.yy.cc
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef __DRAGON_LISP_CONTEXT_H__
|
||||||
|
#define __DRAGON_LISP_CONTEXT_H__
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
#include "value.h"
|
||||||
|
|
||||||
|
namespace DragonLisp {
|
||||||
|
|
||||||
|
class FuncDefAST;
|
||||||
|
|
||||||
|
class Context {
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<Value>> variables;
|
||||||
|
|
||||||
|
Context* parent = nullptr;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<FuncDefAST>>* funcs = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Context(Context* p = nullptr) : parent(p) {
|
||||||
|
this->funcs = p ? p->funcs : new std::unordered_map<std::string, std::shared_ptr<FuncDefAST>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Context() {
|
||||||
|
if (!this->parent)
|
||||||
|
delete this->funcs;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __DRAGON_LISP_CONTEXT_H__
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef __DRAGON_LISP_TYPES_H__
|
||||||
|
#define __DRAGON_LISP_TYPES_H__
|
||||||
|
|
||||||
|
namespace DragonLisp {
|
||||||
|
|
||||||
|
enum ValueType {
|
||||||
|
TYPE_INTEGER,
|
||||||
|
TYPE_FLOAT,
|
||||||
|
TYPE_STRING,
|
||||||
|
TYPE_ARRAY,
|
||||||
|
TYPE_T, // has no value
|
||||||
|
TYPE_NIL, // has no value
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace DragonLisp
|
||||||
|
|
||||||
|
#endif // __DRAGON_LISP_TYPES_H__
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
#ifndef __DRAGON_LISP_VALUE_H__
|
||||||
|
#define __DRAGON_LISP_VALUE_H__
|
||||||
|
|
||||||
|
#include <variant>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
namespace DragonLisp {
|
||||||
|
|
||||||
|
using ValueVariant = std::variant<std::monostate, std::int64_t, double, std::string>;
|
||||||
|
|
||||||
|
class Value {
|
||||||
|
public:
|
||||||
|
virtual bool isArray() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArrayValue : public Value {
|
||||||
|
private:
|
||||||
|
std::vector<ValueVariant> values;
|
||||||
|
|
||||||
|
std::size_t size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ArrayValue() = delete;
|
||||||
|
|
||||||
|
explicit ArrayValue(std::size_t s) : values(s), size(s) {}
|
||||||
|
|
||||||
|
explicit ArrayValue(std::vector<ValueVariant> v) : values(std::move(v)), size(this->values.size()) {}
|
||||||
|
|
||||||
|
bool isArray() const override final {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t getSize() const {
|
||||||
|
return this->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueVariant& operator[](std::size_t i) {
|
||||||
|
return this->values[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
const ValueVariant& operator[](std::size_t i) const {
|
||||||
|
return this->values[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ValueVariant>& getValues() {
|
||||||
|
return this->values;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<ValueVariant>& getValues() const {
|
||||||
|
return this->values;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SingleValue : public Value {
|
||||||
|
private:
|
||||||
|
ValueType type;
|
||||||
|
|
||||||
|
ValueVariant value;
|
||||||
|
|
||||||
|
explicit SingleValue(ValueType t) : type(t), value() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SingleValue(std::int64_t v) : value(v) {}
|
||||||
|
|
||||||
|
explicit SingleValue(double v) : value(v) {}
|
||||||
|
|
||||||
|
explicit SingleValue(std::string v) : value(std::move(v)) {}
|
||||||
|
|
||||||
|
SingleValue() = delete;
|
||||||
|
|
||||||
|
bool isArray() const override final {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SingleValue makeT() {
|
||||||
|
return SingleValue(ValueType::TYPE_T);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SingleValue makeNil() {
|
||||||
|
return SingleValue(ValueType::TYPE_NIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType getType() const {
|
||||||
|
return this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isT() const {
|
||||||
|
return this->type == ValueType::TYPE_T;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isNil() const {
|
||||||
|
return this->type == ValueType::TYPE_NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isInt() const {
|
||||||
|
return std::holds_alternative<std::int64_t>(this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isFloat() const {
|
||||||
|
return std::holds_alternative<double>(this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isString() const {
|
||||||
|
return std::holds_alternative<std::string>(this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::int64_t getInt() const {
|
||||||
|
return std::get<std::int64_t>(this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
double getFloat() const {
|
||||||
|
return std::get<double>(this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getString() const {
|
||||||
|
return std::get<std::string>(this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueVariant getValue() const {
|
||||||
|
return this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setValue(ValueVariant v) {
|
||||||
|
this->value = std::move(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class _Unused_Variable {
|
||||||
|
protected:
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
std::variant<ArrayValue, SingleValue> val;
|
||||||
|
|
||||||
|
public:
|
||||||
|
_Unused_Variable() = delete;
|
||||||
|
|
||||||
|
_Unused_Variable(std::string n, SingleValue v) : name(std::move(n)), val(std::move(v)) {}
|
||||||
|
|
||||||
|
_Unused_Variable(std::string n, ArrayValue v) : name(std::move(n)), val(std::move(v)) {}
|
||||||
|
|
||||||
|
std::string getName() const {
|
||||||
|
return this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isArray() const {
|
||||||
|
return std::holds_alternative<ArrayValue>(this->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValue() const {
|
||||||
|
return std::holds_alternative<SingleValue>(this->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayValue getArray() const {
|
||||||
|
return std::get<ArrayValue>(this->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
SingleValue getValue() const {
|
||||||
|
return std::get<SingleValue>(this->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(SingleValue v) {
|
||||||
|
this->val = std::move(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(ArrayValue v) {
|
||||||
|
this->val = std::move(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __DRAGON_LISP_VALUE_H__
|
||||||
Loading…
Reference in New Issue