#include <assert.h>
#include <string.h>
#include <tree_sitter/parser.h>
#include <wctype.h>
enum TokenType { RAW_STRING_DELIMITER, RAW_STRING_CONTENT };
#define RAW_STRING_DELIMITER_MAX 16
typedef struct {
uint8_t delimiter_length;
wchar_t delimiter[RAW_STRING_DELIMITER_MAX];
} Scanner;
static inline void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
static inline void reset(Scanner *scanner) {
scanner->delimiter_length = 0;
memset(scanner->delimiter, 0, sizeof(scanner->delimiter));
}
static bool scan_raw_string_delimiter(Scanner *scanner, TSLexer *lexer) {
if (scanner->delimiter_length > 0) {
for (int i = 0; i < scanner->delimiter_length; ++i) {
if (lexer->lookahead != scanner->delimiter[i])
return false;
advance(lexer);
}
reset(scanner);
return true;
}
for (;;) {
if (scanner->delimiter_length >= RAW_STRING_DELIMITER_MAX ||
lexer->eof(lexer) || lexer->lookahead == '\\' ||
iswspace(lexer->lookahead)) {
return false;
}
if (lexer->lookahead == '(') {
return scanner->delimiter_length > 0;
}
scanner->delimiter[scanner->delimiter_length++] = lexer->lookahead;
advance(lexer);
}
}
static bool scan_raw_string_content(Scanner *scanner, TSLexer *lexer) {
int delimiter_index = -1;
for (;;) {
if (lexer->eof(lexer)) {
lexer->mark_end(lexer);
return true;
}
if (delimiter_index >= 0) {
if (delimiter_index == scanner->delimiter_length) {
if (lexer->lookahead == '"') {
return true;
} else {
delimiter_index = -1;
}
} else {
if (lexer->lookahead == scanner->delimiter[delimiter_index]) {
delimiter_index++;
} else {
delimiter_index = -1;
}
}
}
if (delimiter_index == -1 && lexer->lookahead == ')') {
lexer->mark_end(lexer);
delimiter_index = 0;
}
advance(lexer);
}
}
static inline bool scan(Scanner *scanner, TSLexer *lexer,
const bool *valid_symbols) {
if (valid_symbols[RAW_STRING_DELIMITER]) {
lexer->result_symbol = RAW_STRING_DELIMITER;
return scan_raw_string_delimiter(scanner, lexer);
}
if (valid_symbols[RAW_STRING_CONTENT]) {
lexer->result_symbol = RAW_STRING_CONTENT;
return scan_raw_string_content(scanner, lexer);
}
return false;
}
void *tree_sitter_cuda_external_scanner_create() {
Scanner *scanner = (Scanner *)calloc(1, sizeof(Scanner));
memset(scanner, 0, sizeof(Scanner));
return scanner;
}
bool tree_sitter_cuda_external_scanner_scan(void *payload, TSLexer *lexer,
const bool *valid_symbols) {
Scanner *scanner = (Scanner *)payload;
return scan(scanner, lexer, valid_symbols);
}
unsigned tree_sitter_cuda_external_scanner_serialize(void *payload,
char *buffer) {
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(RAW_STRING_DELIMITER_MAX * sizeof(wchar_t) <
TREE_SITTER_SERIALIZATION_BUFFER_SIZE,
"Serialized delimiter is too long!");
#else
assert(RAW_STRING_DELIMITER_MAX * sizeof(wchar_t) <
TREE_SITTER_SERIALIZATION_BUFFER_SIZE &&
"Serialized delimiter is too long!");
#endif
Scanner *scanner = (Scanner *)payload;
size_t size = scanner->delimiter_length * sizeof(wchar_t);
memcpy(buffer, scanner->delimiter, size);
return (unsigned)size;
}
void tree_sitter_cuda_external_scanner_deserialize(void *payload,
const char *buffer,
unsigned length) {
assert(length % sizeof(wchar_t) == 0 &&
"Can't decode serialized delimiter!");
Scanner *scanner = (Scanner *)payload;
scanner->delimiter_length = length / sizeof(wchar_t);
memcpy(&scanner->delimiter[0], buffer, length);
}
void tree_sitter_cuda_external_scanner_destroy(void *payload) {
Scanner *scanner = (Scanner *)payload;
free(scanner);
}