Make parser optional.

This commit is contained in:
2026-08-20 13:12:48 +01:00
parent 3a41af01f9
commit 1489b08d57
6 changed files with 73 additions and 69 deletions
+1
View File
@@ -15,6 +15,7 @@ struct BEd {
internal::commands::Command eof_op; internal::commands::Command eof_op;
std::array<std::optional<internal::commands::Suffix>, 26> suffixes; std::array<std::optional<internal::commands::Suffix>, 26> suffixes;
internal::theme::Theme theme; internal::theme::Theme theme;
std::unordered_map<std::string, internal::syntax::Language> languages;
bool help_mode = false; bool help_mode = false;
std::string last_help = ""; std::string last_help = "";
+2 -2
View File
@@ -11,8 +11,8 @@ namespace bed::internal::buffer {
struct Buffer { struct Buffer {
vase::Vase vase; vase::Vase vase;
marks::MarksEngine marks; marks::MarksEngine marks;
syntax::Language lang; std::string language;
syntax::Parser parser; std::optional<syntax::Parser> parser;
uint64_t line = 0; uint64_t line = 0;
bool modified; bool modified;
std::filesystem::path save_path = ""; std::filesystem::path save_path = "";
+2 -2
View File
@@ -164,7 +164,7 @@ struct TreeCursor {
} }
}; };
/*struct Symbol { struct Symbol {
uint64_t definition; uint64_t definition;
std::vector<uint64_t> references; std::vector<uint64_t> references;
}; };
@@ -178,5 +178,5 @@ struct Scope {
uint32_t type; uint32_t type;
trie::Trie<Symbol> symbols; trie::Trie<Symbol> symbols;
std::vector<std::variant<Space, Scope>> children; std::vector<std::variant<Space, Scope>> children;
};*/ };
} // namespace bed::internal::syntax } // namespace bed::internal::syntax
+12 -6
View File
@@ -6,12 +6,17 @@
namespace bed::internal::syntax { namespace bed::internal::syntax {
struct Parser { struct Parser {
ParseState *root; static constexpr const uint64_t MAX_CHUNK = 256;
Language &lang;
Parser(vase::Vase &, uint64_t, Language &); ParseState *root;
Language lang;
Parser(vase::Vase &, uint64_t, Language);
~Parser(); ~Parser();
void reset(vase::Vase &, uint64_t, Language &); Parser(const Parser &) = delete;
Parser &operator=(const Parser &) = delete;
void reset(vase::Vase &, uint64_t, Language);
void erase(vase::Vase &, uint64_t, uint64_t); void erase(vase::Vase &, uint64_t, uint64_t);
void insert(vase::Vase &, uint64_t, uint64_t); void insert(vase::Vase &, uint64_t, uint64_t);
void modify(vase::Vase &, uint64_t, uint64_t); void modify(vase::Vase &, uint64_t, uint64_t);
@@ -19,8 +24,9 @@ struct Parser {
std::pair<ParseState *, ParseState *> split_tree(ParseState *node, uint64_t line); std::pair<ParseState *, ParseState *> split_tree(ParseState *node, uint64_t line);
ParseState *join_tree(ParseState *a, ParseState *b); ParseState *join_tree(ParseState *a, ParseState *b);
// Scope root; Scope scope_root;
// Scope &get_scope(uint64_t); Scope &get_scope(uint64_t);
struct Iterator { struct Iterator {
Parser *p; Parser *p;
std::optional<vase::Iterator> it; std::optional<vase::Iterator> it;
+48 -49
View File
@@ -2,17 +2,14 @@
#include "bed.h" #include "bed.h"
namespace bed::internal::buffer { namespace bed::internal::buffer {
Buffer::Buffer() Buffer::Buffer() : vase("/tmp") {
: vase("/tmp"), lang(syntax::ruby::lang_ruby()), parser.emplace(vase, vase.lines(), syntax::ruby::lang_ruby());
parser(vase, vase.lines(), lang) {
line = vase.lines(); line = vase.lines();
modified = false; modified = false;
} }
Buffer::Buffer(std::string command) Buffer::Buffer(std::string command) : vase(command, "/tmp") {
: vase(command, "/tmp"), parser.emplace(vase, vase.lines(), syntax::ruby::lang_ruby());
lang(syntax::ruby::lang_ruby()),
parser(vase, vase.lines(), lang) {
line = vase.lines(); line = vase.lines();
if (!line) if (!line)
return; return;
@@ -21,10 +18,8 @@ Buffer::Buffer(std::string command)
modified = false; modified = false;
} }
Buffer::Buffer(std::filesystem::path path) Buffer::Buffer(std::filesystem::path path) : vase(path, "/tmp") {
: vase(path, "/tmp"), parser.emplace(vase, vase.lines(), syntax::ruby::lang_ruby());
lang(syntax::ruby::lang_ruby()),
parser(vase, vase.lines(), lang) {
line = vase.lines(); line = vase.lines();
if (!line) if (!line)
return; return;
@@ -37,7 +32,7 @@ Buffer::Buffer(std::filesystem::path path)
void Buffer::load(std::string command) { void Buffer::load(std::string command) {
vase::Vase new_vase = vase::Vase(command, "/tmp"); vase::Vase new_vase = vase::Vase(command, "/tmp");
vase = std::move(new_vase); vase = std::move(new_vase);
parser.reset(vase, vase.lines(), lang); parser.emplace(vase, vase.lines(), syntax::ruby::lang_ruby());
line = vase.lines(); line = vase.lines();
if (!line) { if (!line) {
prev_range.start = 0; prev_range.start = 0;
@@ -52,7 +47,7 @@ void Buffer::load(std::string command) {
void Buffer::load(std::filesystem::path path) { void Buffer::load(std::filesystem::path path) {
vase::Vase new_vase = vase::Vase(path, "/tmp"); vase::Vase new_vase = vase::Vase(path, "/tmp");
vase = std::move(new_vase); vase = std::move(new_vase);
parser.reset(vase, vase.lines(), lang); parser.emplace(vase, vase.lines(), syntax::ruby::lang_ruby());
line = vase.lines(); line = vase.lines();
if (!line) { if (!line) {
prev_range.start = 0; prev_range.start = 0;
@@ -110,17 +105,17 @@ inline void apply(std::ostream &out, const theme::Highlight &hl) {
const uint8_t g = (hl.fg >> 8) & 0xff; const uint8_t g = (hl.fg >> 8) & 0xff;
const uint8_t b = hl.fg & 0xff; const uint8_t b = hl.fg & 0xff;
out << "\x1b[38;2;" out << "\x1b[38;2;"
<< static_cast<unsigned>(r) << ';' << (unsigned)r << ';'
<< static_cast<unsigned>(g) << ';' << (unsigned)g << ';'
<< static_cast<unsigned>(b) << 'm'; << (unsigned)b << 'm';
if (hl.bg != 0) { if (hl.bg != 0) {
const uint8_t br = (hl.bg >> 16) & 0xff; const uint8_t br = (hl.bg >> 16) & 0xff;
const uint8_t bg = (hl.bg >> 8) & 0xff; const uint8_t bg = (hl.bg >> 8) & 0xff;
const uint8_t bb = hl.bg & 0xff; const uint8_t bb = hl.bg & 0xff;
out << "\x1b[48;2;" out << "\x1b[48;2;"
<< static_cast<unsigned>(br) << ';' << (unsigned)br << ';'
<< static_cast<unsigned>(bg) << ';' << (unsigned)bg << ';'
<< static_cast<unsigned>(bb) << 'm'; << (unsigned)bb << 'm';
} }
if (hl.flags & theme::Highlight::Bold) if (hl.flags & theme::Highlight::Bold)
out << "\x1b[1m"; out << "\x1b[1m";
@@ -137,38 +132,42 @@ inline void reset(std::ostream &out) {
} }
void Buffer::print(BEd &ctx, uint64_t start_line, uint64_t end_line) { void Buffer::print(BEd &ctx, uint64_t start_line, uint64_t end_line) {
std::optional<syntax::Parser::Iterator> it_o = parser.get_hl(vase, start_line - 1); if (parser) {
if (!it_o) std::optional<syntax::Parser::Iterator> it_o = parser->get_hl(vase, start_line - 1);
throw ed_error("shouldn't be possible if line existed, which is checked by print's callers."); auto &it = *it_o;
auto &it = *it_o; while (start_line <= end_line) {
while (start_line <= end_line) { it.next();
it.next(); const std::string &line = it.it->line;
const std::string &line = it.it->line; const auto &tokens = it.tokens;
const auto &tokens = it.tokens; uint32_t cursor = 0;
uint32_t cursor = 0; for (const auto &token : tokens) {
for (const auto &token : tokens) { const uint32_t start = token.start;
const uint32_t start = token.start; const uint32_t end = token.end;
const uint32_t end = token.end; if (start > line.size())
if (start > line.size()) break;
break; if (end > line.size())
if (end > line.size()) break;
break; if (cursor < start) {
if (cursor < start) { std::cout.write(
std::cout.write( line.data() + cursor,
line.data() + cursor, start - cursor
start - cursor );
); }
const auto highlight = ctx.theme.get(token);
apply(std::cout, highlight);
std::cout.write(line.data() + start, end - start);
reset(std::cout);
cursor = end;
} }
const auto highlight = ctx.theme.get(token); if (cursor < line.size())
apply(std::cout, highlight); std::cout.write(line.data() + cursor, line.size() - cursor);
std::cout.write(line.data() + start, end - start); std::cout << std::endl;
reset(std::cout); ++start_line;
cursor = end;
} }
if (cursor < line.size()) } else {
std::cout.write(line.data() + cursor, line.size() - cursor); vase::Iterator it = vase.iterate(start_line - 1, Direction::Forward);
std::cout << '\n'; while (it.next() && start_line++ <= end_line)
++start_line; std::cout << it.line << std::endl;
} }
prev_range.start = start_line; prev_range.start = start_line;
prev_range.end = end_line; prev_range.end = end_line;
+8 -10
View File
@@ -42,7 +42,7 @@ static ParseState *build_tree(std::vector<ParseStateLeaf *> &leaves, size_t begi
return make_branch(left, right); return make_branch(left, right);
} }
Parser::Parser(vase::Vase &vase, uint64_t lines, Language &lang) Parser::Parser(vase::Vase &vase, uint64_t lines, Language lang)
: root(nullptr), lang(lang) { : root(nullptr), lang(lang) {
reset(vase, lines, lang); reset(vase, lines, lang);
} }
@@ -51,17 +51,17 @@ Parser::~Parser() {
destroy_tree(root, lang); destroy_tree(root, lang);
} }
void Parser::reset(vase::Vase &vase, uint64_t lines, Language &lang_) { void Parser::reset(vase::Vase &vase, uint64_t lines, Language lang_) {
destroy_tree(root, lang); destroy_tree(root, lang);
root = nullptr; root = nullptr;
if (lines == 0) if (lines == 0)
return; return;
lang = lang_; lang = std::move(lang_);
vase::Iterator it = vase.iterate(0, Direction::Forward); vase::Iterator it = vase.iterate(0, Direction::Forward);
it.next(); it.next();
std::vector<ParseStateLeaf *> leaves; std::vector<ParseStateLeaf *> leaves;
std::vector<Token> tokens; std::vector<Token> tokens;
leaves.reserve((lines + 63) / 64); leaves.reserve((lines + MAX_CHUNK - 1) / MAX_CHUNK);
void *state = lang.none_state(); void *state = lang.none_state();
uint32_t consumed = 0; uint32_t consumed = 0;
while (consumed < lines) { while (consumed < lines) {
@@ -69,7 +69,7 @@ void Parser::reset(vase::Vase &vase, uint64_t lines, Language &lang_) {
leaf->header = 0; leaf->header = 0;
leaf->state = lang.copy(state); leaf->state = lang.copy(state);
uint32_t chunk_lines = 0; uint32_t chunk_lines = 0;
while (chunk_lines < 64 && consumed < lines) { while (chunk_lines < MAX_CHUNK && consumed < lines) {
tokens.clear(); tokens.clear();
lang.parse(&state, it.line, consumed == 0, &tokens); lang.parse(&state, it.line, consumed == 0, &tokens);
++chunk_lines; ++chunk_lines;
@@ -140,17 +140,15 @@ void Parser::insert(vase::Vase &vase, uint64_t start, uint64_t count) {
if (count == 0) if (count == 0)
return; return;
std::vector<ParseStateLeaf *> leaves; std::vector<ParseStateLeaf *> leaves;
leaves.reserve((count + 63) / 64); leaves.reserve((count + MAX_CHUNK - 1) / MAX_CHUNK);
uint64_t consumed = 0; uint64_t consumed = 0;
while (consumed < count) { while (consumed < count) {
auto *leaf = new ParseStateLeaf; auto *leaf = new ParseStateLeaf;
leaf->state = nullptr; leaf->state = nullptr;
uint64_t chunk = 0; uint64_t chunk = 0;
while (chunk < 64 && consumed < count) { while (chunk < MAX_CHUNK && consumed < count) {
++chunk; ++chunk;
++consumed; ++consumed;
if (consumed < count)
break;
} }
leaf->header = chunk; leaf->header = chunk;
leaves.push_back(leaf); leaves.push_back(leaf);
@@ -277,6 +275,6 @@ Parser::Iterator &Parser::Iterator::operator=(Iterator &&other) {
void Parser::Iterator::next() { void Parser::Iterator::next() {
it->next(); it->next();
tokens.clear(); tokens.clear();
p->lang.parse(&state, it->line, at == 0, &tokens); p->lang.parse(&state, it->line, at++ == 0, &tokens);
} }
} // namespace bed::internal::syntax } // namespace bed::internal::syntax