Compute parse state group signature based on the item set

This commit is contained in:
Max Brunsfeld 2016-11-16 10:21:30 -08:00
parent 42d37656ea
commit 6cfd009503
5 changed files with 29 additions and 76 deletions

View file

@ -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);
}
}
}
}

View file

@ -2,6 +2,7 @@
#include <string>
#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) {

View file

@ -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<ParseItem, LookaheadSet> entries;
};

View file

@ -1,7 +1,6 @@
#include "compiler/parse_table.h"
#include <string>
#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<void(ParseStateId *)> 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;

View file

@ -5,7 +5,6 @@
#include <set>
#include <utility>
#include <vector>
#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<void(ParseStateId *)>);
bool has_shift_action() const;
void compute_shift_actions_signature();
std::map<rules::Symbol::Index, ParseTableEntry> terminal_entries;
std::map<rules::Symbol::Index, ParseStateId> nonterminal_entries;
@ -106,38 +104,4 @@ class ParseTable {
} // namespace tree_sitter
namespace std {
using tree_sitter::util::hash_combine;
template <>
struct hash<tree_sitter::ParseAction> {
size_t operator()(const tree_sitter::ParseAction &action) const {
size_t result = 0;
hash_combine<int>(&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<tree_sitter::ParseTableEntry> {
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_