Files
wehub-resource-sync 41cb1c0170
OpenSSF Scorecard / scorecard (push) Failing after 0s
DCO / dco (push) Failing after 0s
CodeQL SAST / analyze (push) Failing after 1s
Deploy Pages / deploy (push) Failing after 1s
chore: import upstream snapshot with attribution
2026-07-13 12:28:05 +08:00

184 lines
5.9 KiB
C
Generated

#include "tree_sitter/parser.h"
/// Block comments and immediate parentheses are easy to parse, but strings
/// require extra-attention.
///
/// The main problems that arise when parsing strings are:
/// 1. Triple quoted strings allow single quotes inside. e.g. """ "foo" """.
/// 2. Strings can have arbitrary interpolations, including other strings.
/// e.g. "echo $("foo")"
/// 3. Non-standard string literals don't allow interpolations or escape
/// sequences, but you can always write \" and \`.
/// All of the above also applies to command literals.
enum TokenType {
BLOCK_COMMENT_REST,
IMMEDIATE_PAREN,
IMMEDIATE_BRACKET,
IMMEDIATE_BRACE,
IMMEDIATE_STRING_START,
IMMEDIATE_COMMAND_START,
CONTENT_CMD_1,
CONTENT_CMD_1_RAW,
CONTENT_CMD_3,
CONTENT_CMD_3_RAW,
CONTENT_STR_1,
CONTENT_STR_1_RAW,
CONTENT_STR_3,
CONTENT_STR_3_RAW,
END_CMD,
END_STR,
};
void *tree_sitter_julia_external_scanner_create() {
return NULL;
}
void tree_sitter_julia_external_scanner_destroy(void *payload) {}
unsigned tree_sitter_julia_external_scanner_serialize(void *payload, char *buffer) { return 0; }
void tree_sitter_julia_external_scanner_deserialize(void *payload, const char *buffer, unsigned size) {}
// Scanner functions
static void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
static void mark_end(TSLexer *lexer) { lexer->mark_end(lexer); }
static bool scan_content(TSLexer *lexer, TSSymbol content_symbol, char end_char, unsigned n_delim, bool interp) {
TSSymbol end_symbol = (end_char == '"') ? END_STR : END_CMD;
bool has_content = false;
int32_t next;
while ((next = lexer->lookahead)) {
mark_end(lexer);
if (interp && (next == '$' || next == '\\')) {
lexer->result_symbol = content_symbol;
return has_content;
} else if (next == '\\') {
// Parse backslash in raw strings (check escaped delimiters and '\\')
advance(lexer);
next = lexer->lookahead;
if (next == end_char || next == '\\') {
lexer->result_symbol = content_symbol;
return has_content;
}
} else {
bool is_end_delimiter = true;
for (unsigned i = 1; i <= n_delim; i++) {
if (lexer->lookahead == end_char) {
advance(lexer);
} else {
is_end_delimiter = false;
break;
}
}
if (is_end_delimiter) {
if (has_content) {
lexer->result_symbol = content_symbol;
return true;
} else {
mark_end(lexer);
lexer->result_symbol = end_symbol;
return true;
}
}
}
advance(lexer);
has_content = true;
}
return false;
}
static bool scan_block_comment(TSLexer *lexer) {
// NOTE: The first `#=` is scanned by tree-sitter
bool after_eq = false;
unsigned nesting_depth = 1;
for (;;) {
switch (lexer->lookahead) {
case '=':
advance(lexer);
after_eq = true;
break;
case '#':
advance(lexer);
if (after_eq) {
after_eq = false;
nesting_depth--;
if (nesting_depth == 0) {
lexer->result_symbol = BLOCK_COMMENT_REST;
return true;
}
} else {
after_eq = false;
if (lexer->lookahead == '=') {
advance(lexer);
nesting_depth++;
}
}
break;
case '\0':
return false;
default:
advance(lexer);
after_eq = false;
break;
}
}
}
bool tree_sitter_julia_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) {
if (valid_symbols[IMMEDIATE_PAREN] && lexer->lookahead == '(') {
lexer->result_symbol = IMMEDIATE_PAREN;
return true;
} else if (valid_symbols[IMMEDIATE_BRACKET] && lexer->lookahead == '[') {
lexer->result_symbol = IMMEDIATE_BRACKET;
return true;
} else if (valid_symbols[IMMEDIATE_BRACE] && lexer->lookahead == '{') {
lexer->result_symbol = IMMEDIATE_BRACE;
return true;
} else if (valid_symbols[IMMEDIATE_STRING_START] && lexer->lookahead == '"') {
lexer->result_symbol = IMMEDIATE_STRING_START;
return true;
} else if (valid_symbols[IMMEDIATE_COMMAND_START] && lexer->lookahead == '`') {
lexer->result_symbol = IMMEDIATE_COMMAND_START;
return true;
}
if (valid_symbols[BLOCK_COMMENT_REST] && scan_block_comment(lexer)) {
return true;
}
if (valid_symbols[CONTENT_STR_1] && scan_content(lexer, CONTENT_STR_1, '"', 1, true)) {
return true;
}
if (valid_symbols[CONTENT_STR_3] && scan_content(lexer, CONTENT_STR_3, '"', 3, true)) {
return true;
}
if (valid_symbols[CONTENT_CMD_1] && scan_content(lexer, CONTENT_CMD_1, '`', 1, true)) {
return true;
}
if (valid_symbols[CONTENT_CMD_3] && scan_content(lexer, CONTENT_CMD_3, '`', 3, true)) {
return true;
}
if (valid_symbols[CONTENT_STR_1_RAW] && scan_content(lexer, CONTENT_STR_1_RAW, '"', 1, false)) {
return true;
}
if (valid_symbols[CONTENT_STR_3_RAW] && scan_content(lexer, CONTENT_STR_3_RAW, '"', 3, false)) {
return true;
}
if (valid_symbols[CONTENT_CMD_1_RAW] && scan_content(lexer, CONTENT_CMD_1_RAW, '`', 1, false)) {
return true;
}
if (valid_symbols[CONTENT_CMD_3_RAW] && scan_content(lexer, CONTENT_CMD_3_RAW, '`', 3, false)) {
return true;
}
return false;
}