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;
size_t value_stack_size = 0;
std::vector<Definition*> rule_stack;
std::vector<std::vector<std::shared_ptr<Ope>>> 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<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);
} else {
// Definition
c.push_args(std::vector<std::shared_ptr<Ope>>());
auto se = make_scope_exit([&]() { c.pop_args(); });
auto ope = get_core_operator();
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);
}
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]+