Refactoring.

pull/3/head
yhirose 9 years ago
parent 18ffa7d28c
commit f8da5085aa
  1. 11
      language/interpreter.cc
  2. 18
      language/interpreter.hpp
  3. 47
      language/parser.cc
  4. 3
      language/parser.hpp
  5. 108
      peglib.h

@ -8,7 +8,7 @@ using namespace std;
struct Eval
{
static Value eval(const Ast& ast, shared_ptr<Environment> 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<Environment> callEnv) {
callEnv->push_outer(env);
return eval(*body, callEnv);
}
};
return Value(f);
});
};
static Value eval_function_call(const Ast& ast, shared_ptr<Environment> 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<Environment> env, const string& var) {

@ -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<Environment> env) {
std::cout << env->get("arg").str() << std::endl;
return Value();
}
};
set("pp", Value(func_pretty_print));
}));
}
private:

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

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

@ -65,15 +65,6 @@ public:
return *this;
}
template <typename T>
any& operator=(const T& value) {
if (content_) {
delete content_;
}
content_ = new holder<T>(value);
return *this;
}
~any() {
delete content_;
}
@ -1831,16 +1822,16 @@ private:
struct Ast
{
Ast(const char* _name, int _type, const std::vector<std::shared_ptr<Ast>>& _nodes)
: name(_name), type(_type), is_token(false), nodes(_nodes) {}
Ast(const char* _name, int _tag, const std::vector<std::shared_ptr<Ast>>& _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<std::shared_ptr<Ast>> 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<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;
}
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<Ast>(name, type, sv.map<std::shared_ptr<Ast>>());
return std::make_shared<Ast>(name, tag, sv.map<std::shared_ptr<Ast>>());
};
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> ast = sv[0].get<std::shared_ptr<Ast>>();
return ast;
}
return std::make_shared<Ast>(name, type, sv.map<std::shared_ptr<Ast>>());
return std::make_shared<Ast>(name, tag, sv.map<std::shared_ptr<Ast>>());
};
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<Ast>(name, type, std::string(sv.s, sv.n));
return std::make_shared<Ast>(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> 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 std::make_shared<Ast>(name.c_str(), tag, sv.map<std::shared_ptr<Ast>>());
};
}
}
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> grammar_;

Loading…
Cancel
Save