diff --git a/README.md b/README.md index db747f3..e7c483f 100644 --- a/README.md +++ b/README.md @@ -41,19 +41,20 @@ int main(void) { peg parser(syntax); // (3) Setup an action - parser["Additive"] = { - nullptr, // Default action - [](const SemanticValues& sv) { - return sv[0].get() + sv[1].get(); // "Multitive '+' Additive" - }, - [](const SemanticValues& sv) { return sv[0]; } // "Multitive" + parser["Additive"] = [](const SemanticValues& sv) { + switch (sv.choice) { + case 0: // "Multitive '+' Additive" + return sv[0].get() + sv[1].get(); + default: // "Multitive" + return sv[0].get(); + } }; parser["Multitive"] = [](const SemanticValues& sv) { switch (sv.choice) { - case 0: // "Multitive '+' Additive" + case 0: // "Primary '*' Multitive" return sv[0].get() * sv[1].get(); - default: // "Multitive" + default: // "Primary" return sv[0].get(); } }; @@ -63,7 +64,7 @@ int main(void) { }; // (4) Parse - parser.packrat_parsing(true); // Enable packrat parsing. + parser.packrat_parsing(); // Enable packrat parsing. int val; parser.parse("(1+2)*3", val); diff --git a/peglib.h b/peglib.h index 0b83364..1947cda 100644 --- a/peglib.h +++ b/peglib.h @@ -946,7 +946,7 @@ public: 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_; Definition* outer_; @@ -1076,15 +1076,13 @@ public: }; Definition() - : actions(1) - , ignoreSemanticValue(false) + : ignoreSemanticValue(false) , enablePackratParsing(false) , is_token(false) , holder_(std::make_shared(this)) {} Definition(const Definition& rhs) : name(rhs.name) - , actions(1) , ignoreSemanticValue(false) , enablePackratParsing(false) , is_token(false) @@ -1095,7 +1093,6 @@ public: Definition(Definition&& rhs) : name(std::move(rhs.name)) - , actions(1) , ignoreSemanticValue(rhs.ignoreSemanticValue) , enablePackratParsing(rhs.enablePackratParsing) , is_token(rhs.is_token) @@ -1105,8 +1102,7 @@ public: } Definition(const std::shared_ptr& ope) - : actions(1) - , ignoreSemanticValue(false) + : ignoreSemanticValue(false) , enablePackratParsing(false) , is_token(false) , holder_(std::make_shared(this)) @@ -1182,14 +1178,8 @@ public: return parse_and_get_value(s, n, dt, val); } - Definition& operator=(Action action) { - assert(!actions.empty()); - actions[0] = action; - return *this; - } - - Definition& operator=(std::initializer_list ini) { - actions = ini; + Definition& operator=(Action a) { + action = a; return *this; } @@ -1210,7 +1200,7 @@ public: std::string name; size_t id; - std::vector actions; + Action action; std::function error_message; bool ignoreSemanticValue; bool enablePackratParsing; @@ -1258,13 +1248,6 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context // Invoke action 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) { anchors = chldsv.s; anchorn = chldsv.n; @@ -1274,7 +1257,7 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context } try { - val = reduce(chldsv, dt, action); + val = reduce(chldsv, dt); } catch (const parse_error& e) { if (e.what()) { c.message_pos = s; @@ -1299,9 +1282,9 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context return len; } -inline any Holder::reduce(const SemanticValues& sv, any& dt, const Action& action) const { - if (action) { - return action(sv, dt); +inline any Holder::reduce(const SemanticValues& sv, any& dt) const { + if (outer_->action) { + return outer_->action(sv, dt); } else if (sv.empty()) { return any(); } else { @@ -1674,8 +1657,8 @@ private: auto ignore = (sv.size() == 4); auto baseId = ignore ? 1 : 0; - const auto& name = sv[baseId].val.get(); - auto ope = sv[baseId + 2].val.get>(); + const auto& name = sv[baseId].get(); + auto ope = sv[baseId + 2].get>(); auto& grammar = *data.grammar; if (grammar.find(name) == grammar.end()) { @@ -1694,11 +1677,11 @@ private: g["Expression"] = [&](const SemanticValues& sv) { if (sv.size() == 1) { - return sv[0].val.get>(); + return sv[0].get>(); } else { std::vector> opes; for (auto i = 0u; i < sv.size(); i++) { - opes.push_back(sv[i].val.get>()); + opes.push_back(sv[i].get>()); } const std::shared_ptr ope = std::make_shared(opes); return ope; @@ -1707,11 +1690,11 @@ private: g["Sequence"] = [&](const SemanticValues& sv) { if (sv.size() == 1) { - return sv[0].val.get>(); + return sv[0].get>(); } else { std::vector> opes; for (const auto& x: sv) { - opes.push_back(x.val.get>()); + opes.push_back(x.get>()); } const std::shared_ptr ope = std::make_shared(opes); return ope; @@ -1721,11 +1704,11 @@ private: g["Prefix"] = [&](const SemanticValues& sv) { std::shared_ptr ope; if (sv.size() == 1) { - ope = sv[0].val.get>(); + ope = sv[0].get>(); } else { assert(sv.size() == 2); - auto tok = sv[0].val.get(); - ope = sv[1].val.get>(); + auto tok = sv[0].get(); + ope = sv[1].get>(); if (tok == '&') { ope = apd(ope); } else { // '!' @@ -1736,12 +1719,12 @@ private: }; g["Suffix"] = [&](const SemanticValues& sv) { - auto ope = sv[0].val.get>(); + auto ope = sv[0].get>(); if (sv.size() == 1) { return ope; } else { assert(sv.size() == 2); - auto tok = sv[1].val.get(); + auto tok = sv[1].get(); if (tok == '?') { return opt(ope); } else if (tok == '*') { @@ -1752,45 +1735,40 @@ private: } }; - g["Primary"].actions = { - // Default - [&](const SemanticValues& sv) { - return sv[0]; - }, - // Reference - [&](const SemanticValues& sv, any& dt) { - Data& data = *dt.get(); + g["Primary"] = [&](const SemanticValues& sv, any& dt) { + Data& data = *dt.get(); + switch (sv.choice) { + case 0: { // Reference + auto ignore = (sv.size() == 2); + auto baseId = ignore ? 1 : 0; - auto ignore = (sv.size() == 2); - auto baseId = ignore ? 1 : 0; + const auto& ident = sv[baseId].get(); - const auto& ident = sv[baseId].val.get(); + if (data.references.find(ident) == data.references.end()) { + data.references[ident] = sv.s; // for error handling + } - if (data.references.find(ident) == data.references.end()) { - data.references[ident] = sv.s; // for error handling + if (ignore) { + return ign(ref(*data.grammar, ident, sv.s)); + } else { + return ref(*data.grammar, ident, sv.s); + } } - - if (ignore) { - return ign(ref(*data.grammar, ident, sv.s)); - } else { - return ref(*data.grammar, ident, sv.s); + case 1: { // (Expression) + return sv[1].get>(); + } + case 2: { // Anchor + auto ope = sv[1].get>(); + return anc(ope); + } + case 3: { // Capture + auto name = std::string(sv[0].s, sv[0].n); + auto ope = sv[1].get>(); + return cap(ope, data.match_action, ++data.capture_count, name); + } + default: { + return sv[0].get>(); } - }, - // (Expression) - [&](const SemanticValues& sv) { - return sv[1]; - }, - // Anchor - [&](const SemanticValues& sv) { - auto ope = sv[1].val.get>(); - return anc(ope); - }, - // Capture - [&](const SemanticValues& sv, any& dt) { - Data& data = *dt.get(); - auto name = std::string(sv[0].s, sv[0].n); - auto ope = sv[1].val.get>(); - return cap(ope, data.match_action, ++data.capture_count, name); } }; @@ -2249,10 +2227,9 @@ private: for (auto& x: *grammar_) { const auto& name = x.first; auto& rule = x.second; - auto& action = rule.actions.front(); - if (!action) { + if (!rule.action) { auto is_token = rule.is_token; - action = [=](const SemanticValues& sv) { + rule.action = [=](const SemanticValues& sv) { if (is_token) { return std::make_shared(name.c_str(), AstDefaultTag, std::string(sv.s, sv.n)); } diff --git a/test/test.cc b/test/test.cc index 41c6fe6..5e166b2 100644 --- a/test/test.cc +++ b/test/test.cc @@ -284,21 +284,21 @@ TEST_CASE("Simple calculator test", "[general]") peg parser(syntax); - parser["Additive"] = { - // Default action - nullptr, - // Action for the first choice - [](const SemanticValues& sv) { return sv[0].val.get() + sv[1].val.get(); }, - // Action for the second choice - [](const SemanticValues& sv) { return sv[0]; } + parser["Additive"] = [](const SemanticValues& sv) { + switch (sv.choice) { + case 0: + return sv[0].get() + sv[1].get(); + default: + return sv[0].get(); + } }; parser["Multitive"] = [](const SemanticValues& sv) { switch (sv.choice) { - case 0: // Action for the first choice - return sv[0].val.get() * sv[1].val.get(); - default: // Action for the second choice - return sv[0].val.get(); + case 0: + return sv[0].get() * sv[1].get(); + default: + return sv[0].get(); } };