Implement syntax highlighting
- Create a generic incremental syntax highlighting system. - Implement a ruby syntax highlighter for it.
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
|
||||
#include "decl.h"
|
||||
#include "pch.h"
|
||||
|
||||
namespace bed::internal::syntax::ruby {
|
||||
struct RubyParser {
|
||||
void **v_state;
|
||||
RubyState *state;
|
||||
std::string_view line;
|
||||
uint32_t i = 0;
|
||||
bool heredoc_start_line = false;
|
||||
|
||||
RubyParser(void **v_state, std::string_view line)
|
||||
: v_state(v_state), state((RubyState *)*v_state), line(line) {}
|
||||
|
||||
uint32_t len() const {
|
||||
return line.size();
|
||||
}
|
||||
|
||||
RubyState::RubyInternalState ¤t() {
|
||||
return state->stack()[state->top - 1];
|
||||
}
|
||||
|
||||
char peek(uint32_t offset = 0) {
|
||||
uint32_t pos = i + offset;
|
||||
return pos < line.size() ? line[pos] : '\0';
|
||||
}
|
||||
|
||||
std::string_view peek_str(uint32_t len) {
|
||||
return line.substr(i, len);
|
||||
}
|
||||
|
||||
void advance() {
|
||||
++i;
|
||||
}
|
||||
|
||||
void advance(uint32_t n) {
|
||||
i += n;
|
||||
}
|
||||
|
||||
void push_state() {
|
||||
state->top++;
|
||||
*v_state = (RubyState *)realloc(
|
||||
*v_state,
|
||||
sizeof(RubyState)
|
||||
+ sizeof(RubyState::RubyInternalState) * state->top
|
||||
+ state->docs
|
||||
);
|
||||
state = (RubyState *)*v_state;
|
||||
memmove(
|
||||
state->heredocs(),
|
||||
state->stack() + state->top - 1,
|
||||
state->docs
|
||||
);
|
||||
current() = {
|
||||
.brace_level = 1,
|
||||
.lit_brace_level = 0,
|
||||
.state = RubyState::RubyInternalState::NONE,
|
||||
.flags = 0,
|
||||
.delim_start = '\0',
|
||||
.delim_end = '\0'
|
||||
};
|
||||
}
|
||||
|
||||
void pop_state() {
|
||||
state->top--;
|
||||
memmove(
|
||||
state->heredocs(),
|
||||
state->stack() + state->top + 1,
|
||||
state->docs
|
||||
);
|
||||
}
|
||||
|
||||
void enqueue_doc(uint8_t header, std::string_view name) {
|
||||
uint32_t bytes = 1 + name.size();
|
||||
uint32_t old_docs = state->docs;
|
||||
state->docs += bytes;
|
||||
*v_state = (RubyState *)realloc(
|
||||
*v_state,
|
||||
sizeof(RubyState)
|
||||
+ sizeof(RubyState::RubyInternalState) * state->top
|
||||
+ state->docs
|
||||
);
|
||||
state = (RubyState *)*v_state;
|
||||
uint8_t *heredocs = state->heredocs();
|
||||
heredocs[old_docs] = header;
|
||||
memcpy(heredocs + old_docs + 1, name.data(), name.size());
|
||||
}
|
||||
|
||||
bool dequeue_doc(uint8_t heredoc_len) {
|
||||
uint32_t bytes = heredoc_len + 1;
|
||||
uint8_t *heredocs = state->heredocs();
|
||||
if (state->docs -= bytes)
|
||||
memmove(heredocs, heredocs + bytes, state->docs);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void ruby_parse(void **v_state, std::string_view line, bool first_line, std::vector<Token> *);
|
||||
} // namespace bed::internal::syntax::ruby
|
||||
Reference in New Issue
Block a user