Refactoring.

This commit is contained in:
yhirose 2015-06-02 14:17:08 -04:00
parent 18ffa7d28c
commit f8da5085aa
5 changed files with 112 additions and 95 deletions

View File

@ -8,7 +8,7 @@ using namespace std;
struct Eval struct Eval
{ {
static Value eval(const Ast& ast, shared_ptr<Environment> env) { static Value eval(const Ast& ast, shared_ptr<Environment> env) {
switch (ast.type) { switch (ast.tag) {
case Statements: return eval_statements(ast, env); case Statements: return eval_statements(ast, env);
case While: return eval_while(ast, env); case While: return eval_while(ast, env);
case If: return eval_if(ast, env); case If: return eval_if(ast, env);
@ -24,7 +24,7 @@ struct Eval
} }
if (ast.is_token) { if (ast.is_token) {
return Value(ast.token); return Value(string(ast.token));
} }
// NOTREACHED // NOTREACHED
@ -82,14 +82,13 @@ private:
auto body = ast.nodes[1]; auto body = ast.nodes[1];
auto f = Value::FunctionValue { return Value(Value::FunctionValue {
params, params,
[=](shared_ptr<Environment> callEnv) { [=](shared_ptr<Environment> callEnv) {
callEnv->push_outer(env); callEnv->push_outer(env);
return eval(*body, callEnv); return eval(*body, callEnv);
} }
}; });
return Value(f);
}; };
static Value eval_function_call(const Ast& ast, shared_ptr<Environment> env) { static Value eval_function_call(const Ast& ast, shared_ptr<Environment> env) {
@ -187,7 +186,7 @@ private:
const auto& val = eval(*node, env); const auto& val = eval(*node, env);
s += val.str(); s += val.str();
} }
return Value(s); return Value(std::move(s));
}; };
static Value dereference_identirier(shared_ptr<Environment> env, const string& var) { static Value dereference_identirier(shared_ptr<Environment> env, const string& var) {

View File

@ -18,11 +18,14 @@ struct Value
}; };
explicit Value() : type(Undefined) {} explicit Value() : type(Undefined) {}
explicit Value(bool b) : type(Bool) { v = b; } explicit Value(bool b) : type(Bool), v(b) {}
explicit Value(long l) : type(Long) { v = l; } explicit Value(long l) : type(Long), v(l) {}
explicit Value(const std::string& s) : type(String) { v = s; } explicit Value(std::string&& s) : type(String), v(s) {}
explicit Value(const ArrayValue& a) : type(Array) { v = a; } explicit Value(ArrayValue&& a) : type(Array), v(a) {}
explicit Value(const FunctionValue& f) : type(Function) { v = f; } explicit Value(FunctionValue&& f) : type(Function), v(f) {}
Value(const Value&) = default;
Value(Value&& rhs) : type(rhs.type), v(rhs.v) {}
bool to_bool() const { bool to_bool() const {
switch (type) { switch (type) {
@ -210,14 +213,13 @@ struct Environment
} }
void setup_built_in_functions() { void setup_built_in_functions() {
auto func_pretty_print = Value::FunctionValue { set("pp", Value(Value::FunctionValue {
{ "arg" }, { "arg" },
[](std::shared_ptr<Environment> env) { [](std::shared_ptr<Environment> env) {
std::cout << env->get("arg").str() << std::endl; std::cout << env->get("arg").str() << std::endl;
return Value(); return Value();
} }
}; }));
set("pp", Value(func_pretty_print));
} }
private: private:

View File

@ -43,7 +43,7 @@ static auto g_grammar = R"(
Comment <- '/*' (!'*/' .)* '*/' / ('#' / '//') (!(EndOfLine / EndOfFile) .)* (EndOfLine / EndOfFile) Comment <- '/*' (!'*/' .)* '*/' / ('#' / '//') (!(EndOfLine / EndOfFile) .)* (EndOfLine / EndOfFile)
)"; )";
peglib::peg& get_parser() peg& get_parser()
{ {
static peg parser; static peg parser;
@ -60,28 +60,29 @@ peglib::peg& get_parser()
throw logic_error("invalid peg grammar"); throw logic_error("invalid peg grammar");
} }
parser parser.ast({
.ast_node_optimizable("STATEMENTS", Statements) { peg::AstNodeType::Regular, "STATEMENTS", Statements },
.ast_node("WHILE", While) { peg::AstNodeType::Regular, "WHILE", While },
.ast_node("ASSIGNMENT", Assignment) { peg::AstNodeType::Regular, "ASSIGNMENT", Assignment },
.ast_node("IF", If) { peg::AstNodeType::Regular, "IF", If },
.ast_node("FUNCTION", Function) { peg::AstNodeType::Regular, "FUNCTION", Function },
.ast_node("PARAMETERS") { peg::AstNodeType::Regular, "PARAMETERS", Undefined },
.ast_node("FUNCTION_CALL", FunctionCall) { peg::AstNodeType::Regular, "FUNCTION_CALL", FunctionCall },
.ast_node("ARGUMENTS") { peg::AstNodeType::Regular, "ARGUMENTS", Undefined },
.ast_node_optimizable("PRIMARY", Condition) { peg::AstNodeType::Optimizable, "PRIMARY", Condition },
.ast_node_optimizable("CONDITION", BinExpresion) { peg::AstNodeType::Optimizable, "CONDITION", BinExpresion },
.ast_node_optimizable("TERM", BinExpresion) { peg::AstNodeType::Optimizable, "TERM", BinExpresion },
.ast_token("CONDITION_OPERATOR") { peg::AstNodeType::Token, "CONDITION_OPERATOR", Undefined },
.ast_token("TERM_OPERATOR") { peg::AstNodeType::Token, "TERM_OPERATOR", Undefined },
.ast_token("FACTOR_OPERATOR") { peg::AstNodeType::Token, "FACTOR_OPERATOR", Undefined },
.ast_token("NUMBER", Number) { peg::AstNodeType::Token, "NUMBER", Number },
.ast_token("BOOLEAN", Boolean) { peg::AstNodeType::Token, "BOOLEAN", Boolean },
.ast_token("STRING") { peg::AstNodeType::Token, "STRING", Undefined },
.ast_token("IDENTIFIER", Identifier) { peg::AstNodeType::Token, "IDENTIFIER", Identifier },
.ast_node("INTERPOLATED_STRING", InterpolatedString) { peg::AstNodeType::Regular, "INTERPOLATED_STRING", InterpolatedString },
.ast_token("INTERPOLATED_CONTENT") { peg::AstNodeType::Token, "INTERPOLATED_CONTENT", Undefined },
.ast_end(); },
Undefined);
} }
return parser; return parser;

