tree-sitter/src/compiler/build_tables/lookahead_set.cc
2017-07-12 22:08:36 -07:00

109 lines
2.5 KiB
C++

#include "compiler/build_tables/lookahead_set.h"
#include <set>
#include <memory>
#include "compiler/rule.h"
namespace tree_sitter {
namespace build_tables {
using std::vector;
using rules::Symbol;
LookaheadSet::LookaheadSet() {}
LookaheadSet::LookaheadSet(const vector<Symbol> &symbols) {
for (auto symbol : symbols) insert(symbol);
}
bool LookaheadSet::empty() const {
return terminal_bits.empty() && external_bits.empty() && !eof;
}
bool LookaheadSet::operator==(const LookaheadSet &other) const {
return
eof == other.eof &&
external_bits == other.external_bits &&
terminal_bits == other.terminal_bits;
}
bool LookaheadSet::contains(const Symbol &symbol) const {
if (symbol == rules::END_OF_INPUT()) return eof;
auto &bits = symbol.is_external() ? external_bits : terminal_bits;
return bits.size() > static_cast<size_t>(symbol.index) && bits[symbol.index];
}
size_t LookaheadSet::size() const {
size_t result = 0;
for (bool bit : external_bits) if (bit) result++;
for (bool bit : terminal_bits) if (bit) result++;
if (eof) result++;
return result;
}
bool LookaheadSet::insert_all(const LookaheadSet &other) {
bool result = false;
if (other.eof) {
if (!eof) {
eof = true;
result = true;
}
}
if (other.external_bits.size() > external_bits.size()) {
external_bits.resize(other.external_bits.size());
}
auto iter = external_bits.begin();
auto other_iter = other.external_bits.begin();
auto other_end = other.external_bits.end();
while (other_iter != other_end) {
if (*other_iter && !*iter) {
result = true;
*iter = true;
}
++iter;
++other_iter;
}
if (other.terminal_bits.size() > terminal_bits.size()) {
terminal_bits.resize(other.terminal_bits.size());
}
iter = terminal_bits.begin();
other_iter = other.terminal_bits.begin();
other_end = other.terminal_bits.end();
while (other_iter != other_end) {
if (*other_iter && !*iter) {
result = true;
*iter = true;
}
++iter;
++other_iter;
}
return result;
}
bool LookaheadSet::insert(const Symbol &symbol) {
if (symbol == rules::END_OF_INPUT()) {
if (!eof) {
eof = true;
return true;
}
return false;
}
auto &bits = symbol.is_external() ? external_bits : terminal_bits;
if (bits.size() <= static_cast<size_t>(symbol.index)) {
bits.resize(symbol.index + 1);
}
if (!bits[symbol.index]) {
bits[symbol.index] = true;
return true;
}
return false;
}
} // namespace build_tables
} // namespace tree_sitter