diff --git a/src/compiler/build_tables/build_parse_table.cc b/src/compiler/build_tables/build_parse_table.cc index 805ab9ef..ed08d727 100644 --- a/src/compiler/build_tables/build_parse_table.cc +++ b/src/compiler/build_tables/build_parse_table.cc @@ -146,8 +146,8 @@ class ParseTableBuilder { auto pair = parse_state_ids.find(item_set); if (pair == parse_state_ids.end()) { ParseStateId state_id = parse_table.add_state(); - parse_state_ids[item_set] = state_id; + parse_table.states[state_id].shift_actions_signature = item_set.unfinished_item_signature(); item_sets_to_process.push_back({ std::move(item_set), state_id }); return state_id; } else { @@ -176,9 +176,6 @@ class ParseTableBuilder { parse_table.set_nonterminal_action(state_id, symbol.index, next_state); } } - - ParseState &state = parse_table.states[state_id]; - state.compute_shift_actions_signature(); } void add_reduce_actions(const ParseItemSet &item_set, ParseStateId state_id) { @@ -285,26 +282,16 @@ class ParseTableBuilder { for (ParseStateId i = 0, n = parse_table.states.size(); i < n; i++) { ParseState &state = parse_table.states[i]; - bool did_update_state = false; if (state_replacements.count(i)) { - auto &old_group = state_indices_by_signature[state.shift_actions_signature]; - old_group.erase(i); + state_indices_by_signature[state.shift_actions_signature].erase(i); } else { - state.each_referenced_state([&state_replacements, &did_update_state](int64_t *state_index) { - auto new_replacement = state_replacements.find(*state_index); - if (new_replacement != state_replacements.end()) { - *state_index = new_replacement->second; - did_update_state = true; + state.each_referenced_state([&state_replacements](int64_t *state_index) { + auto replacement = state_replacements.find(*state_index); + if (replacement != state_replacements.end()) { + *state_index = replacement->second; } }); - - if (did_update_state) { - auto &old_group = state_indices_by_signature[state.shift_actions_signature]; - old_group.erase(i); - state.compute_shift_actions_signature(); - state_indices_by_signature[state.shift_actions_signature].insert(i); - } } } } diff --git a/src/compiler/build_tables/parse_item.cc b/src/compiler/build_tables/parse_item.cc index 5054e578..c71ddbdf 100644 --- a/src/compiler/build_tables/parse_item.cc +++ b/src/compiler/build_tables/parse_item.cc @@ -2,6 +2,7 @@ #include #include "compiler/syntax_grammar.h" #include "compiler/rules/built_in_symbols.h" +#include "compiler/util/hash_combine.h" namespace tree_sitter { namespace build_tables { @@ -12,6 +13,9 @@ using std::string; using std::to_string; using std::hash; using rules::Symbol; +using util::hash_combine; + +ParseItem::ParseItem() : variable_index(-1), production(nullptr), step_index(0) {} ParseItem::ParseItem(const Symbol &lhs, const Production &production, unsigned int step_index) @@ -108,6 +112,23 @@ size_t ParseItemSet::Hash::operator()(const ParseItemSet &item_set) const { return result; } +size_t ParseItemSet::unfinished_item_signature() const { + size_t result = 0; + ParseItem previous_item; + for (auto &pair : entries) { + const ParseItem &item = pair.first; + if (item.step_index < item.production->size()) { + if (item.variable_index != previous_item.variable_index && + item.step_index != previous_item.step_index) { + hash_combine(&result, item.variable_index); + hash_combine(&result, item.step_index); + previous_item = item; + } + } + } + return result; +} + ParseItemSet::TransitionMap ParseItemSet::transitions() const { ParseItemSet::TransitionMap result; for (const auto &pair : entries) { diff --git a/src/compiler/build_tables/parse_item.h b/src/compiler/build_tables/parse_item.h index 404b67c3..90260260 100644 --- a/src/compiler/build_tables/parse_item.h +++ b/src/compiler/build_tables/parse_item.h @@ -14,6 +14,7 @@ namespace build_tables { class ParseItem { public: + ParseItem(); ParseItem(const rules::Symbol &, const Production &, unsigned int); struct CompletionStatus { @@ -54,6 +55,7 @@ class ParseItemSet { TransitionMap transitions() const; bool operator==(const ParseItemSet &) const; void add(const ParseItemSet &); + size_t unfinished_item_signature() const; std::map entries; }; diff --git a/src/compiler/parse_table.cc b/src/compiler/parse_table.cc index ffb64f43..a70b7a91 100644 --- a/src/compiler/parse_table.cc +++ b/src/compiler/parse_table.cc @@ -1,7 +1,6 @@ #include "compiler/parse_table.h" #include #include "compiler/precedence_range.h" -#include "compiler/util/hash_combine.h" namespace tree_sitter { @@ -13,7 +12,6 @@ using std::set; using std::vector; using std::function; using rules::Symbol; -using util::hash_combine; ParseAction::ParseAction(ParseActionType type, ParseStateId state_index, Symbol symbol, size_t consumed_symbol_count, @@ -153,25 +151,6 @@ void ParseState::each_referenced_state(function fn) { fn(&entry.second); } -void ParseState::compute_shift_actions_signature() { - shift_actions_signature = 0; - for (const auto &pair : nonterminal_entries) { - rules::Symbol::Index lookahead = pair.first; - ParseStateId next_state = pair.second; - hash_combine(&shift_actions_signature, lookahead); - hash_combine(&shift_actions_signature, next_state); - } - - for (const auto &pair : terminal_entries) { - rules::Symbol::Index lookahead = pair.first; - const ParseTableEntry &entry = pair.second; - if (entry.actions.back().type == ParseActionTypeShift) { - hash_combine(&shift_actions_signature, lookahead); - hash_combine(&shift_actions_signature, entry); - } - } -} - bool ParseState::operator==(const ParseState &other) const { return terminal_entries == other.terminal_entries && nonterminal_entries == other.nonterminal_entries; diff --git a/src/compiler/parse_table.h b/src/compiler/parse_table.h index 473eec42..81142f75 100644 --- a/src/compiler/parse_table.h +++ b/src/compiler/parse_table.h @@ -5,7 +5,6 @@ #include #include #include -#include "compiler/util/hash_combine.h" #include "compiler/lex_table.h" #include "compiler/rules/symbol.h" #include "compiler/rules/metadata.h" @@ -76,7 +75,6 @@ class ParseState { bool merge(const ParseState &); void each_referenced_state(std::function); bool has_shift_action() const; - void compute_shift_actions_signature(); std::map terminal_entries; std::map nonterminal_entries; @@ -106,38 +104,4 @@ class ParseTable { } // namespace tree_sitter -namespace std { - -using tree_sitter::util::hash_combine; - -template <> -struct hash { - size_t operator()(const tree_sitter::ParseAction &action) const { - size_t result = 0; - hash_combine(&result, action.type); - hash_combine(&result, action.extra); - hash_combine(&result, action.fragile); - hash_combine(&result, action.symbol); - hash_combine(&result, action.state_index); - hash_combine(&result, action.consumed_symbol_count); - return result; - } -}; - -template <> -struct hash { - size_t operator()(const tree_sitter::ParseTableEntry &entry) const { - size_t result = 0; - hash_combine(&result, entry.actions.size()); - for (const tree_sitter::ParseAction &action : entry.actions) { - hash_combine(&result, action); - } - hash_combine(&result, entry.reusable); - hash_combine(&result, entry.depends_on_lookahead); - return result; - } -}; - -} - #endif // COMPILER_PARSE_TABLE_H_