mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 20:05:31 +00:00
Refactoring.
This commit is contained in:
parent
18ffa7d28c
commit
f8da5085aa
@ -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
|
||||
|
128
peglib.h
128
peglib.h
@ -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,51 +2013,35 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
peg& ast_node(const char* name, int type = -1) {
|
||||
(*this)[name] = [=](const SemanticValues& sv) {
|
||||
return std::make_shared<Ast>(name, type, sv.map<std::shared_ptr<Ast>>());
|
||||
};
|
||||
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;
|
||||
enum AstNodeType {
|
||||
Regular,
|
||||
Optimizable,
|
||||
Token
|
||||
};
|
||||
|
||||
peg& set_logger(Log _log) {
|
||||
log = _log;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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::string start_;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user