diff --git a/spec/compiler/build_tables/item_set_closure_spec.cc b/spec/compiler/build_tables/item_set_closure_spec.cc index 0f6afc9a..c49480e1 100644 --- a/spec/compiler/build_tables/item_set_closure_spec.cc +++ b/spec/compiler/build_tables/item_set_closure_spec.cc @@ -19,9 +19,9 @@ describe("computing closures of item sets", []() { }, {}); it("adds items at the beginnings of referenced rules", [&]() { - ParseItemSet item_set = item_set_closure(ParseItemSet({ - ParseItem(ISymbol(0), grammar.rule(ISymbol(0)), 0, ISymbol(10, SymbolOptionToken)) - }), grammar); + ParseItemSet item_set = item_set_closure( + ParseItem(ISymbol(0), grammar.rule(ISymbol(0)), 0, ISymbol(10, SymbolOptionToken)), + grammar); AssertThat(item_set, Equals(ParseItemSet({ ParseItem(ISymbol(1), grammar.rule(ISymbol(1)), 0, ISymbol(11, SymbolOptionToken)), diff --git a/src/compiler/build_tables/build_tables.cc b/src/compiler/build_tables/build_tables.cc index 93b7970d..5cc67367 100644 --- a/src/compiler/build_tables/build_tables.cc +++ b/src/compiler/build_tables/build_tables.cc @@ -185,7 +185,7 @@ namespace tree_sitter { void build() { auto start_symbol = make_shared(0); ParseItem item(rules::START(), start_symbol, {}, rules::END_OF_INPUT()); - ParseItemSet item_set = item_set_closure(ParseItemSet({ item }), grammar); + ParseItemSet item_set = item_set_closure(item, grammar); add_parse_state(item_set); add_error_lex_state(); } diff --git a/src/compiler/build_tables/item_set_closure.cc b/src/compiler/build_tables/item_set_closure.cc index f423a030..0c643e3e 100644 --- a/src/compiler/build_tables/item_set_closure.cc +++ b/src/compiler/build_tables/item_set_closure.cc @@ -32,11 +32,10 @@ namespace tree_sitter { } } - const ParseItemSet item_set_closure(const ParseItemSet &item_set, + const ParseItemSet item_set_closure(const ParseItem &item, const PreparedGrammar &grammar) { ParseItemSet result; - for (const ParseItem &item : item_set) - add_item(&result, item, grammar); + add_item(&result, item, grammar); return result; } } diff --git a/src/compiler/build_tables/item_set_closure.h b/src/compiler/build_tables/item_set_closure.h index 3c2abc26..dde19ff5 100644 --- a/src/compiler/build_tables/item_set_closure.h +++ b/src/compiler/build_tables/item_set_closure.h @@ -7,7 +7,7 @@ namespace tree_sitter { class PreparedGrammar; namespace build_tables { - const ParseItemSet item_set_closure(const ParseItemSet &item_set, + const ParseItemSet item_set_closure(const ParseItem &item, const PreparedGrammar &grammar); } } diff --git a/src/compiler/build_tables/item_set_transitions.cc b/src/compiler/build_tables/item_set_transitions.cc index 4263855d..f1e76cdb 100644 --- a/src/compiler/build_tables/item_set_transitions.cc +++ b/src/compiler/build_tables/item_set_transitions.cc @@ -12,27 +12,6 @@ namespace tree_sitter { using rules::ISymbol; namespace build_tables { - map - char_transitions(const LexItem &item) { - map result; - for (auto &transition : char_transitions(item.rule)) { - LexItem next_item(item.lhs, transition.second); - result.insert({ transition.first, LexItemSet({ next_item }) }); - } - return result; - } - - map - sym_transitions(const ParseItem &item, const PreparedGrammar &grammar) { - map result; - for (auto transition : sym_transitions(item.rule)) { - ISymbol rule = transition.first; - ParseItem new_item(item.lhs, transition.second, item.consumed_symbol_count + 1, item.lookahead_sym); - result.insert({ rule, item_set_closure(ParseItemSet({ new_item }), grammar) }); - } - return result; - } - template static unordered_set merge_sets(const unordered_set &left, const unordered_set &right) { unordered_set result = left; @@ -44,11 +23,16 @@ namespace tree_sitter { char_transitions(const LexItemSet &item_set, const PreparedGrammar &grammar) { map result; for (const LexItem &item : item_set) { - map item_transitions = char_transitions(item); - merge_char_transitions(result, - item_transitions, - [](LexItemSet left, LexItemSet right) { - return merge_sets(left, right); + map item_transitions; + for (auto &transition : char_transitions(item.rule)) { + LexItem next_item(item.lhs, transition.second); + item_transitions.insert({ + transition.first, + LexItemSet({ next_item }) + }); + } + merge_char_transitions(result, item_transitions, [](const LexItemSet &l, const LexItemSet &r) { + return merge_sets(l, r); }); } return result; @@ -58,11 +42,16 @@ namespace tree_sitter { sym_transitions(const ParseItemSet &item_set, const PreparedGrammar &grammar) { map result; for (const ParseItem &item : item_set) { - map item_transitions = sym_transitions(item, grammar); - merge_sym_transitions(result, - item_transitions, - [&](ParseItemSet left, ParseItemSet right) { - return merge_sets(left, right); + map item_transitions; + for (auto &transition : sym_transitions(item.rule)) { + ParseItem new_item(item.lhs, transition.second, item.consumed_symbol_count + 1, item.lookahead_sym); + item_transitions.insert({ + transition.first, + item_set_closure(new_item, grammar) + }); + } + merge_sym_transitions(result, item_transitions, [&](const ParseItemSet &l, const ParseItemSet &r) { + return merge_sets(l, r); }); } return result; diff --git a/src/compiler/build_tables/merge_transitions.h b/src/compiler/build_tables/merge_transitions.h index f5127643..7d3794b1 100644 --- a/src/compiler/build_tables/merge_transitions.h +++ b/src/compiler/build_tables/merge_transitions.h @@ -17,7 +17,7 @@ namespace tree_sitter { template void merge_sym_transitions(std::map &left, const std::map &right, - std::function merge_fn) { + std::function merge_fn) { for (auto &pair : right) { auto rule = pair.first; bool merged = false; @@ -27,6 +27,8 @@ namespace tree_sitter { existing_pair.second = merge_fn(existing_pair.second, pair.second); merged = true; break; + } else if (rule < existing_rule) { + break; } } if (!merged) @@ -43,7 +45,7 @@ namespace tree_sitter { template void merge_char_transitions(std::map &left, const std::map &right, - std::function merge_fn) { + std::function merge_fn) { for (auto &new_pair : right) { rules::CharacterSet new_char_set = new_pair.first; T new_value = new_pair.second;