diff --git a/language/interpreter.cc b/language/interpreter.cc index ac01fd9..9fd67ac 100755 --- a/language/interpreter.cc +++ b/language/interpreter.cc @@ -8,7 +8,7 @@ using namespace std; struct Eval { static Value eval(const Ast& ast, shared_ptr env) { - switch (ast.type) { + switch (ast.tag) { case Statements: return eval_statements(ast, env); case While: return eval_while(ast, env); case If: return eval_if(ast, env); @@ -24,7 +24,7 @@ struct Eval } if (ast.is_token) { - return Value(ast.token); + return Value(string(ast.token)); } // NOTREACHED @@ -82,14 +82,13 @@ private: auto body = ast.nodes[1]; - auto f = Value::FunctionValue { + return Value(Value::FunctionValue { params, [=](shared_ptr callEnv) { callEnv->push_outer(env); return eval(*body, callEnv); } - }; - return Value(f); + }); }; static Value eval_function_call(const Ast& ast, shared_ptr env) { @@ -187,7 +186,7 @@ private: const auto& val = eval(*node, env); s += val.str(); } - return Value(s); + return Value(std::move(s)); }; static Value dereference_identirier(shared_ptr env, const string& var) { diff --git a/language/interpreter.hpp b/language/interpreter.hpp index bc42574..a569e33 100755 --- a/language/interpreter.hpp +++ b/language/interpreter.hpp @@ -18,11 +18,14 @@ struct Value }; explicit Value() : type(Undefined) {} - explicit Value(bool b) : type(Bool) { v = b; } - explicit Value(long l) : type(Long) { v = l; } - explicit Value(const std::string& s) : type(String) { v = s; } - explicit Value(const ArrayValue& a) : type(Array) { v = a; } - explicit Value(const FunctionValue& f) : type(Function) { v = f; } + explicit Value(bool b) : type(Bool), v(b) {} + explicit Value(long l) : type(Long), v(l) {} + explicit Value(std::string&& s) : type(String), v(s) {} + explicit Value(ArrayValue&& a) : type(Array), v(a) {} + 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 { switch (type) { @@ -210,14 +213,13 @@ struct Environment } void setup_built_in_functions() { - auto func_pretty_print = Value::FunctionValue { + set("pp", Value(Value::FunctionValue { { "arg" }, [](std::shared_ptr env) { std::cout << env->get("arg").str() << std::endl; return Value(); } - }; - set("pp", Value(func_pretty_print)); + })); } private: diff --git a/language/parser.cc b/language/parser.cc index 99abeb3..1461a27 100644 --- a/language/parser.cc +++ b/language/parser.cc @@ -43,7 +43,7 @@ static auto g_grammar = R"( Comment <- '/*' (!'*/' .)* '*/' / ('#' / '//') (!(EndOfLine / EndOfFile) .)* (EndOfLine / EndOfFile) )"; -peglib::peg& get_parser() +peg& get_parser() { static peg parser; @@ -60,28 +60,29 @@ peglib::peg& get_parser() throw logic_error("invalid peg grammar"); } - parser - .ast_node_optimizable("STATEMENTS", Statements) - .ast_node("WHILE", While) - .ast_node("ASSIGNMENT", Assignment) - .ast_node("IF", If) - .ast_node("FUNCTION", Function) - .ast_node("PARAMETERS") - .ast_node("FUNCTION_CALL", FunctionCall) - .ast_node("ARGUMENTS") - .ast_node_optimizable("PRIMARY", Condition) - .ast_node_optimizable("CONDITION", BinExpresion) - .ast_node_optimizable("TERM", BinExpresion) - .ast_token("CONDITION_OPERATOR") - .ast_token("TERM_OPERATOR") - .ast_token("FACTOR_OPERATOR") - .ast_token("NUMBER", Number) - .ast_token("BOOLEAN", Boolean) - .ast_token("STRING") - .ast_token("IDENTIFIER", Identifier) - .ast_node("INTERPOLATED_STRING", InterpolatedString) - .ast_token("INTERPOLATED_CONTENT") - .ast_end(); + parser.ast({ + { peg::AstNodeType::Regular, "STATEMENTS", Statements }, + { peg::AstNodeType::Regular, "WHILE", While }, + { peg::AstNodeType::Regular, "ASSIGNMENT", Assignment }, + { peg::AstNodeType::Regular, "IF", If }, + { peg::AstNodeType::Regular, "FUNCTION", Function }, + { peg::AstNodeType::Regular, "PARAMETERS", Undefined }, + { peg::AstNodeType::Regular, "FUNCTION_CALL", FunctionCall }, + { peg::AstNodeType::Regular, "ARGUMENTS", Undefined }, + { peg::AstNodeType::Optimizable, "PRIMARY", Condition }, + { peg::AstNodeType::Optimizable, "CONDITION", BinExpresion }, + { peg::AstNodeType::Optimizable, "TERM", BinExpresion }, + { peg::AstNodeType::Token, "CONDITION_OPERATOR", Undefined }, + { peg::AstNodeType::Token, "TERM_OPERATOR", Undefined }, + { peg::AstNodeType::Token, "FACTOR_OPERATOR", Undefined }, + { peg::AstNodeType::Token, "NUMBER", Number }, + { peg::AstNodeType::Token, "BOOLEAN", Boolean }, + { peg::AstNodeType::Token, "STRING", Undefined }, + { peg::AstNodeType::Token, "IDENTIFIER", Identifier }, + { peg::AstNodeType::Regular, "INTERPOLATED_STRING", InterpolatedString }, + { peg::AstNodeType::Token, "INTERPOLATED_CONTENT", Undefined }, + }, + Undefined); } return parser; diff --git a/language/parser.hpp b/language/parser.hpp index 001b976..31fa8d3 100644 --- a/language/parser.hpp +++ b/language/parser.hpp @@ -1,7 +1,8 @@ #include -enum AstType +enum AstTag { + Undefined, Statements, While, If, FunctionCall, Assignment, Condition, BinExpresion, Identifier, InterpolatedString, Number, Boolean, Function diff --git a/peglib.h b/peglib.h index f8cb736..8fba467 100644 --- a/peglib.h +++ b/peglib.h @@ -65,15 +65,6 @@ public: return *this; } - template - any& operator=(const T& value) { - if (content_) { - delete content_; - } - content_ = new holder(value); - return *this; - } - ~any() { delete content_; } @@ -1831,16 +1822,16 @@ private: struct Ast { - Ast(const char* _name, int _type, const std::vector>& _nodes) - : name(_name), type(_type), is_token(false), nodes(_nodes) {} + Ast(const char* _name, int _tag, const std::vector>& _nodes) + : name(_name), tag(_tag), is_token(false), nodes(_nodes) {} - Ast(const char* _name, int _type, const std::string& _token) - : name(_name), type(_type), is_token(true), token(_token) {} + Ast(const char* _name, int _tag, const std::string& _token) + : name(_name), tag(_tag), is_token(true), token(_token) {} void print() const; const std::string name; - const int type; + const int tag; const bool is_token; const std::string token; const std::vector> nodes; @@ -2022,32 +2013,77 @@ public: } } - peg& ast_node(const char* name, int type = -1) { + enum AstNodeType { + Regular, + Optimizable, + Token + }; + + struct AstNodeInfo { + AstNodeType type; + const char* name; + int tag; + }; + + peg& ast(std::initializer_list 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; + } + + MatchAction match_action; + Log log; + +private: + void output_log(const char* s, size_t n, Log log, const Definition::Result& r) const { + if (log) { + if (!r.ret) { + auto line = line_info(s, r.error_pos); + log(line.first, line.second, r.message.empty() ? "syntax error" : r.message); + } else if (r.len != n) { + auto line = line_info(s, s + r.len); + log(line.first, line.second, "syntax error"); + } + } + } + + void ast_node(const char* name, int tag) { (*this)[name] = [=](const SemanticValues& sv) { - return std::make_shared(name, type, sv.map>()); + return std::make_shared(name, tag, sv.map>()); }; - return *this; } - peg& ast_node_optimizable(const char* name, int type = -1) { + void ast_node_optimizable(const char* name, int tag) { (*this)[name] = [=](const SemanticValues& sv) { if (sv.size() == 1) { std::shared_ptr ast = sv[0].get>(); return ast; } - return std::make_shared(name, type, sv.map>()); + return std::make_shared(name, tag, sv.map>()); }; - return *this; } - peg& ast_token(const char* name, int type = -1) { + void ast_token(const char* name, int tag) { (*this)[name] = [=](const SemanticValues& sv) { - return std::make_shared(name, type, std::string(sv.s, sv.n)); + return std::make_shared(name, tag, std::string(sv.s, sv.n)); }; - return *this; } - peg& ast_end() { + void ast_end(int tag) { for (auto& x: *grammar_) { const auto& name = x.first; auto& def = x.second; @@ -2058,32 +2094,10 @@ public: std::shared_ptr ast = sv[0].get>(); return ast; } - return std::make_shared(name.c_str(), -1, sv.map>()); + return std::make_shared(name.c_str(), tag, sv.map>()); }; } } - return *this; - }; - - peg& set_logger(Log _log) { - log = _log; - return *this; - } - - MatchAction match_action; - Log log; - -private: - void output_log(const char* s, size_t n, Log log, const Definition::Result& r) const { - if (log) { - if (!r.ret) { - auto line = line_info(s, r.error_pos); - log(line.first, line.second, r.message.empty() ? "syntax error" : r.message); - } else if (r.len != n) { - auto line = line_info(s, s + r.len); - log(line.first, line.second, "syntax error"); - } - } } std::shared_ptr grammar_;