Compare commits

..
Author SHA1 Message Date
syedm 8f67be87ee Add escape in strings control to ruby parser. 2026-09-13 14:07:19 +01:00
3 changed files with 83 additions and 63 deletions
+2 -1
View File
@@ -24,7 +24,8 @@ struct alignas(2) RubyState {
DEF_NAME = 0b10, DEF_NAME = 0b10,
MODULE_NAME = 0b11 MODULE_NAME = 0b11
}; };
static constexpr uint8_t NEWLINE = 1 << 5; static constexpr uint8_t NEWLINE = 1 << 4;
static constexpr uint8_t ALLOW_ESCAPE = 1 << 5;
static constexpr uint8_t ALLOW_INTERPOLATION = 1 << 6; static constexpr uint8_t ALLOW_INTERPOLATION = 1 << 6;
static constexpr uint8_t EXPECTING_EXPRESSION = 1 << 7; static constexpr uint8_t EXPECTING_EXPRESSION = 1 << 7;
uint8_t flags = 0; uint8_t flags = 0;
+23 -4
View File
@@ -35,8 +35,21 @@ inline uint8_t utf8_codepoint_width(unsigned char c) {
} }
bool handle_escapes(RubyParser &p, std::vector<io::Token> *tokens, uint32_t &start, bool string = true) { bool handle_escapes(RubyParser &p, std::vector<io::Token> *tokens, uint32_t &start, bool string = true) {
// TODO: properly handle escapes for %q ' etc. if (p.peek() != '\\')
if (p.peek() == '\\') { return false;
if (!(p.current().flags & RubyState::RubyInternalState::ALLOW_ESCAPE)) {
p.advance();
if (p.peek() != '\'' && p.peek() != '\\')
return false;
if (string)
tokens->push_back({start, p.i - 1, io::Token::String});
else
tokens->push_back({start, p.i - 1, io::Token::Regexp});
p.advance();
tokens->push_back({p.i - 2, p.i, io::Token::Escape});
start = p.i;
return true;
}
if (string) if (string)
tokens->push_back({start, p.i, io::Token::String}); tokens->push_back({start, p.i, io::Token::String});
else else
@@ -99,8 +112,6 @@ bool handle_escapes(RubyParser &p, std::vector<io::Token> *tokens, uint32_t &sta
tokens->push_back({start, p.i, io::Token::Escape}); tokens->push_back({start, p.i, io::Token::Escape});
start = p.i; start = p.i;
return true; return true;
}
return false;
}; };
bool handle_heredoc(RubyParser &p, std::vector<io::Token> *tokens, std::vector<ParseEvent> *events) { bool handle_heredoc(RubyParser &p, std::vector<io::Token> *tokens, std::vector<ParseEvent> *events) {
@@ -669,6 +680,7 @@ bool handle_syntax(RubyParser &p, std::vector<io::Token> *tokens, std::vector<Pa
p.current().delim_start = '\''; p.current().delim_start = '\'';
p.current().delim_end = '\''; p.current().delim_end = '\'';
p.current().flags &= ~RubyState::RubyInternalState::ALLOW_INTERPOLATION; p.current().flags &= ~RubyState::RubyInternalState::ALLOW_INTERPOLATION;
p.current().flags &= ~RubyState::RubyInternalState::ALLOW_ESCAPE;
p.advance(); p.advance();
return false; return false;
} }
@@ -679,6 +691,7 @@ bool handle_syntax(RubyParser &p, std::vector<io::Token> *tokens, std::vector<Pa
p.current().delim_start = '"'; p.current().delim_start = '"';
p.current().delim_end = '"'; p.current().delim_end = '"';
p.current().flags |= RubyState::RubyInternalState::ALLOW_INTERPOLATION; p.current().flags |= RubyState::RubyInternalState::ALLOW_INTERPOLATION;
p.current().flags |= RubyState::RubyInternalState::ALLOW_ESCAPE;
p.advance(); p.advance();
return false; return false;
} }
@@ -704,6 +717,7 @@ bool handle_syntax(RubyParser &p, std::vector<io::Token> *tokens, std::vector<Pa
char delim_start = '\0'; char delim_start = '\0';
char delim_end = '\0'; char delim_end = '\0';
bool allow_interp = true; bool allow_interp = true;
bool allow_escape = true;
int prefix_len = 1; int prefix_len = 1;
bool is_regexp = false; bool is_regexp = false;
switch (type) { switch (type) {
@@ -717,6 +731,7 @@ bool handle_syntax(RubyParser &p, std::vector<io::Token> *tokens, std::vector<Pa
case 'I': case 'I':
case 'W': case 'W':
allow_interp = true; allow_interp = true;
allow_escape = true;
prefix_len = 2; prefix_len = 2;
break; break;
case 'w': case 'w':
@@ -724,10 +739,12 @@ bool handle_syntax(RubyParser &p, std::vector<io::Token> *tokens, std::vector<Pa
case 'i': case 'i':
case 's': case 's':
allow_interp = false; allow_interp = false;
allow_escape = false;
prefix_len = 2; prefix_len = 2;
break; break;
default: default:
allow_interp = true; allow_interp = true;
allow_escape = true;
prefix_len = 1; prefix_len = 1;
break; break;
} }
@@ -769,6 +786,8 @@ bool handle_syntax(RubyParser &p, std::vector<io::Token> *tokens, std::vector<Pa
p.current().delim_end = delim_end; p.current().delim_end = delim_end;
if (allow_interp) if (allow_interp)
p.current().flags |= RubyState::RubyInternalState::ALLOW_INTERPOLATION; p.current().flags |= RubyState::RubyInternalState::ALLOW_INTERPOLATION;
if (allow_escape)
p.current().flags |= RubyState::RubyInternalState::ALLOW_ESCAPE;
p.current().lit_brace_level = 1; p.current().lit_brace_level = 1;
p.advance(prefix_len + 1); p.advance(prefix_len + 1);
return false; return false;