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
|
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) {
|
||||||
|
@ -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:
|
||||||
|
@ -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;
|
||||||
|
@ -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
128
peglib.h
@ -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_;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user