Use hash_combine everywhere

This commit is contained in:
Max Brunsfeld 2016-11-16 11:46:22 -08:00
parent 6cfd009503
commit 6935f1d26f
12 changed files with 132 additions and 73 deletions

View file

@ -44,7 +44,7 @@ class LexTableBuilder {
const LexicalGrammar lex_grammar;
vector<rule_ptr> separator_rules;
LexConflictManager conflict_manager;
unordered_map<const LexItemSet, LexStateId, LexItemSet::Hash> lex_state_ids;
unordered_map<LexItemSet, LexStateId> lex_state_ids;
public:
LexTableBuilder(ParseTable *parse_table, const LexicalGrammar &lex_grammar)

View file

@ -36,7 +36,7 @@ class ParseTableBuilder {
const LexicalGrammar lexical_grammar;
ParseConflictManager conflict_manager;
unordered_map<Symbol, ParseItemSet> recovery_states;
unordered_map<ParseItemSet, ParseStateId, ParseItemSet::Hash> parse_state_ids;
unordered_map<ParseItemSet, ParseStateId> parse_state_ids;
vector<pair<ParseItemSet, ParseStateId>> item_sets_to_process;
ParseTable parse_table;
set<string> conflicts;

View file

@ -8,11 +8,11 @@
#include "compiler/rules/symbol.h"
#include "compiler/rules/repeat.h"
#include "compiler/rules/visitor.h"
#include "compiler/util/hash_combine.h"
namespace tree_sitter {
namespace build_tables {
using std::hash;
using std::map;
using std::string;
using std::unordered_set;
@ -69,20 +69,9 @@ LexItem::CompletionStatus LexItem::completion_status() const {
return GetCompletionStatus().apply(rule);
}
size_t LexItem::Hash::operator()(const LexItem &item) const {
return hash<Symbol>()(item.lhs) ^ hash<rule_ptr>()(item.rule);
}
size_t LexItemSet::Hash::operator()(const LexItemSet &item_set) const {
size_t result = hash<size_t>()(item_set.entries.size());
for (const auto &item : item_set.entries)
result ^= LexItem::Hash()(item);
return result;
}
LexItemSet::LexItemSet() {}
LexItemSet::LexItemSet(const unordered_set<LexItem, LexItem::Hash> &entries)
LexItemSet::LexItemSet(const unordered_set<LexItem> &entries)
: entries(entries) {}
bool LexItemSet::operator==(const LexItemSet &other) const {
@ -103,3 +92,27 @@ bool LexItemSet::Transition::operator==(const LexItemSet::Transition &other) con
} // namespace build_tables
} // namespace tree_sitter
namespace std {
using tree_sitter::util::hash_combine;
using tree_sitter::util::symmetric_hash_combine;
using tree_sitter::build_tables::LexItem;
using tree_sitter::build_tables::LexItemSet;
size_t hash<LexItem>::operator()(const LexItem &item) const {
size_t result = 0;
hash_combine(&result, item.lhs.index);
hash_combine(&result, item.rule);
return result;
}
size_t hash<LexItemSet>::operator()(const LexItemSet &item_set) const {
size_t result = 0;
hash_combine(&result, item_set.entries.size());
for (const auto &item : item_set.entries)
symmetric_hash_combine(&result, item);
return result;
}
} // namespace std

View file

@ -22,10 +22,6 @@ class LexItem {
bool is_string;
};
struct Hash {
size_t operator()(const LexItem &) const;
};
bool operator==(const LexItem &other) const;
CompletionStatus completion_status() const;
@ -33,23 +29,34 @@ class LexItem {
rule_ptr rule;
};
} // namespace build_tables
} // namespace tree_sitter
namespace std {
template <>
struct hash<tree_sitter::build_tables::LexItem> {
size_t operator()(const tree_sitter::build_tables::LexItem &) const;
};
} // namespace std
namespace tree_sitter {
namespace build_tables {
class LexItemSet {
public:
LexItemSet();
explicit LexItemSet(const std::unordered_set<LexItem, LexItem::Hash> &);
explicit LexItemSet(const std::unordered_set<LexItem> &);
bool operator==(const LexItemSet &) const;
struct Hash {
size_t operator()(const LexItemSet &) const;
};
struct Transition;
typedef std::map<rules::CharacterSet, Transition> TransitionMap;
TransitionMap transitions() const;
std::unordered_set<LexItem, LexItem::Hash> entries;
std::unordered_set<LexItem> entries;
};
struct LexItemSet::Transition {
@ -63,4 +70,13 @@ struct LexItemSet::Transition {
} // namespace build_tables
} // namespace tree_sitter
namespace std {
template <>
struct hash<tree_sitter::build_tables::LexItemSet> {
size_t operator()(const tree_sitter::build_tables::LexItemSet &) const;
};
} // namespace std
#endif // COMPILER_BUILD_TABLES_LEX_ITEM_H_

View file

@ -11,7 +11,6 @@ using std::map;
using std::pair;
using std::string;
using std::to_string;
using std::hash;
using rules::Symbol;
using util::hash_combine;
@ -82,13 +81,6 @@ rules::Associativity ParseItem::associativity() const {
return production->at(step_index).associativity;
}
size_t ParseItem::Hash::operator()(const ParseItem &item) const {
size_t result = hash<int>()(item.variable_index);
result ^= hash<unsigned int>()(item.step_index);
result ^= hash<const void *>()(static_cast<const void *>(item.production));
return result;
}
ParseItemSet::ParseItemSet() {}
ParseItemSet::ParseItemSet(const map<ParseItem, LookaheadSet> &entries)
@ -98,20 +90,6 @@ bool ParseItemSet::operator==(const ParseItemSet &other) const {
return entries == other.entries;
}
size_t ParseItemSet::Hash::operator()(const ParseItemSet &item_set) const {
size_t result = hash<size_t>()(item_set.entries.size());
for (auto &pair : item_set.entries) {
const ParseItem &item = pair.first;
result ^= ParseItem::Hash()(item);
const LookaheadSet &lookahead_set = pair.second;
result ^= hash<size_t>()(lookahead_set.entries->size());
for (Symbol::Index index : *pair.second.entries)
result ^= hash<Symbol::Index>()(index);
}
return result;
}
size_t ParseItemSet::unfinished_item_signature() const {
size_t result = 0;
ParseItem previous_item;
@ -156,3 +134,37 @@ void ParseItemSet::add(const ParseItemSet &other) {
} // namespace build_tables
} // namespace tree_sitter
namespace std {
using tree_sitter::build_tables::ParseItem;
using tree_sitter::build_tables::ParseItemSet;
using tree_sitter::util::hash_combine;
template <>
struct hash<ParseItem> {
size_t operator()(const ParseItem &item) const {
size_t result = 0;
hash_combine(&result, item.variable_index);
hash_combine(&result, item.step_index);
hash_combine(&result, item.production);
return result;
}
};
size_t hash<ParseItemSet>::operator()(const ParseItemSet &item_set) const {
size_t result = 0;
hash_combine(&result, item_set.entries.size());
for (auto &pair : item_set.entries) {
const ParseItem &item = pair.first;
const auto &lookahead_set = pair.second;
hash_combine(&result, item);
hash_combine(&result, lookahead_set.entries->size());
for (auto index : *pair.second.entries)
hash_combine(&result, index);
}
return result;
}
} // namespace std

View file

@ -23,10 +23,6 @@ class ParseItem {
rules::Associativity associativity;
};
struct Hash {
size_t operator()(const ParseItem &) const;
};
bool operator==(const ParseItem &other) const;
bool operator<(const ParseItem &other) const;
rules::Symbol lhs() const;
@ -48,10 +44,6 @@ class ParseItemSet {
typedef std::map<rules::Symbol, std::pair<ParseItemSet, PrecedenceRange>>
TransitionMap;
struct Hash {
size_t operator()(const ParseItemSet &) const;
};
TransitionMap transitions() const;
bool operator==(const ParseItemSet &) const;
void add(const ParseItemSet &);
@ -63,4 +55,15 @@ class ParseItemSet {
} // namespace build_tables
} // namespace tree_sitter
namespace std {
using tree_sitter::build_tables::ParseItemSet;
template <>
struct hash<tree_sitter::build_tables::ParseItemSet> {
size_t operator()(const ParseItemSet &item_set) const;
};
} // namespace std
#endif // COMPILER_BUILD_TABLES_PARSE_ITEM_H_

View file

@ -4,7 +4,6 @@
namespace tree_sitter {
using std::hash;
using std::string;
using std::ostream;
using std::to_string;

View file

@ -3,14 +3,15 @@
#include <utility>
#include <vector>
#include "compiler/rules/visitor.h"
#include "compiler/util/hash_combine.h"
namespace tree_sitter {
namespace rules {
using std::string;
using std::hash;
using std::set;
using std::vector;
using util::hash_combine;
static void add_range(set<uint32_t> *characters, uint32_t min, uint32_t max) {
for (uint32_t c = min; c <= max; c++)
@ -83,14 +84,14 @@ bool CharacterSet::operator<(const CharacterSet &other) const {
}
size_t CharacterSet::hash_code() const {
size_t result = hash<bool>()(includes_all);
result ^= hash<size_t>()(included_chars.size());
for (auto &c : included_chars)
result ^= hash<uint32_t>()(c);
result <<= 1;
result ^= hash<size_t>()(excluded_chars.size());
for (auto &c : excluded_chars)
result ^= hash<uint32_t>()(c);
size_t result = 0;
hash_combine(&result, includes_all);
hash_combine(&result, included_chars.size());
for (uint32_t c : included_chars)
hash_combine(&result, c);
hash_combine(&result, excluded_chars.size());
for (uint32_t c : excluded_chars)
hash_combine(&result, c);
return result;
}

View file

@ -2,6 +2,7 @@
#include <string>
#include <set>
#include "compiler/rules/visitor.h"
#include "compiler/util/hash_combine.h"
namespace tree_sitter {
namespace rules {
@ -10,6 +11,7 @@ using std::string;
using std::make_shared;
using std::vector;
using std::set;
using util::symmetric_hash_combine;
Choice::Choice(const vector<rule_ptr> &elements) : elements(elements) {}
@ -50,9 +52,10 @@ bool Choice::operator==(const Rule &rule) const {
}
size_t Choice::hash_code() const {
size_t result = std::hash<size_t>()(elements.size());
size_t result = 0;
symmetric_hash_combine(&result, elements.size());
for (const auto &element : elements)
result ^= element->hash_code();
symmetric_hash_combine(&result, element);
return result;
}

View file

@ -3,14 +3,15 @@
#include <map>
#include "compiler/rules/visitor.h"
#include "compiler/rules/blank.h"
#include "compiler/util/hash_combine.h"
namespace tree_sitter {
namespace rules {
using std::hash;
using std::make_shared;
using std::map;
using std::pair;
using util::hash_combine;
Metadata::Metadata(rule_ptr rule, map<MetadataKey, int> values)
: rule(rule), value(values) {}
@ -25,10 +26,11 @@ bool Metadata::operator==(const Rule &rule) const {
}
size_t Metadata::hash_code() const {
size_t result = hash<size_t>()(value.size());
size_t result = 0;
hash_combine(&result, value.size());
for (auto &pair : value) {
result ^= hash<int>()(pair.first);
result ^= hash<int>()(pair.second);
hash_combine<int>(&result, pair.first);
hash_combine(&result, pair.second);
}
return result;
}

View file

@ -2,13 +2,14 @@
#include <string>
#include <map>
#include "compiler/rules/visitor.h"
#include "compiler/util/hash_combine.h"
namespace tree_sitter {
namespace rules {
using std::string;
using std::to_string;
using std::hash;
using util::hash_combine;
Symbol::Symbol(Symbol::Index index) : index(index), is_token(false) {}
@ -24,7 +25,10 @@ bool Symbol::operator==(const Rule &rule) const {
}
size_t Symbol::hash_code() const {
return hash<Symbol::Index>()(index) ^ hash<bool>()(is_token);
size_t result = 0;
hash_combine(&result, index);
hash_combine(&result, is_token);
return result;
}
rule_ptr Symbol::copy() const {

View file

@ -12,6 +12,12 @@ inline void hash_combine(std::size_t *seed, const T &new_value) {
*seed ^= hasher(new_value) + 0x9e3779b9 + (*seed << 6) + (*seed >> 2);
}
template <class T>
inline void symmetric_hash_combine(std::size_t *seed, const T &new_value) {
std::hash<T> hasher;
*seed ^= hasher(new_value);
}
} // namespace util
} // namespace tree_sitter