diff --git a/peglib.h b/peglib.h index 7295355..d4001a2 100644 --- a/peglib.h +++ b/peglib.h @@ -245,11 +245,16 @@ public: PrioritizedChoice(std::vector>&& rules) : rules_(std::move(rules)) {} Match parse(const char* s, size_t l, SemanticValues& sv) const { + auto sz = sv.values.size(); for (const auto& rule : rules_) { auto m = rule->parse(s, l, sv); if (m.ret) { return success(m.len); } + while (sv.values.size() > sz) { + sv.values.pop_back(); + sv.names.pop_back(); + } } return fail(); } diff --git a/test/test.cc b/test/test.cc index 5d78613..6ae3b45 100644 --- a/test/test.cc +++ b/test/test.cc @@ -5,6 +5,11 @@ #include #include +TEST_CASE("Empty syntax test", "[general]") +{ + REQUIRE_THROWS(peglib::make_parser("")); +} + TEST_CASE("String capture test", "[general]") { auto parser = peglib::make_parser( @@ -95,6 +100,35 @@ TEST_CASE("Lambda action test", "[general]") REQUIRE(ss == "hello"); } +TEST_CASE("Simple calculator test", "[general]") +{ + auto syntax = + " Additive <- Multitive '+' Additive / Multitive " + " Multitive <- Primary '*' Multitive / Primary " + " Primary <- '(' Additive ')' / Number " + " Number <- [0-9]+ "; + + auto parser = make_parser(syntax); + + parser["Additive"] = [](const vector& v) { + return v.size() == 1 ? v[0] : v[0].get() + v[1].get(); + }; + parser["Multitive"] = [](const vector& v) { + return v.size() == 1 ? v[0] : v[0].get() * v[1].get(); + }; + parser["Primary"] = [](const vector& v) { + return v.size() == 1 ? v[0] : v[1]; + }; + parser["Number"] = [](const char* s, size_t l) { + return atoi(s); + }; + + int val; + parser.parse("1+2*3", val); + + REQUIRE(val == 7); +} + TEST_CASE("Calculator test", "[general]") { // Construct grammer