Simplefied code.

This commit is contained in:
yhirose 2015-06-15 23:26:49 -04:00
parent 30971d28de
commit 2aa60699be
3 changed files with 73 additions and 95 deletions

View File

@ -41,19 +41,20 @@ int main(void) {
peg parser(syntax); peg parser(syntax);
// (3) Setup an action // (3) Setup an action
parser["Additive"] = { parser["Additive"] = [](const SemanticValues& sv) {
nullptr, // Default action switch (sv.choice) {
[](const SemanticValues& sv) { case 0: // "Multitive '+' Additive"
return sv[0].get<int>() + sv[1].get<int>(); // "Multitive '+' Additive" return sv[0].get<int>() + sv[1].get<int>();
}, default: // "Multitive"
[](const SemanticValues& sv) { return sv[0]; } // "Multitive" return sv[0].get<int>();
}
}; };
parser["Multitive"] = [](const SemanticValues& sv) { parser["Multitive"] = [](const SemanticValues& sv) {
switch (sv.choice) { switch (sv.choice) {
case 0: // "Multitive '+' Additive" case 0: // "Primary '*' Multitive"
return sv[0].get<int>() * sv[1].get<int>(); return sv[0].get<int>() * sv[1].get<int>();
default: // "Multitive" default: // "Primary"
return sv[0].get<int>(); return sv[0].get<int>();
} }
}; };
@ -63,7 +64,7 @@ int main(void) {
}; };
// (4) Parse // (4) Parse
parser.packrat_parsing(true); // Enable packrat parsing. parser.packrat_parsing(); // Enable packrat parsing.
int val; int val;
parser.parse("(1+2)*3", val); parser.parse("(1+2)*3", val);

127
peglib.h
View File