View File

@ -1,7 +1,8 @@
#include <peglib.h> #include <peglib.h>
enum AstType enum AstTag
{ {
Undefined,
Statements, While, If, FunctionCall, Assignment, Condition, BinExpresion, Statements, While, If, FunctionCall, Assignment, Condition, BinExpresion,
Identifier, InterpolatedString, Identifier, InterpolatedString,
Number, Boolean, Function Number, Boolean, Function

128
peglib.h
View File

@ -65,15 +65,6 @@ public:
return *this; return *this;
} }
template <typename T>
any& operator=(const T& value) {
if (content_) {
delete content_;
}
content_ = new holder<T>(value);
return *this;
}
~any() { ~any() {
delete content_; delete content_;
} }
@ -1831,16 +1822,16 @@ private:
struct Ast struct Ast
{ {
Ast(const char* _name, int _type, const std::vector<std::shared_ptr<Ast>>& _nodes) Ast(const char* _name, int _tag, const std::vector<std::shared_ptr<Ast>>& _nodes)
: name(_name), type(_type), is_token(false), nodes(_nodes) {} : name(_name), tag(_tag), is_token(false), nodes(_nodes) {}
Ast(const char* _name, int _type, const std::string& _token) Ast(const char* _name, int _tag, const std::string& _token)
: name(_name), type(_type), is_token(true), token(_token) {} : name(_name), tag(_tag), is_token(true), token(_token) {}
void print() const; void print() const;
const std::string name; const std::string name;
const int type; const int tag;
const bool is_token; const bool is_token;
const std::string token; const std::string token;
const std::vector<std::shared_ptr<Ast>> nodes; const std::vector<std::shared_ptr<Ast>> nodes;
@ -2022,51 +2013,35 @@ public:
} }
} }
peg& ast_node(const char* name, int type = -1) { enum AstNodeType {
(*this)[name] = [=](const SemanticValues& sv) { Regular,
return std::make_shared<Ast>(name, type, sv.map<std::shared_ptr<Ast>>()); Optimizable,
}; Token
return *this;
}
peg& ast_node_optimizable(const char* name, int type = -1) {
(*this)[name] = [=](const SemanticValues& sv) {
if (sv.size() == 1) {
std::shared_ptr<Ast> ast = sv[0].get<std::shared_ptr<Ast>>();
return ast;
}
return std::make_shared<Ast>(name, type, sv.map<std::shared_ptr<Ast>>());
};
return *this;
}
peg& ast_token(const char* name, int type = -1) {
(*this)[name] = [=](const SemanticValues& sv) {
return std::make_shared<Ast>(name, type, std::string(sv.s, sv.n));
};
return *this;
}
peg& ast_end() {
for (auto& x: *grammar_) {
const auto& name = x.first;
auto& def = x.second;
auto& action = def.actions.front();
if (!action) {
action = [&](const SemanticValues& sv) {
if (sv.size() == 1) {
std::shared_ptr<Ast> ast = sv[0].get<std::shared_ptr<Ast>>();
return ast;
}
return std::make_shared<Ast>(name.c_str(), -1, sv.map<std::shared_ptr<Ast>>());
};
}
}
return *this;
}; };
peg& set_logger(Log _log) { struct AstNodeInfo {
log = _log; AstNodeType type;
const char* name;
int tag;
};
peg& ast(std::initializer_list<AstNodeInfo> list, int tag) {
for (const auto& info: list) {
switch (info.type) {
case Regular:
ast_node(info.name, info.tag);
break;
case Optimizable:
ast_node_optimizable(info.name, info.tag);
break;
case Token:
ast_token(info.name, info.tag);
break;
default:
throw std::logic_error("Invalid Ast type was used...");
}
}
ast_end(tag);
return *this; return *this;
} }
@ -2086,6 +2061,45 @@ private:
} }
} }
void ast_node(const char* name, int tag) {
(*this)[name] = [=](const SemanticValues& sv) {
return std::make_shared<Ast>(name, tag, sv.map<std::shared_ptr<Ast>>());
};
}
void ast_node_optimizable(const char* name, int tag) {
(*this)[name] = [=](const SemanticValues& sv) {
if (sv.size() == 1) {
std::shared_ptr<Ast> ast = sv[0].get<std::shared_ptr<Ast>>();
return ast;
}
return std::make_shared<Ast>(name, tag, sv.map<std::shared_ptr<Ast>>());
};
}
void ast_token(const char* name, int tag) {
(*this)[name] = [=](const SemanticValues& sv) {
return std::make_shared<Ast>(name, tag, std::string(sv.s, sv.n));
};
}
void ast_end(int tag) {
for (auto& x: *grammar_) {
const auto& name = x.first;
auto& def = x.second;
auto& action = def.actions.front();
if (!action) {
action = [&](const SemanticValues& sv) {
if (sv.size() == 1) {
std::shared_ptr<Ast> ast = sv[0].get<std::shared_ptr<Ast>>();
return ast;
}
return std::make_shared<Ast>(name.c_str(), tag, sv.map<std::shared_ptr<Ast>>());
};
}
}
}
std::shared_ptr<Grammar> grammar_; std::shared_ptr<Grammar> grammar_;
std::string start_; std::string start_;
}; };