#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <tree_sitter/parser.h>
enum TokenType {
HERE_STRING_BODY,
};
typedef struct {
size_t len;
size_t cap;
char *data;
} String;
static void check_alloc(void *ptr) {
if (ptr == NULL) {
#ifndef __wasm32__
fprintf(stderr, "Scanner: Failed to allocate memory\n");
#endif
abort();
}
}
static String string_new(void) {
size_t init_len = 16;
size_t cap = init_len + 1;
void *tmp = calloc(1, sizeof(char) * cap);
check_alloc(tmp);
return (String){.cap = cap, .len = 0, .data = tmp};
}
static void string_resize(String *str, size_t new_cap) {
void *block = realloc(str->data, new_cap * sizeof(char));
check_alloc(block);
str->data = block;
str->cap = new_cap;
memset(str->data + str->len, 0, (new_cap - str->len) * sizeof(char));
}
static void string_push(String *str, int32_t elem) {
if (str->len + sizeof(elem) >= str->cap) {
string_resize(str, str->cap * 2 + 1);
}
memcpy(str->data + str->len, &elem, sizeof(elem));
str->len += sizeof(elem);
}
static void string_free(String *str) {
if (str->data != NULL) {
free(str->data);
str->data = NULL;
str->len = 0;
str->cap = 0;
}
}
static void string_clear(String *str) {
memset(str->data, 0, str->len * sizeof(char));
str->len = 0;
}
static void advance(TSLexer *lexer) {
lexer->advance(lexer, false);
}
static void skip(TSLexer *lexer) {
lexer->advance(lexer, true);
}
static bool isnewline(int32_t chr) {
return chr == '\n';
}
static void read_line(String *str, TSLexer *lexer) {
while (!isnewline(lexer->lookahead) && !lexer->eof(lexer)) {
string_push(str, lexer->lookahead);
advance(lexer);
}
}
static bool scan(TSLexer *lexer, const bool *valid_symbols) {
if (!valid_symbols[HERE_STRING_BODY]) {
return false;
}
String terminator = string_new();
read_line(&terminator, lexer);
if (lexer->eof(lexer)) {
string_free(&terminator);
return false;
}
skip(lexer);
String current_line = string_new();
while (true) {
read_line(¤t_line, lexer);
if (strcmp(terminator.data, current_line.data) == 0) {
lexer->result_symbol = HERE_STRING_BODY;
string_free(&terminator);
string_free(¤t_line);
return true;
}
if (lexer->eof(lexer)) {
string_free(&terminator);
string_free(¤t_line);
return false;
}
string_clear(¤t_line);
skip(lexer);
}
}
void *tree_sitter_racket_external_scanner_create() {
return NULL;
}
unsigned tree_sitter_racket_external_scanner_serialize(void *payload,
char *buffer) {
return 0;
}
void tree_sitter_racket_external_scanner_deserialize(void *payload,
const char *buffer,
unsigned length) {
}
bool tree_sitter_racket_external_scanner_scan(void *payload,
TSLexer *lexer,
const bool *valid_symbols) {
return scan(lexer, valid_symbols);
}
void tree_sitter_racket_external_scanner_destroy(void *payload) {
}