This commit is contained in:
yhirose 2020-05-31 23:46:46 -04:00
parent f9e0d252d9
commit 072cdb6d23
2 changed files with 38 additions and 7 deletions

View File

@ -840,6 +840,8 @@ public:
std::vector<std::shared_ptr<SemanticValues>> value_stack; std::vector<std::shared_ptr<SemanticValues>> value_stack;
size_t value_stack_size = 0; size_t value_stack_size = 0;
std::vector<Definition*> rule_stack;
std::vector<std::vector<std::shared_ptr<Ope>>> args_stack; std::vector<std::vector<std::shared_ptr<Ope>>> args_stack;
bool in_token = false; bool in_token = false;
@ -2475,7 +2477,12 @@ inline size_t Holder::parse_core(const char *s, size_t n, SemanticValues &sv,
// Macro reference // Macro reference
// TODO: need packrat support // 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; size_t len;
any val; any val;
@ -2491,7 +2498,9 @@ inline size_t Holder::parse_core(const char *s, size_t n, SemanticValues &sv,
auto &chldsv = c.push(); auto &chldsv = c.push();
c.rule_stack.push_back(outer_);
len = ope_->parse(s, n, chldsv, c, dt); len = ope_->parse(s, n, chldsv, c, dt);
c.rule_stack.pop_back();
// Invoke action // Invoke action
if (success(len)) { if (success(len)) {
@ -2556,7 +2565,7 @@ inline size_t Reference::parse_core(const char *s, size_t n, SemanticValues &sv,
// Reference rule // Reference rule
if (rule_->is_macro) { if (rule_->is_macro) {
// Macro // Macro
FindReference vis(c.top_args(), rule_->params); FindReference vis(c.top_args(), c.rule_stack.back()->params);
// Collect arguments // Collect arguments
std::vector<std::shared_ptr<Ope>> args; std::vector<std::shared_ptr<Ope>> 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); return ope->parse(s, n, sv, c, dt);
} else { } else {
// Definition // Definition
c.push_args(std::vector<std::shared_ptr<Ope>>());
auto se = make_scope_exit([&]() { c.pop_args(); });
auto ope = get_core_operator(); auto ope = get_core_operator();
return ope->parse(s, n, sv, c, dt); return ope->parse(s, n, sv, c, dt);
} }

View File

@ -903,20 +903,40 @@ TEST_CASE("Macro token check test", "[macro]")
REQUIRE(parser["T"].is_token() == true); REQUIRE(parser["T"].is_token() == true);
} }
TEST_CASE("Macro rule-parameter collision", "[macro]") TEST_CASE("Macro passes an arg to another macro", "[macro]") {
{ parser parser(R"(
parser parser(R"(
A <- B(C) A <- B(C)
B(D) <- D B(D) <- D
C <- 'c' C <- 'c'
D <- 'd' 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"( parser parser(R"(
S <- _ (WORD _)+ S <- _ (WORD _)+
WORD <- [A-Za-z]+ WORD <- [A-Za-z]+