Avoid unnecessary std::map construction when merging transition sets

This commit is contained in:
Max Brunsfeld 2014-06-26 13:42:42 -07:00
parent 9686c57e90
commit 9bad5dff3e
4 changed files with 55 additions and 74 deletions

View file

@ -21,7 +21,7 @@ namespace tree_sitter {
const set<Symbol> &lookahead_symbols = pair.second;
for (auto &transition : sym_transitions(item.rule)) {
ParseItem new_item(item.lhs, transition.second, item.consumed_symbol_count + 1);
merge_sym_transitions<ParseItemSet>(&result, {{ transition.first, item_set_closure(new_item, lookahead_symbols, grammar) }},
merge_sym_transitions<ParseItemSet>(&result, { transition.first, item_set_closure(new_item, lookahead_symbols, grammar) },
[](ParseItemSet *left, const ParseItemSet *right) {
for (auto &pair : *right)
left->operator[](pair.first).insert(pair.second.begin(), pair.second.end());
@ -37,7 +37,7 @@ namespace tree_sitter {
for (const LexItem &item : item_set) {
for (auto &transition : char_transitions(item.rule)) {
LexItem next_item(item.lhs, transition.second);
merge_char_transitions<LexItemSet>(&result, {{ transition.first, LexItemSet({ next_item }) }},
merge_char_transitions<LexItemSet>(&result, { transition.first, LexItemSet({ next_item }) },
[](LexItemSet *left, const LexItemSet *right) {
left->insert(right->begin(), right->end());
});

View file

@ -16,24 +16,18 @@ namespace tree_sitter {
*/
template<typename T>
void merge_sym_transitions(std::map<rules::Symbol, T> *left,
const std::map<rules::Symbol, T> &right,
const std::pair<rules::Symbol, T> &new_pair,
std::function<void(T *, const T *)> merge_fn) {
for (auto &pair : right) {
auto rule = pair.first;
bool merged = false;
for (auto &existing_pair : *left) {
auto existing_rule = existing_pair.first;
if (existing_rule == rule) {
merge_fn(&existing_pair.second, &pair.second);
merged = true;
break;
} else if (rule < existing_rule) {
break;
}
auto new_symbol = new_pair.first;
for (auto &existing_pair : *left) {
auto existing_symbol = existing_pair.first;
if (new_symbol < existing_symbol) break;
if (existing_symbol == new_symbol) {
merge_fn(&existing_pair.second, &new_pair.second);
return;
}
if (!merged)
left->insert({ pair.first, pair.second });
}
left->insert(new_pair);
}
/*
@ -44,37 +38,35 @@ namespace tree_sitter {
*/
template<typename T>
void merge_char_transitions(std::map<rules::CharacterSet, T> *left,
const std::map<rules::CharacterSet, T> &right,
const std::pair<rules::CharacterSet, T> &new_pair,
std::function<void(T *, const T *)> merge_fn) {
for (auto &new_pair : right) {
rules::CharacterSet new_char_set = new_pair.first;
T new_value = new_pair.second;
rules::CharacterSet new_char_set = new_pair.first;
T new_value = new_pair.second;
std::map<rules::CharacterSet, T> pairs_to_insert;
std::map<rules::CharacterSet, T> pairs_to_insert;
auto iter = left->begin();
while (iter != left->end()) {
rules::CharacterSet char_set = iter->first;
T value = iter->second;
auto iter = left->begin();
while (iter != left->end()) {
rules::CharacterSet char_set = iter->first;
T value = iter->second;
rules::CharacterSet intersection = char_set.remove_set(new_char_set);
if (!intersection.is_empty()) {
new_char_set.remove_set(intersection);
if (!char_set.is_empty())
pairs_to_insert.insert({ char_set, value });
merge_fn(&value, &new_value);
pairs_to_insert.insert({ intersection, value });
left->erase(iter++);
} else {
++iter;
}
rules::CharacterSet intersection = char_set.remove_set(new_char_set);
if (!intersection.is_empty()) {
new_char_set.remove_set(intersection);
if (!char_set.is_empty())
pairs_to_insert.insert({ char_set, value });
merge_fn(&value, &new_value);
pairs_to_insert.insert({ intersection, value });
left->erase(iter++);
} else {
++iter;
}
left->insert(pairs_to_insert.begin(), pairs_to_insert.end());
if (!new_char_set.is_empty())
left->insert({ new_char_set, new_pair.second });
}
left->insert(pairs_to_insert.begin(), pairs_to_insert.end());
if (!new_char_set.is_empty())
left->insert({ new_char_set, new_pair.second });
}
}
}

View file

@ -25,16 +25,18 @@ namespace tree_sitter {
template<>
void merge_transitions(map<CharacterSet, rule_ptr> *left, const map<CharacterSet, rule_ptr> &right) {
merge_char_transitions<rule_ptr>(left, right, [](rule_ptr *left, const rule_ptr *right) {
*left = rules::Choice::Build({ *left, *right });
});
for (auto &pair : right)
merge_char_transitions<rule_ptr>(left, pair, [](rule_ptr *left, const rule_ptr *right) {
*left = rules::Choice::Build({ *left, *right });
});
}
template<>
void merge_transitions(map<Symbol, rule_ptr> *left, const map<Symbol, rule_ptr> &right) {
merge_sym_transitions<rule_ptr>(left, right, [](rule_ptr *left, const rule_ptr *right) {
*left = rules::Choice::Build({ *left, *right });
});
for (auto &pair : right)
merge_sym_transitions<rule_ptr>(left, pair, [](rule_ptr *left, const rule_ptr *right) {
*left = rules::Choice::Build({ *left, *right });
});
}
template<typename T>