121 lines
3.6 KiB
C++
121 lines
3.6 KiB
C++
#include "internal/syntax/miniparser.h"
|
|
|
|
namespace bed::internal::syntax {
|
|
MiniParser::MiniParser(Language &lang, vase::Shard *vase, void *initial_state)
|
|
: lang(lang),
|
|
start_state(initial_state ? lang.copy(initial_state) : lang.none_state()) {
|
|
vase::Iterator it(vase, 0, Direction::Forward);
|
|
void *state = lang.copy(start_state);
|
|
std::vector<io::Token> tokens;
|
|
std::vector<ParseEvent> events;
|
|
const uint64_t count = vase ? vase->lines + 1 : 1;
|
|
lines.reserve(count);
|
|
for (uint64_t i = 0; i < count; ++i) {
|
|
it.next();
|
|
tokens.clear();
|
|
events.clear();
|
|
lang.parse(&state, it.line, i == 0, &tokens, &events);
|
|
lines.emplace_back(lang.copy(state), std::move(tokens));
|
|
}
|
|
lang.destroy(state);
|
|
}
|
|
|
|
MiniParser::~MiniParser() {
|
|
if (start_state)
|
|
lang.destroy(start_state);
|
|
for (auto &[state, tokens] : lines)
|
|
if (state)
|
|
lang.destroy(state);
|
|
}
|
|
|
|
void MiniParser::dirty(vase::Shard *vase, uint64_t start, uint64_t count) {
|
|
vase::Iterator it(vase, start, Direction::Forward);
|
|
void *state = start ? lang.copy(lines[start - 1].first)
|
|
: lang.copy(start_state);
|
|
std::vector<ParseEvent> events;
|
|
uint64_t i = start;
|
|
for (; i < start + count; i++) {
|
|
it.next();
|
|
auto &line = lines[i];
|
|
line.second.clear();
|
|
events.clear();
|
|
lang.parse(&state, it.line, i == 0, &line.second, &events);
|
|
lang.destroy(line.first);
|
|
line.first = lang.copy(state);
|
|
}
|
|
while (it.next()) {
|
|
auto &line = lines[i++];
|
|
line.second.clear();
|
|
events.clear();
|
|
lang.parse(&state, it.line, false, &line.second, &events);
|
|
if (lang.equal(line.first, state))
|
|
break;
|
|
lang.destroy(line.first);
|
|
line.first = lang.copy(state);
|
|
}
|
|
lang.destroy(state);
|
|
}
|
|
|
|
void MiniParser::insert(vase::Shard *vase, uint64_t start, uint64_t count) {
|
|
vase::Iterator it(vase, start, Direction::Forward);
|
|
void *state = start ? lang.copy(lines[start - 1].first)
|
|
: lang.copy(start_state);
|
|
std::vector<ParseEvent> events;
|
|
std::vector<std::pair<void *, std::vector<io::Token>>> lines_new;
|
|
std::vector<io::Token> tokens;
|
|
lines_new.reserve(count);
|
|
for (uint64_t i = 0; i < count; ++i) {
|
|
it.next();
|
|
tokens.clear();
|
|
events.clear();
|
|
lang.parse(&state, it.line, start + i == 0, &tokens, &events);
|
|
lines_new.emplace_back(lang.copy(state), std::move(tokens));
|
|
}
|
|
uint64_t i = start;
|
|
while (it.next()) {
|
|
auto &line = lines[i++];
|
|
line.second.clear();
|
|
events.clear();
|
|
lang.parse(&state, it.line, i == 0, &line.second, &events);
|
|
if (lang.equal(line.first, state))
|
|
break;
|
|
lang.destroy(line.first);
|
|
line.first = lang.copy(state);
|
|
}
|
|
lines.insert(
|
|
lines.begin() + start,
|
|
std::make_move_iterator(lines_new.begin()),
|
|
std::make_move_iterator(lines_new.end())
|
|
);
|
|
lang.destroy(state);
|
|
}
|
|
|
|
void MiniParser::erase(vase::Shard *vase, uint64_t start, uint64_t count) {
|
|
if (count == 0)
|
|
return;
|
|
void *state = start ? lang.copy(lines[start - 1].first)
|
|
: lang.copy(start_state);
|
|
std::vector<ParseEvent> events;
|
|
for (uint64_t i = start; i < start + count; ++i)
|
|
if (lines[i].first)
|
|
lang.destroy(lines[i].first);
|
|
lines.erase(
|
|
lines.begin() + start,
|
|
lines.begin() + start + count
|
|
);
|
|
vase::Iterator it(vase, start, Direction::Forward);
|
|
uint64_t i = start;
|
|
while (i < lines.size() && it.next()) {
|
|
auto &line = lines[i];
|
|
line.second.clear();
|
|
events.clear();
|
|
lang.parse(&state, it.line, i++ == 0, &line.second, &events);
|
|
if (lang.equal(line.first, state))
|
|
break;
|
|
lang.destroy(line.first);
|
|
line.first = lang.copy(state);
|
|
}
|
|
lang.destroy(state);
|
|
}
|
|
} // namespace bed::internal::syntax
|