#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 tokens; std::vector 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 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 events; std::vector>> lines_new; std::vector 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 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