@ -946,7 +946,7 @@ public:
void accept(Visitor& v) override; void accept(Visitor& v) override;
any reduce(const SemanticValues& sv, any& dt, const Action& action) const; any reduce(const SemanticValues& sv, any& dt) const;
std::shared_ptr<Ope> ope_; std::shared_ptr<Ope> ope_;
Definition* outer_; Definition* outer_;
@ -1076,15 +1076,13 @@ public:
}; };
Definition() Definition()
: actions(1) : ignoreSemanticValue(false)
, ignoreSemanticValue(false)
, enablePackratParsing(false) , enablePackratParsing(false)
, is_token(false) , is_token(false)
, holder_(std::make_shared<Holder>(this)) {} , holder_(std::make_shared<Holder>(this)) {}
Definition(const Definition& rhs) Definition(const Definition& rhs)
: name(rhs.name) : name(rhs.name)
, actions(1)
, ignoreSemanticValue(false) , ignoreSemanticValue(false)
, enablePackratParsing(false) , enablePackratParsing(false)
, is_token(false) , is_token(false)
@ -1095,7 +1093,6 @@ public:
Definition(Definition&& rhs) Definition(Definition&& rhs)
: name(std::move(rhs.name)) : name(std::move(rhs.name))
, actions(1)
, ignoreSemanticValue(rhs.ignoreSemanticValue) , ignoreSemanticValue(rhs.ignoreSemanticValue)
, enablePackratParsing(rhs.enablePackratParsing) , enablePackratParsing(rhs.enablePackratParsing)
, is_token(rhs.is_token) , is_token(rhs.is_token)
@ -1105,8 +1102,7 @@ public:
} }
Definition(const std::shared_ptr<Ope>& ope) Definition(const std::shared_ptr<Ope>& ope)
: actions(1) : ignoreSemanticValue(false)
, ignoreSemanticValue(false)
, enablePackratParsing(false) , enablePackratParsing(false)
, is_token(false) , is_token(false)
, holder_(std::make_shared<Holder>(this)) , holder_(std::make_shared<Holder>(this))
@ -1182,14 +1178,8 @@ public:
return parse_and_get_value(s, n, dt, val); return parse_and_get_value(s, n, dt, val);
} }
Definition& operator=(Action action) { Definition& operator=(Action a) {
assert(!actions.empty()); action = a;
actions[0] = action;
return *this;
}
Definition& operator=(std::initializer_list<Action> ini) {
actions = ini;
return *this; return *this;
} }
@ -1210,7 +1200,7 @@ public:
std::string name; std::string name;
size_t id; size_t id;
std::vector<Action> actions; Action action;
std::function<std::string ()> error_message; std::function<std::string ()> error_message;
bool ignoreSemanticValue; bool ignoreSemanticValue;
bool enablePackratParsing; bool enablePackratParsing;
@ -1258,13 +1248,6 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
// Invoke action // Invoke action
if (success(len)) { if (success(len)) {
assert(!outer_->actions.empty());
auto i = chldsv.choice + 1; // Index 0 is for the default action
const auto& action = (i < outer_->actions.size() && outer_->actions[i])
? outer_->actions[i]
: outer_->actions[0];
if (chldsv.s) { if (chldsv.s) {
anchors = chldsv.s; anchors = chldsv.s;
anchorn = chldsv.n; anchorn = chldsv.n;
@ -1274,7 +1257,7 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
} }
try { try {
val = reduce(chldsv, dt, action); val = reduce(chldsv, dt);
} catch (const parse_error& e) { } catch (const parse_error& e) {
if (e.what()) { if (e.what()) {
c.message_pos = s; c.message_pos = s;
@ -1299,9 +1282,9 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
return len; return len;
} }
inline any Holder::reduce(const SemanticValues& sv, any& dt, const Action& action) const { inline any Holder::reduce(const SemanticValues& sv, any& dt) const {
if (action) { if (outer_->action) {
return action(sv, dt); return outer_->action(sv, dt);
} else if (sv.empty()) { } else if (sv.empty()) {
return any(); return any();
} else { } else {
@ -1674,8 +1657,8 @@ private:
auto ignore = (sv.size() == 4); auto ignore = (sv.size() == 4);
auto baseId = ignore ? 1 : 0; auto baseId = ignore ? 1 : 0;
const auto& name = sv[baseId].val.get<std::string>(); const auto& name = sv[baseId].get<std::string>();
auto ope = sv[baseId + 2].val.get<std::shared_ptr<Ope>>(); auto ope = sv[baseId + 2].get<std::shared_ptr<Ope>>();
auto& grammar = *data.grammar; auto& grammar = *data.grammar;
if (grammar.find(name) == grammar.end()) { if (grammar.find(name) == grammar.end()) {
@ -1694,11 +1677,11 @@ private:
g["Expression"] = [&](const SemanticValues& sv) { g["Expression"] = [&](const SemanticValues& sv) {
if (sv.size() == 1) { if (sv.size() == 1) {
return sv[0].val.get<std::shared_ptr<Ope>>(); return sv[0].get<std::shared_ptr<Ope>>();
} else { } else {
std::vector<std::shared_ptr<Ope>> opes; std::vector<std::shared_ptr<Ope>> opes;
for (auto i = 0u; i < sv.size(); i++) { for (auto i = 0u; i < sv.size(); i++) {
opes.push_back(sv[i].val.get<std::shared_ptr<Ope>>()); opes.push_back(sv[i].get<std::shared_ptr<Ope>>());
} }
const std::shared_ptr<Ope> ope = std::make_shared<PrioritizedChoice>(opes); const std::shared_ptr<Ope> ope = std::make_shared<PrioritizedChoice>(opes);
return ope; return ope;
@ -1707,11 +1690,11 @@ private:
g["Sequence"] = [&](const SemanticValues& sv) { g["Sequence"] = [&](const SemanticValues& sv) {
if (sv.size() == 1) { if (sv.size() == 1) {
return sv[0].val.get<std::shared_ptr<Ope>>(); return sv[0].get<std::shared_ptr<Ope>>();
} else { } else {
std::vector<std::shared_ptr<Ope>> opes; std::vector<std::shared_ptr<Ope>> opes;
for (const auto& x: sv) { for (const auto& x: sv) {
opes.push_back(x.val.get<std::shared_ptr<Ope>>()); opes.push_back(x.get<std::shared_ptr<Ope>>());
} }
const std::shared_ptr<Ope> ope = std::make_shared<Sequence>(opes); const std::shared_ptr<Ope> ope = std::make_shared<Sequence>(opes);
return ope; return ope;
@ -1721,11 +1704,11 @@ private:
g["Prefix"] = [&](const SemanticValues& sv) { g["Prefix"] = [&](const SemanticValues& sv) {
std::shared_ptr<Ope> ope; std::shared_ptr<Ope> ope;
if (sv.size() == 1) { if (sv.size() == 1) {
ope = sv[0].val.get<std::shared_ptr<Ope>>(); ope = sv[0].get<std::shared_ptr<Ope>>();
} else { } else {
assert(sv.size() == 2); assert(sv.size() == 2);
auto tok = sv[0].val.get<char>(); auto tok = sv[0].get<char>();
ope = sv[1].val.get<std::shared_ptr<Ope>>(); ope = sv[1].get<std::shared_ptr<Ope>>();
if (tok == '&') { if (tok == '&') {
ope = apd(ope); ope = apd(ope);
} else { // '!' } else { // '!'
@ -1736,12 +1719,12 @@ private:
}; };
g["Suffix"] = [&](const SemanticValues& sv) { g["Suffix"] = [&](const SemanticValues& sv) {
auto ope = sv[0].val.get<std::shared_ptr<Ope>>(); auto ope = sv[0].get<std::shared_ptr<Ope>>();
if (sv.size() == 1) { if (sv.size() == 1) {
return ope; return ope;
} else { } else {
assert(sv.size() == 2); assert(sv.size() == 2);
auto tok = sv[1].val.get<char>(); auto tok = sv[1].get<char>();
if (tok == '?') { if (tok == '?') {
return opt(ope); return opt(ope);
} else if (tok == '*') { } else if (tok == '*') {
@ -1752,45 +1735,40 @@ private:
} }
}; };
g["Primary"].actions = { g["Primary"] = [&](const SemanticValues& sv, any& dt) {
// Default Data& data = *dt.get<Data*>();
[&](const SemanticValues& sv) { switch (sv.choice) {
return sv[0]; case 0: { // Reference
}, auto ignore = (sv.size() == 2);
// Reference auto baseId = ignore ? 1 : 0;
[&](const SemanticValues& sv, any& dt) {
Data& data = *dt.get<Data*>();
auto ignore = (sv.size() == 2); const auto& ident = sv[baseId].get<std::string>();
auto baseId = ignore ? 1 : 0;
const auto& ident = sv[baseId].val.get<std::string>(); if (data.references.find(ident) == data.references.end()) {
data.references[ident] = sv.s; // for error handling
}
if (data.references.find(ident) == data.references.end()) { if (ignore) {
data.references[ident] = sv.s; // for error handling return ign(ref(*data.grammar, ident, sv.s));
} else {
return ref(*data.grammar, ident, sv.s);
}
} }
case 1: { // (Expression)
if (ignore) { return sv[1].get<std::shared_ptr<Ope>>();
return ign(ref(*data.grammar, ident, sv.s)); }
} else { case 2: { // Anchor
return ref(*data.grammar, ident, sv.s); auto ope = sv[1].get<std::shared_ptr<Ope>>();
return anc(ope);
}
case 3: { // Capture
auto name = std::string(sv[0].s, sv[0].n);
auto ope = sv[1].get<std::shared_ptr<Ope>>();
return cap(ope, data.match_action, ++data.capture_count, name);
}
default: {
return sv[0].get<std::shared_ptr<Ope>>();
} }
},
// (Expression)
[&](const SemanticValues& sv) {
return sv[1];
},
// Anchor
[&](const SemanticValues& sv) {
auto ope = sv[1].val.get<std::shared_ptr<Ope>>();
return anc(ope);
},
// Capture
[&](const SemanticValues& sv, any& dt) {
Data& data = *dt.get<Data*>();
auto name = std::string(sv[0].s, sv[0].n);
auto ope = sv[1].val.get<std::shared_ptr<Ope>>();
return cap(ope, data.match_action, ++data.capture_count, name);
} }
}; };
@ -2249,10 +2227,9 @@ private:
for (auto& x: *grammar_) { for (auto& x: *grammar_) {
const auto& name = x.first; const auto& name = x.first;
auto& rule = x.second; auto& rule = x.second;
auto& action = rule.actions.front(); if (!rule.action) {
if (!action) {
auto is_token = rule.is_token; auto is_token = rule.is_token;
action = [=](const SemanticValues& sv) { rule.action = [=](const SemanticValues& sv) {
if (is_token) { if (is_token) {
return std::make_shared<Ast>(name.c_str(), AstDefaultTag, std::string(sv.s, sv.n)); return std::make_shared<Ast>(name.c_str(), AstDefaultTag, std::string(sv.s, sv.n));
} }

View File

@ -284,21 +284,21 @@ TEST_CASE("Simple calculator test", "[general]")
peg parser(syntax); peg parser(syntax);
parser["Additive"] = { parser["Additive"] = [](const SemanticValues& sv) {
// Default action switch (sv.choice) {
nullptr, case 0:
// Action for the first choice return sv[0].get<int>() + sv[1].get<int>();
[](const SemanticValues& sv) { return sv[0].val.get<int>() + sv[1].val.get<int>(); }, default:
// Action for the second choice return sv[0].get<int>();
[](const SemanticValues& sv) { return sv[0]; } }
}; };
parser["Multitive"] = [](const SemanticValues& sv) { parser["Multitive"] = [](const SemanticValues& sv) {
switch (sv.choice) { switch (sv.choice) {
case 0: // Action for the first choice case 0:
return sv[0].val.get<int>() * sv[1].val.get<int>(); return sv[0].get<int>() * sv[1].get<int>();
default: // Action for the second choice default:
return sv[0].val.get<int>(); return sv[0].get<int>();
} }
}; };