add: introduce AST

This commit is contained in:
Eatswap 2022-12-12 23:20:25 +08:00
parent aa457f917e
commit 8be5386075
Signed by: Eatswap
GPG Key ID: BE661106A1F3FA0B
6 changed files with 461 additions and 1 deletions

7
AST.cpp Normal file
View File

@ -0,0 +1,7 @@
#include <utility>
#include "AST.h"
namespace DragonLisp {
} // end of namespace DragonLisp

226
AST.h Normal file
View File

@ -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__

View File

@ -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

34
context.h Normal file
View File

@ -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__

17
types.h Normal file
View File

@ -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__

175
value.h Normal file
View File

@ -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__