Improve ruby parsing heuristics.
This commit is contained in:
@@ -70,13 +70,16 @@ struct Token {
|
|||||||
|
|
||||||
struct ParseEvent {
|
struct ParseEvent {
|
||||||
std::string_view name;
|
std::string_view name;
|
||||||
enum : uint8_t {
|
enum T : uint8_t {
|
||||||
Opening,
|
Opening,
|
||||||
Closing,
|
Closing,
|
||||||
SymbolDef,
|
SymbolDef,
|
||||||
Symbol
|
Symbol
|
||||||
} ev_type;
|
} ev_type;
|
||||||
uint8_t type; // type.
|
uint8_t type; // type.
|
||||||
|
|
||||||
|
ParseEvent(T t) : ev_type(t) {}
|
||||||
|
ParseEvent(std::string_view s, T e_t, uint8_t type) : name(s), ev_type(e_t), type(type) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Language {
|
struct Language {
|
||||||
@@ -87,6 +90,16 @@ struct Language {
|
|||||||
std::function<void(void *)> destroy;
|
std::function<void(void *)> destroy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Symbol {
|
||||||
|
uint32_t definition;
|
||||||
|
uint16_t reference_count;
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t len;
|
||||||
|
// first chars of count len, padded to 4 bytes.
|
||||||
|
// then a set of references. 32bit
|
||||||
|
// references later as modifying at end is faster than shifting the name.
|
||||||
|
};
|
||||||
|
|
||||||
struct ParseState {
|
struct ParseState {
|
||||||
static constexpr uint64_t BRANCH_BIT = 1ull << 63;
|
static constexpr uint64_t BRANCH_BIT = 1ull << 63;
|
||||||
static constexpr uint64_t LINES_MASK = ~BRANCH_BIT;
|
static constexpr uint64_t LINES_MASK = ~BRANCH_BIT;
|
||||||
@@ -106,6 +119,12 @@ struct ParseStateBranch : ParseState {
|
|||||||
|
|
||||||
struct ParseStateLeaf : ParseState {
|
struct ParseStateLeaf : ParseState {
|
||||||
void *state;
|
void *state;
|
||||||
|
uint64_t n;
|
||||||
|
static constexpr uint32_t IS_OPENING = 1ull << 31;
|
||||||
|
static constexpr uint32_t LINE_MASK = ~IS_OPENING;
|
||||||
|
// followed by n number of relative offsets
|
||||||
|
// stored as uint32_t with 1 bit for if it is start or end
|
||||||
|
// and rest as number.
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TreeCursor {
|
struct TreeCursor {
|
||||||
@@ -117,36 +136,4 @@ struct TreeCursor {
|
|||||||
void next();
|
void next();
|
||||||
void prev();
|
void prev();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ScopeNode {
|
|
||||||
static constexpr uint64_t SCOPE_BIT = 1ull << 63;
|
|
||||||
static constexpr uint64_t LINES_MASK = ~SCOPE_BIT;
|
|
||||||
uint64_t header;
|
|
||||||
bool is_scope() const {
|
|
||||||
return header & SCOPE_BIT;
|
|
||||||
}
|
|
||||||
uint64_t lines() const {
|
|
||||||
return header & LINES_MASK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Symbol {
|
|
||||||
uint32_t definition;
|
|
||||||
uint16_t reference_count;
|
|
||||||
uint8_t type;
|
|
||||||
uint8_t len;
|
|
||||||
// first chars of count len, padded to 4 bytes.
|
|
||||||
// then a set of references. 32bit
|
|
||||||
// references later as modifying at end is faster than shifting the name.
|
|
||||||
};
|
|
||||||
|
|
||||||
struct alignas(8) Scope : ScopeNode {
|
|
||||||
uint16_t children_count;
|
|
||||||
uint16_t symbol_count;
|
|
||||||
uint8_t type;
|
|
||||||
uint8_t len;
|
|
||||||
uint32_t : 32; // if more stuff is needed use the padding first.
|
|
||||||
// first chars of count len, padded to 8 bytes.
|
|
||||||
// followed by that many number of pointers.
|
|
||||||
};
|
|
||||||
} // namespace bed::internal::syntax
|
} // namespace bed::internal::syntax
|
||||||
|
|||||||
@@ -24,9 +24,6 @@ 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 scope_root;
|
|
||||||
Scope *get_scope(uint64_t);
|
|
||||||
|
|
||||||
struct Iterator {
|
struct Iterator {
|
||||||
Parser *p;
|
Parser *p;
|
||||||
std::optional<vase::Iterator> it;
|
std::optional<vase::Iterator> it;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ struct RubyParser {
|
|||||||
std::string_view line;
|
std::string_view line;
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
bool heredoc_start_line = false;
|
bool heredoc_start_line = false;
|
||||||
|
bool ending = true;
|
||||||
|
|
||||||
RubyParser(void **v_state, std::string_view line)
|
RubyParser(void **v_state, std::string_view line)
|
||||||
: v_state(v_state), state((RubyState *)*v_state), line(line) {}
|
: v_state(v_state), state((RubyState *)*v_state), line(line) {}
|
||||||
@@ -22,7 +23,7 @@ struct RubyParser {
|
|||||||
return state->stack()[state->top - 1];
|
return state->stack()[state->top - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
char peek(uint32_t offset = 0) {
|
char peek(int32_t offset = 0) {
|
||||||
uint32_t pos = i + offset;
|
uint32_t pos = i + offset;
|
||||||
return pos < line.size() ? line[pos] : '\0';
|
return pos < line.size() ? line[pos] : '\0';
|
||||||
}
|
}
|
||||||
@@ -57,7 +58,7 @@ struct RubyParser {
|
|||||||
.brace_level = 1,
|
.brace_level = 1,
|
||||||
.lit_brace_level = 0,
|
.lit_brace_level = 0,
|
||||||
.state = RubyState::RubyInternalState::NONE,
|
.state = RubyState::RubyInternalState::NONE,
|
||||||
.flags = 0,
|
.flags = RubyState::RubyInternalState::EXPECTING_EXPRESSION,
|
||||||
.delim_start = '\0',
|
.delim_start = '\0',
|
||||||
.delim_end = '\0'
|
.delim_end = '\0'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -212,10 +212,10 @@ const static std::vector<std::string> base_keywords = {
|
|||||||
"else",
|
"else",
|
||||||
"rescue",
|
"rescue",
|
||||||
"ensure",
|
"ensure",
|
||||||
"when",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const static std::vector<std::string> expecting_keywords = {
|
const static std::vector<std::string> expecting_keywords = {
|
||||||
|
"when",
|
||||||
"elsif",
|
"elsif",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -247,13 +247,13 @@ const static std::vector<std::string> operator_keywords = {
|
|||||||
"redo",
|
"redo",
|
||||||
"rescue",
|
"rescue",
|
||||||
"retry",
|
"retry",
|
||||||
"super",
|
|
||||||
"self",
|
"self",
|
||||||
"nil",
|
"nil",
|
||||||
"undef",
|
"undef",
|
||||||
};
|
};
|
||||||
|
|
||||||
const static std::vector<std::string> expecting_operators = {
|
const static std::vector<std::string> expecting_operators = {
|
||||||
|
"super",
|
||||||
"and",
|
"and",
|
||||||
"return",
|
"return",
|
||||||
"not",
|
"not",
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ bool handle_heredoc(RubyParser &p, std::vector<Token> *tokens) {
|
|||||||
if (!p.dequeue_doc(heredoc_len))
|
if (!p.dequeue_doc(heredoc_len))
|
||||||
p.current().state = RubyState::RubyInternalState::NONE;
|
p.current().state = RubyState::RubyInternalState::NONE;
|
||||||
tokens->push_back({p.i, p.len(), Token::Annotation});
|
tokens->push_back({p.i, p.len(), Token::Annotation});
|
||||||
|
p.current().flags |= RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,13 +131,13 @@ bool handle_heredoc(RubyParser &p, std::vector<Token> *tokens) {
|
|||||||
tokens->push_back({p.i, p.i + 2, Token::Interpolation});
|
tokens->push_back({p.i, p.i + 2, Token::Interpolation});
|
||||||
p.advance(2);
|
p.advance(2);
|
||||||
p.push_state();
|
p.push_state();
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
p.advance();
|
p.advance();
|
||||||
}
|
}
|
||||||
if (p.i >= p.len())
|
if (p.i >= p.len())
|
||||||
tokens->push_back({start, p.len(), Token::String});
|
tokens->push_back({start, p.len(), Token::String});
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +152,7 @@ void handle_string(RubyParser &p, std::vector<Token> *tokens) {
|
|||||||
tokens->push_back({p.i, p.i + 2, Token::Interpolation});
|
tokens->push_back({p.i, p.i + 2, Token::Interpolation});
|
||||||
p.advance(2);
|
p.advance(2);
|
||||||
p.push_state();
|
p.push_state();
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
if (p.peek() == p.current().delim_start
|
if (p.peek() == p.current().delim_start
|
||||||
&& p.current().delim_start != p.current().delim_end)
|
&& p.current().delim_start != p.current().delim_end)
|
||||||
@@ -191,7 +192,7 @@ void handle_regex(RubyParser &p, std::vector<Token> *tokens) {
|
|||||||
tokens->push_back({p.i, p.i + 2, Token::Interpolation});
|
tokens->push_back({p.i, p.i + 2, Token::Interpolation});
|
||||||
p.advance(2);
|
p.advance(2);
|
||||||
p.push_state();
|
p.push_state();
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
if (p.peek() == p.current().delim_start
|
if (p.peek() == p.current().delim_start
|
||||||
&& p.current().delim_start != p.current().delim_end)
|
&& p.current().delim_start != p.current().delim_end)
|
||||||
@@ -224,7 +225,7 @@ bool handle_line_markers(RubyParser &p, std::vector<Token> *tokens, std::vector<
|
|||||||
if (p.len() == 6 && p.peek_str(6) == "=begin") {
|
if (p.len() == 6 && p.peek_str(6) == "=begin") {
|
||||||
p.current().state = RubyState::RubyInternalState::COMMENT;
|
p.current().state = RubyState::RubyInternalState::COMMENT;
|
||||||
p.current().flags &= ~RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
p.current().flags &= ~RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
||||||
events->push_back({p.peek_str(6), ParseEvent::Opening, (uint8_t)ScopeTypes::Comment});
|
events->push_back(ParseEvent::Opening);
|
||||||
tokens->push_back({0, p.len(), Token::Comment});
|
tokens->push_back({0, p.len(), Token::Comment});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -251,21 +252,22 @@ bool handle_comment(RubyParser &p, std::vector<Token> *tokens, bool first_line)
|
|||||||
|
|
||||||
void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseEvent> *events) {
|
void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseEvent> *events) {
|
||||||
static const RubyTries tries = RubyTries();
|
static const RubyTries tries = RubyTries();
|
||||||
|
while (p.peek() == ' ' || p.peek() == '\t')
|
||||||
|
p.advance();
|
||||||
if (p.current().flags & RubyState::RubyInternalState::NAME_MASK) {
|
if (p.current().flags & RubyState::RubyInternalState::NAME_MASK) {
|
||||||
|
if (p.peek() == '\0')
|
||||||
|
return;
|
||||||
|
if (p.peek() == '\\' && p.peek(1) == '\0')
|
||||||
|
return;
|
||||||
switch (p.current().flags & RubyState::RubyInternalState::NAME_MASK) {
|
switch (p.current().flags & RubyState::RubyInternalState::NAME_MASK) {
|
||||||
case RubyState::RubyInternalState::CLASS_NAME: {
|
case RubyState::RubyInternalState::CLASS_NAME: {
|
||||||
while (p.peek() == ' ' || p.peek() == '\t')
|
|
||||||
p.advance();
|
|
||||||
if (p.peek() == '\0')
|
|
||||||
return;
|
|
||||||
if (p.peek() == '<' && p.peek(1) == '<') {
|
if (p.peek() == '<' && p.peek(1) == '<') {
|
||||||
p.advance(2);
|
p.advance(2);
|
||||||
events->push_back({"singleton", ParseEvent::Opening, (uint8_t)ScopeTypes::Class});
|
events->push_back(ParseEvent::Opening);
|
||||||
p.current().flags = (p.current().flags & ~RubyState::RubyInternalState::NAME_MASK);
|
p.current().flags = (p.current().flags & ~RubyState::RubyInternalState::NAME_MASK);
|
||||||
p.current().flags |= RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
p.current().flags |= RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t k = p.i;
|
|
||||||
uint32_t j = 0;
|
uint32_t j = 0;
|
||||||
if (identifier_start_char(p.peek(j))) {
|
if (identifier_start_char(p.peek(j))) {
|
||||||
j++;
|
j++;
|
||||||
@@ -280,16 +282,11 @@ void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseE
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
events->push_back({p.line.substr(k, j), ParseEvent::Opening, (uint8_t)ScopeTypes::Class});
|
events->push_back(ParseEvent::Opening);
|
||||||
p.current().flags = (p.current().flags & ~RubyState::RubyInternalState::NAME_MASK);
|
p.current().flags = (p.current().flags & ~RubyState::RubyInternalState::NAME_MASK);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case RubyState::RubyInternalState::DEF_NAME: {
|
case RubyState::RubyInternalState::DEF_NAME: {
|
||||||
while (p.peek() == ' ' || p.peek() == '\t')
|
|
||||||
p.advance();
|
|
||||||
if (p.peek() == '\0')
|
|
||||||
return;
|
|
||||||
uint32_t k = p.i;
|
|
||||||
uint32_t j = 0;
|
uint32_t j = 0;
|
||||||
if (identifier_start_char(p.peek(j))) {
|
if (identifier_start_char(p.peek(j))) {
|
||||||
j++;
|
j++;
|
||||||
@@ -311,16 +308,11 @@ void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseE
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
events->push_back({p.line.substr(k, j), ParseEvent::Opening, (uint8_t)ScopeTypes::Method});
|
events->push_back(ParseEvent::Opening);
|
||||||
p.current().flags = (p.current().flags & ~RubyState::RubyInternalState::NAME_MASK);
|
p.current().flags = (p.current().flags & ~RubyState::RubyInternalState::NAME_MASK);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case RubyState::RubyInternalState::MODULE_NAME: {
|
case RubyState::RubyInternalState::MODULE_NAME: {
|
||||||
while (p.peek() == ' ' || p.peek() == '\t')
|
|
||||||
p.advance();
|
|
||||||
if (p.peek() == '\0')
|
|
||||||
return;
|
|
||||||
uint32_t k = p.i;
|
|
||||||
uint32_t j = 0;
|
uint32_t j = 0;
|
||||||
if (identifier_start_char(p.peek(j))) {
|
if (identifier_start_char(p.peek(j))) {
|
||||||
j++;
|
j++;
|
||||||
@@ -335,7 +327,7 @@ void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseE
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
events->push_back({p.line.substr(k, j), ParseEvent::Opening, (uint8_t)ScopeTypes::Module});
|
events->push_back(ParseEvent::Opening);
|
||||||
p.current().flags = (p.current().flags & ~RubyState::RubyInternalState::NAME_MASK);
|
p.current().flags = (p.current().flags & ~RubyState::RubyInternalState::NAME_MASK);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -349,7 +341,7 @@ void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseE
|
|||||||
if (p.peek(j) == '~' || p.peek(j) == '-')
|
if (p.peek(j) == '~' || p.peek(j) == '-')
|
||||||
j++;
|
j++;
|
||||||
tokens->push_back({p.i, p.i + j, Token::Operator});
|
tokens->push_back({p.i, p.i + j, Token::Operator});
|
||||||
if (j >= p.len())
|
if (p.i + j >= p.len())
|
||||||
return;
|
return;
|
||||||
std::string delim;
|
std::string delim;
|
||||||
bool interpolation = true;
|
bool interpolation = true;
|
||||||
@@ -358,15 +350,17 @@ void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseE
|
|||||||
char q = p.peek(j++);
|
char q = p.peek(j++);
|
||||||
if (q == '\'')
|
if (q == '\'')
|
||||||
interpolation = false;
|
interpolation = false;
|
||||||
while (j < p.len() && p.peek(j) != q)
|
while (j + p.i < p.len() && p.peek(j) != q)
|
||||||
delim += p.peek(j++);
|
delim += p.peek(j++);
|
||||||
} else {
|
} else {
|
||||||
if (j < p.len() && identifier_start_char(p.peek(j))) {
|
if (j + p.i < p.len() && identifier_start_char(p.peek(j))) {
|
||||||
delim += p.peek(j++);
|
delim += p.peek(j++);
|
||||||
while (j < p.len() && identifier_char(p.peek(j)))
|
while (j + p.i < p.len() && identifier_char(p.peek(j)))
|
||||||
delim += p.peek(j++);
|
delim += p.peek(j++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (p.peek() == '\0')
|
||||||
|
return;
|
||||||
p.current().flags &= ~RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
p.current().flags &= ~RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
||||||
if (!delim.empty()) {
|
if (!delim.empty()) {
|
||||||
tokens->push_back({s, p.i + j, Token::Annotation});
|
tokens->push_back({s, p.i + j, Token::Annotation});
|
||||||
@@ -762,7 +756,9 @@ void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseE
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tokens->push_back({p.i, p.i + prefix_len + 1, (is_regexp ? Token::Regexp : Token::String)});
|
tokens->push_back({p.i, p.i + prefix_len + 1, (is_regexp ? Token::Regexp : Token::String)});
|
||||||
p.current().state = is_regexp ? RubyState::RubyInternalState::REGEXP : RubyState::RubyInternalState::STRING;
|
p.current().state = is_regexp
|
||||||
|
? RubyState::RubyInternalState::REGEXP
|
||||||
|
: RubyState::RubyInternalState::STRING;
|
||||||
p.current().delim_start = delim_start;
|
p.current().delim_start = delim_start;
|
||||||
p.current().delim_end = delim_end;
|
p.current().delim_end = delim_end;
|
||||||
if (allow_interp)
|
if (allow_interp)
|
||||||
@@ -775,12 +771,21 @@ void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseE
|
|||||||
p.current().flags |= RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
p.current().flags |= RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
||||||
p.advance();
|
p.advance();
|
||||||
return;
|
return;
|
||||||
|
case '\\':
|
||||||
|
if (p.peek(1) == '\0')
|
||||||
|
p.ending = false;
|
||||||
|
p.advance();
|
||||||
|
return;
|
||||||
|
case '\0':
|
||||||
|
if (p.ending)
|
||||||
|
p.current().flags |= RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
||||||
|
p.advance();
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
if ('0' <= p.peek() && p.peek() <= '9') {
|
if ('0' <= p.peek() && p.peek() <= '9') {
|
||||||
p.current().flags &= ~RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
p.current().flags &= ~RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
||||||
uint32_t start = p.i;
|
uint32_t start = p.i;
|
||||||
if (p.peek() == '0'
|
if (p.peek() == '0') {
|
||||||
&& (p.peek(1) == 'X' || p.peek(1) == 'x' || p.peek(1) == 'b' || p.peek(1) == 'B' || p.peek(1) == 'o' || p.peek(1) == 'O')) {
|
|
||||||
p.advance();
|
p.advance();
|
||||||
if (p.peek() == 'x' || p.peek() == 'X') {
|
if (p.peek() == 'x' || p.peek() == 'X') {
|
||||||
p.advance();
|
p.advance();
|
||||||
@@ -802,8 +807,11 @@ void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseE
|
|||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (p.peek() == 'o' || p.peek() == 'O') {
|
} else {
|
||||||
p.advance();
|
if (p.peek() == 'o' || p.peek() == 'O')
|
||||||
|
p.advance();
|
||||||
|
else if (p.peek() == '.')
|
||||||
|
goto decimal;
|
||||||
while (true) {
|
while (true) {
|
||||||
while (p.peek() >= '0' && p.peek() <= '7')
|
while (p.peek() >= '0' && p.peek() <= '7')
|
||||||
p.advance();
|
p.advance();
|
||||||
@@ -814,6 +822,7 @@ void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
decimal:
|
||||||
while (true) {
|
while (true) {
|
||||||
while (p.peek() >= '0' && p.peek() <= '9')
|
while (p.peek() >= '0' && p.peek() <= '9')
|
||||||
p.advance();
|
p.advance();
|
||||||
@@ -876,7 +885,7 @@ void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseE
|
|||||||
p.advance(j);
|
p.advance(j);
|
||||||
return;
|
return;
|
||||||
} else if (j == tries.types_trie.longest_match(p.peek_str(j))) {
|
} else if (j == tries.types_trie.longest_match(p.peek_str(j))) {
|
||||||
p.current().flags &= ~RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
p.current().flags |= RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
||||||
tokens->push_back({p.i, p.i + j, Token::Type});
|
tokens->push_back({p.i, p.i + j, Token::Type});
|
||||||
p.advance(j);
|
p.advance(j);
|
||||||
return;
|
return;
|
||||||
@@ -886,22 +895,21 @@ void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseE
|
|||||||
p.advance(j);
|
p.advance(j);
|
||||||
return;
|
return;
|
||||||
} else if (j == tries.expecting_end_keywords_trie.longest_match(p.peek_str(j))) {
|
} else if (j == tries.expecting_end_keywords_trie.longest_match(p.peek_str(j))) {
|
||||||
events->push_back({p.peek_str(j), ParseEvent::Opening, 0});
|
events->push_back(ParseEvent::Opening);
|
||||||
p.current().flags |= RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
p.current().flags |= RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
||||||
tokens->push_back({p.i, p.i + j, Token::Keyword});
|
tokens->push_back({p.i, p.i + j, Token::Keyword});
|
||||||
p.advance(j);
|
p.advance(j);
|
||||||
return;
|
return;
|
||||||
} else if (j == tries.conditional_keywords_trie.longest_match(p.peek_str(j))) {
|
} else if (j == tries.conditional_keywords_trie.longest_match(p.peek_str(j))) {
|
||||||
if (p.current().flags & RubyState::RubyInternalState::EXPECTING_EXPRESSION)
|
if (p.current().flags & RubyState::RubyInternalState::EXPECTING_EXPRESSION)
|
||||||
events->push_back({p.peek_str(j), ParseEvent::Opening, 0});
|
events->push_back(ParseEvent::Opening);
|
||||||
p.current().flags |= RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
p.current().flags |= RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
||||||
tokens->push_back({p.i, p.i + j, Token::Keyword});
|
tokens->push_back({p.i, p.i + j, Token::Keyword});
|
||||||
p.advance(j);
|
p.advance(j);
|
||||||
return;
|
return;
|
||||||
} else if (j == tries.end_keywords_trie.longest_match(p.peek_str(j))) {
|
} else if (j == tries.end_keywords_trie.longest_match(p.peek_str(j))) {
|
||||||
p.current().flags &= ~RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
p.current().flags |= RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
||||||
ScopeTypes kind = p.peek() == 'd' ? ScopeTypes::Block : ScopeTypes::None;
|
events->push_back(ParseEvent::Opening);
|
||||||
events->push_back({p.peek_str(j), ParseEvent::Opening, (uint8_t)kind});
|
|
||||||
tokens->push_back({p.i, p.i + j, Token::Keyword});
|
tokens->push_back({p.i, p.i + j, Token::Keyword});
|
||||||
p.advance(j);
|
p.advance(j);
|
||||||
return;
|
return;
|
||||||
@@ -938,7 +946,7 @@ void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseE
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (j == 3 && p.peek_str(3) == "end") {
|
if (j == 3 && p.peek_str(3) == "end") {
|
||||||
events->push_back({p.peek_str(3), ParseEvent::Closing, 0});
|
events->push_back(ParseEvent::Closing);
|
||||||
tokens->push_back({p.i, p.i + j, Token::Keyword});
|
tokens->push_back({p.i, p.i + j, Token::Keyword});
|
||||||
p.advance(3);
|
p.advance(3);
|
||||||
return;
|
return;
|
||||||
@@ -973,7 +981,7 @@ void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseE
|
|||||||
p.advance();
|
p.advance();
|
||||||
tokens->push_back({start, p.i, Token::Label});
|
tokens->push_back({start, p.i, Token::Label});
|
||||||
return;
|
return;
|
||||||
} else if (p.peek() == '!' || p.peek() == '?') {
|
} else if (p.peek(-1) == '!' || p.peek(-1) == '?') {
|
||||||
p.advance();
|
p.advance();
|
||||||
tokens->push_back({start, p.i, Token::Function});
|
tokens->push_back({start, p.i, Token::Function});
|
||||||
return;
|
return;
|
||||||
@@ -1019,6 +1027,7 @@ void handle_syntax(RubyParser &p, std::vector<Token> *tokens, std::vector<ParseE
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tokens->push_back({start, p.i, Token::Function});
|
tokens->push_back({start, p.i, Token::Function});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1042,14 +1051,14 @@ void ruby_parse(
|
|||||||
std::vector<ParseEvent> *events
|
std::vector<ParseEvent> *events
|
||||||
) {
|
) {
|
||||||
RubyParser p(v_state, line);
|
RubyParser p(v_state, line);
|
||||||
while (p.i < p.len()) {
|
while (p.i <= p.len()) {
|
||||||
if (p.current().state == RubyState::RubyInternalState::END)
|
if (p.current().state == RubyState::RubyInternalState::END)
|
||||||
return;
|
return;
|
||||||
if (p.current().state == RubyState::RubyInternalState::COMMENT) {
|
if (p.current().state == RubyState::RubyInternalState::COMMENT) {
|
||||||
tokens->push_back({p.i, p.len(), Token::Comment});
|
tokens->push_back({p.i, p.len(), Token::Comment});
|
||||||
if (p.i == 0 && p.peek_str(4) == "=end") {
|
if (p.i == 0 && p.peek_str(4) == "=end") {
|
||||||
p.current().state = RubyState::RubyInternalState::NONE;
|
p.current().state = RubyState::RubyInternalState::NONE;
|
||||||
events->push_back({{nullptr, 0}, ParseEvent::Closing, 0});
|
events->push_back(ParseEvent::Closing);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1062,10 +1071,14 @@ void ruby_parse(
|
|||||||
}
|
}
|
||||||
if (p.current().state == RubyState::RubyInternalState::STRING) {
|
if (p.current().state == RubyState::RubyInternalState::STRING) {
|
||||||
handle_string(p, tokens);
|
handle_string(p, tokens);
|
||||||
|
if (p.current().state == RubyState::RubyInternalState::STRING)
|
||||||
|
return;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (p.current().state == RubyState::RubyInternalState::REGEXP) {
|
if (p.current().state == RubyState::RubyInternalState::REGEXP) {
|
||||||
handle_regex(p, tokens);
|
handle_regex(p, tokens);
|
||||||
|
if (p.current().state == RubyState::RubyInternalState::REGEXP)
|
||||||
|
return;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!p.i && handle_line_markers(p, tokens, events))
|
if (!p.i && handle_line_markers(p, tokens, events))
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Language lang_ruby() {
|
|||||||
.brace_level = 1,
|
.brace_level = 1,
|
||||||
.lit_brace_level = 0,
|
.lit_brace_level = 0,
|
||||||
.state = RubyState::RubyInternalState::NONE,
|
.state = RubyState::RubyInternalState::NONE,
|
||||||
.flags = 0,
|
.flags = RubyState::RubyInternalState::EXPECTING_EXPRESSION,
|
||||||
.delim_start = '\0',
|
.delim_start = '\0',
|
||||||
.delim_end = '\0'
|
.delim_end = '\0'
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user