Fix error in merging character set transitions
This commit is contained in:
parent
2a222adb7e
commit
85b97c4f87
3 changed files with 45 additions and 13 deletions
|
|
@ -113,7 +113,6 @@ describe("rule transitions", []() {
|
|||
})));
|
||||
});
|
||||
|
||||
|
||||
it("handles choices between overlapping character sets", [&]() {
|
||||
AssertThat(
|
||||
char_transitions(choice({
|
||||
|
|
@ -130,6 +129,35 @@ describe("rule transitions", []() {
|
|||
})));
|
||||
});
|
||||
|
||||
it("handles choices between a subset and a superset of characters", [&]() {
|
||||
AssertThat(
|
||||
char_transitions(choice({
|
||||
seq({
|
||||
character({ {'a', 'c'} }),
|
||||
sym("x") }),
|
||||
seq({
|
||||
character({ { 'a', 'z' } }),
|
||||
sym("y") }) })),
|
||||
Equals(rule_map<CharacterSet>({
|
||||
{ CharacterSet({ {'a', 'c'} }), choice({ sym("x"), sym("y") }) },
|
||||
{ CharacterSet({ {'d', 'z'} }), sym("y") },
|
||||
})));
|
||||
|
||||
AssertThat(
|
||||
char_transitions(choice({
|
||||
seq({
|
||||
character({ { 'a', 'z' } }),
|
||||
sym("x") }),
|
||||
seq({
|
||||
character({ {'a', 'c'} }),
|
||||
sym("y") }) })),
|
||||
Equals(rule_map<CharacterSet>({
|
||||
{ CharacterSet({ {'a', 'c'} }), choice({ sym("x"), sym("y") }) },
|
||||
{ CharacterSet({ {'d', 'z'} }), sym("x") },
|
||||
})));
|
||||
|
||||
});
|
||||
|
||||
it("handles blanks", [&]() {
|
||||
AssertThat(char_transitions(blank()), Equals(rule_map<CharacterSet>({})));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -49,19 +49,25 @@ namespace tree_sitter {
|
|||
const std::map<rules::CharacterSet, T> &right,
|
||||
std::function<T(T, T)> merge_fn) {
|
||||
std::map<rules::CharacterSet, T> result(left);
|
||||
for (auto &pair : right) {
|
||||
auto rule = pair.first;
|
||||
for (auto &new_pair : right) {
|
||||
rules::CharacterSet new_rule = new_pair.first;
|
||||
T new_value = new_pair.second;
|
||||
|
||||
for (auto &existing_pair : left) {
|
||||
auto existing_rule = existing_pair.first;
|
||||
auto intersection = existing_rule.remove_set(rule);
|
||||
rules::CharacterSet existing_rule = existing_pair.first;
|
||||
T existing_value = existing_pair.second;
|
||||
|
||||
rules::CharacterSet intersection = existing_rule.remove_set(new_rule);
|
||||
if (!intersection.is_empty()) {
|
||||
result.erase(existing_pair.first);
|
||||
result.insert({ existing_rule, existing_pair.second });
|
||||
rule.remove_set(intersection);
|
||||
result.insert({ intersection, merge_fn(existing_pair.second, pair.second) });
|
||||
if (!existing_rule.is_empty())
|
||||
result.insert({ existing_rule, existing_value });
|
||||
result.insert({ intersection, merge_fn(existing_value, new_value) });
|
||||
new_rule.remove_set(intersection);
|
||||
}
|
||||
}
|
||||
result.insert({ rule, pair.second });
|
||||
if (!new_rule.is_empty())
|
||||
result.insert({ new_rule, new_pair.second });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,19 +26,17 @@ namespace tree_sitter {
|
|||
template<>
|
||||
map<CharacterSet, rule_ptr>
|
||||
merge_transitions(const map<CharacterSet, rule_ptr> &left, const map<CharacterSet, rule_ptr> &right) {
|
||||
auto transitions = merge_char_transitions<rule_ptr>(left, right, [](rule_ptr left, rule_ptr right) {
|
||||
return merge_char_transitions<rule_ptr>(left, right, [](rule_ptr left, rule_ptr right) {
|
||||
return make_shared<rules::Choice>(left, right);
|
||||
});
|
||||
return *static_cast<map<CharacterSet, rule_ptr> *>(&transitions);
|
||||
}
|
||||
|
||||
template<>
|
||||
map<Symbol, rule_ptr>
|
||||
merge_transitions(const map<Symbol, rule_ptr> &left, const map<Symbol, rule_ptr> &right) {
|
||||
auto transitions = merge_sym_transitions<rule_ptr>(left, right, [](rule_ptr left, rule_ptr right) {
|
||||
return merge_sym_transitions<rule_ptr>(left, right, [](rule_ptr left, rule_ptr right) {
|
||||
return make_shared<rules::Choice>(left, right);
|
||||
});
|
||||
return *static_cast<map<Symbol, rule_ptr> *>(&transitions);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue