Skip to content

Commit 2bb2186

Browse files
feat(parser): add StringInterner class for symbol interning
1 parent d0fd1c1 commit 2bb2186

1 file changed

Lines changed: 113 additions & 0 deletions

File tree

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#if !defined(SYMBOL_HXX)
2+
#define SYMBOL_HXX
3+
4+
#include <cstdint>
5+
#include <deque>
6+
#include <string>
7+
#include <string_view>
8+
#include <unordered_map>
9+
#include <utility>
10+
#include "wheel_parser/config.hxx"
11+
#include "wheel_parser/allocator.hxx"
12+
13+
WHEEL_PARSER_AST_NAMESPACE
14+
using SymbolID = uint32_t;
15+
16+
inline constexpr SymbolID INVALID_SYMBOL_ID = static_cast<SymbolID>(-1);
17+
18+
struct SymbolHash {
19+
using is_transparent = void;
20+
21+
[[nodiscard]] size_t operator()(std::string_view text) const noexcept {
22+
return std::hash<std::string_view>{}(text);
23+
}
24+
25+
[[nodiscard]] size_t operator()(const std::string &text) const noexcept {
26+
return std::hash<std::string_view>{}(text);
27+
}
28+
};
29+
30+
struct SymbolEqual {
31+
using is_transparent = void;
32+
33+
[[nodiscard]] bool operator()(std::string_view lhs, std::string_view rhs) const noexcept {
34+
return lhs == rhs;
35+
}
36+
37+
[[nodiscard]] bool operator()(const std::string &lhs, const std::string &rhs) const noexcept {
38+
return lhs == rhs;
39+
}
40+
41+
[[nodiscard]] bool operator()(const std::string &lhs, std::string_view rhs) const noexcept {
42+
return lhs == rhs;
43+
}
44+
45+
[[nodiscard]] bool operator()(std::string_view lhs, const std::string &rhs) const noexcept {
46+
return lhs == rhs;
47+
}
48+
};
49+
50+
class StringInterner {
51+
private:
52+
std::deque<std::string> m_storage;
53+
std::unordered_map<std::string_view, SymbolID, SymbolHash, SymbolEqual> m_index;
54+
55+
private:
56+
void rebuild_index() {
57+
m_index.clear();
58+
for (SymbolID id = 0; id < static_cast<SymbolID>(m_storage.size()); ++id) {
59+
m_index.emplace(std::string_view(m_storage[id]), id);
60+
}
61+
}
62+
63+
public:
64+
StringInterner() = default;
65+
~StringInterner() = default;
66+
StringInterner(const StringInterner&) = delete;
67+
StringInterner& operator=(const StringInterner&) = delete;
68+
69+
StringInterner(StringInterner&& other) noexcept :
70+
m_storage(std::move(other.m_storage)),
71+
m_index() {
72+
73+
rebuild_index();
74+
}
75+
76+
StringInterner &operator=(StringInterner&& other) noexcept {
77+
if (this != &other) {
78+
m_storage = std::move(other.m_storage);
79+
rebuild_index();
80+
}
81+
82+
return *this;
83+
}
84+
85+
[[nodiscard]] SymbolID intern(std::string_view text) {
86+
auto found = m_index.find(text);
87+
if (found != m_index.end()) {
88+
return found->second;
89+
}
90+
91+
const SymbolID symbol_id = static_cast<SymbolID>(m_storage.size());
92+
m_storage.emplace_back(text);
93+
m_index.emplace(std::string_view(m_storage.back()), symbol_id);
94+
95+
return symbol_id;
96+
}
97+
98+
[[nodiscard]] std::string_view resolve(SymbolID symbol_id) const noexcept {
99+
if (symbol_id >= m_storage.size()) {
100+
return {};
101+
}
102+
103+
return m_storage[symbol_id];
104+
}
105+
106+
[[nodiscard]] size_t size() const noexcept {
107+
return m_storage.size();
108+
}
109+
};
110+
111+
WHEEL_PARSER_END_NAMESPACE
112+
113+
#endif // SYMBOL_HXX

0 commit comments

Comments
 (0)