Avoid creating redundant auxiliary repeat rules

This commit is contained in:
Max Brunsfeld 2015-04-16 17:42:22 -07:00
parent 9ef52ce2fb
commit e8db35af6b
3 changed files with 2227 additions and 2263 deletions

View file

@ -67,6 +67,28 @@ describe("expand_repeats", []() {
})));
});
it("does not create redundant auxiliary rules", [&]() {
SyntaxGrammar grammar({
{ "rule0", choice({
seq({ i_token(1), repeat(i_token(3)) }),
seq({ i_token(2), repeat(i_token(3)) }) }) },
}, {}, set<Symbol>());
auto match = expand_repeats(grammar);
AssertThat(match.rules, Equals(rule_list({
{ "rule0", choice({
seq({ i_token(1), choice({ i_aux_sym(0), blank() }) }),
seq({ i_token(2), choice({ i_aux_sym(0), blank() }) }) }) },
})));
AssertThat(match.aux_rules, Equals(rule_list({
{ "rule0_repeat0", seq({
i_token(3),
choice({ i_aux_sym(0), blank() }) }) },
})));
});
it("can replace multiple repeats in the same rule", [&]() {
SyntaxGrammar grammar({
{ "rule0", seq({

File diff suppressed because it is too large Load diff

View file

@ -28,18 +28,28 @@ using rules::Symbol;
class ExpandRepeats : public rules::IdentityRuleFn {
string rule_name;
vector<pair<const rule_ptr, Symbol>> existing_repeats;
rule_ptr expand_repeat(const Repeat *rule) {
for (auto pair : existing_repeats) {
if (pair.first->operator==(*rule))
return pair.second.copy();
}
rule_ptr apply_to(const Repeat *rule) {
rule_ptr inner_rule = apply(rule->content);
size_t index = aux_rules.size();
string helper_rule_name = rule_name + string("_repeat") + to_string(index);
rule_ptr repeat_symbol =
make_shared<Symbol>(offset + index, rules::SymbolOptionAuxiliary);
Symbol repeat_symbol(offset + index, rules::SymbolOptionAuxiliary);
existing_repeats.push_back({ rule->copy(), repeat_symbol });
aux_rules.push_back(
{ helper_rule_name,
Seq::build({ inner_rule, Choice::build({ repeat_symbol,
Seq::build({ inner_rule, Choice::build({ repeat_symbol.copy(),
make_shared<Blank>() }) }) });
return Choice::build({ repeat_symbol, make_shared<Blank>() });
return repeat_symbol.copy();
}
rule_ptr apply_to(const Repeat *rule) {
return Choice::build({ expand_repeat(rule), make_shared<Blank>() });
}
public: