diff --git a/peglib.h b/peglib.h index f76d93f..8896bed 100644 --- a/peglib.h +++ b/peglib.h @@ -840,6 +840,8 @@ public: std::vector> value_stack; size_t value_stack_size = 0; + + std::vector rule_stack; std::vector>> args_stack; bool in_token = false; @@ -2475,7 +2477,12 @@ inline size_t Holder::parse_core(const char *s, size_t n, SemanticValues &sv, // Macro reference // TODO: need packrat support - if (outer_->is_macro) { return ope_->parse(s, n, sv, c, dt); } + if (outer_->is_macro) { + c.rule_stack.push_back(outer_); + auto len = ope_->parse(s, n, sv, c, dt); + c.rule_stack.pop_back(); + return len; + } size_t len; any val; @@ -2491,7 +2498,9 @@ inline size_t Holder::parse_core(const char *s, size_t n, SemanticValues &sv, auto &chldsv = c.push(); + c.rule_stack.push_back(outer_); len = ope_->parse(s, n, chldsv, c, dt); + c.rule_stack.pop_back(); // Invoke action if (success(len)) { @@ -2556,7 +2565,7 @@ inline size_t Reference::parse_core(const char *s, size_t n, SemanticValues &sv, // Reference rule if (rule_->is_macro) { // Macro - FindReference vis(c.top_args(), rule_->params); + FindReference vis(c.top_args(), c.rule_stack.back()->params); // Collect arguments std::vector> args; @@ -2571,6 +2580,8 @@ inline size_t Reference::parse_core(const char *s, size_t n, SemanticValues &sv, return ope->parse(s, n, sv, c, dt); } else { // Definition + c.push_args(std::vector>()); + auto se = make_scope_exit([&]() { c.pop_args(); }); auto ope = get_core_operator(); return ope->parse(s, n, sv, c, dt); } diff --git a/test/test2.cc b/test/test2.cc index c6073aa..2b249e3 100644 --- a/test/test2.cc +++ b/test/test2.cc @@ -903,20 +903,40 @@ TEST_CASE("Macro token check test", "[macro]") REQUIRE(parser["T"].is_token() == true); } -TEST_CASE("Macro rule-parameter collision", "[macro]") -{ - parser parser(R"( +TEST_CASE("Macro passes an arg to another macro", "[macro]") { + parser parser(R"( A <- B(C) B(D) <- D C <- 'c' D <- 'd' )"); - REQUIRE(parser.parse("c")); + REQUIRE(parser.parse("c")); } -TEST_CASE("Line information test", "[line information]") +TEST_CASE("Nested macro call", "[macro]") { + parser parser(R"( + A <- B(T) + B(X) <- C(X) + C(Y) <- Y + T <- 'val' + )"); + + REQUIRE(parser.parse("val")); +} + +TEST_CASE("Nested macro call2", "[macro]") { + parser parser(R"( + START <- A('TestVal1', 'TestVal2')+ + A(Aarg1, Aarg2) <- B(Aarg1) '#End' + B(Barg1) <- '#' Barg1 + )"); + + REQUIRE(parser.parse("#TestVal1#End")); +} + +TEST_CASE("Line information test", "[line information]") { parser parser(R"( S <- _ (WORD _)+ WORD <- [A-Za-z]+