#include "tree_sitter/parser.h"
#include <string.h>
enum TokenType {
SQL_BODY,
};
void *tree_sitter_plpgsql_external_scanner_create(void) { return NULL; }
void tree_sitter_plpgsql_external_scanner_destroy(void *payload) { (void)payload; }
unsigned tree_sitter_plpgsql_external_scanner_serialize(void *payload, char *buffer) { (void)payload; (void)buffer; return 0; }
void tree_sitter_plpgsql_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) { (void)payload; (void)buffer; (void)length; }
static void skip_whitespace(TSLexer *lexer) {
while (lexer->lookahead == ' ' || lexer->lookahead == '\t' ||
lexer->lookahead == '\n' || lexer->lookahead == '\r') {
lexer->advance(lexer, true);
}
}
static bool is_ascii_alpha(int c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
static bool is_ascii_digit(int c) {
return c >= '0' && c <= '9';
}
static bool is_ascii_alnum(int c) {
return is_ascii_alpha(c) || is_ascii_digit(c);
}
static char ascii_tolower(int c) {
return (c >= 'A' && c <= 'Z') ? (char)(c + ('a' - 'A')) : (char)c;
}
bool tree_sitter_plpgsql_external_scanner_scan(
void *payload, TSLexer *lexer, const bool *valid_symbols
) {
(void)payload;
if (!valid_symbols[SQL_BODY]) return false;
skip_whitespace(lexer);
if (lexer->lookahead == 0) return false;
if (lexer->lookahead == ';') return false;
int depth = 0;
bool has_content = false;
while (lexer->lookahead != 0) {
if (depth == 0 && lexer->lookahead == ';') break;
if (depth == 0 && lexer->lookahead == '<') {
lexer->mark_end(lexer);
lexer->advance(lexer, false);
if (lexer->lookahead == '<') {
if (has_content) {
lexer->result_symbol = SQL_BODY;
return true;
}
return false;
}
has_content = true;
continue;
}
if (depth == 0 && lexer->lookahead == ':') {
lexer->mark_end(lexer);
lexer->advance(lexer, false);
if (lexer->lookahead == '=') {
if (has_content) {
lexer->result_symbol = SQL_BODY;
return true;
}
return false;
}
if (lexer->lookahead == ':') {
lexer->advance(lexer, false);
has_content = true;
continue;
}
has_content = true;
continue;
}
if (depth == 0 && lexer->lookahead == '.') {
lexer->mark_end(lexer);
lexer->advance(lexer, false);
if (lexer->lookahead == '.') {
if (has_content) {
lexer->result_symbol = SQL_BODY;
return true;
}
return false;
}
has_content = true;
continue;
}
if (lexer->lookahead == '(' || lexer->lookahead == '[') {
depth++;
lexer->advance(lexer, false);
has_content = true;
continue;
}
if (lexer->lookahead == ')' || lexer->lookahead == ']') {
if (depth > 0) {
depth--;
lexer->advance(lexer, false);
has_content = true;
continue;
}
break;
}
if (lexer->lookahead == '\'') {
lexer->advance(lexer, false);
while (lexer->lookahead != 0) {
if (lexer->lookahead == '\'') {
lexer->advance(lexer, false);
if (lexer->lookahead != '\'') break;
lexer->advance(lexer, false);
} else {
lexer->advance(lexer, false);
}
}
has_content = true;
continue;
}
if (lexer->lookahead == '$') {
lexer->advance(lexer, false);
has_content = true;
continue;
}
if (lexer->lookahead == '-') {
lexer->advance(lexer, false);
if (lexer->lookahead == '-') {
while (lexer->lookahead != 0 && lexer->lookahead != '\n') {
lexer->advance(lexer, false);
}
has_content = true;
continue;
}
has_content = true;
continue;
}
if (lexer->lookahead == '/') {
lexer->advance(lexer, false);
if (lexer->lookahead == '*') {
lexer->advance(lexer, false);
int comment_depth = 1;
while (lexer->lookahead != 0 && comment_depth > 0) {
if (lexer->lookahead == '/') {
lexer->advance(lexer, false);
if (lexer->lookahead == '*') {
comment_depth++;
lexer->advance(lexer, false);
}
} else if (lexer->lookahead == '*') {
lexer->advance(lexer, false);
if (lexer->lookahead == '/') {
comment_depth--;
lexer->advance(lexer, false);
}
} else {
lexer->advance(lexer, false);
}
}
has_content = true;
continue;
}
has_content = true;
continue;
}
if (depth == 0 && is_ascii_alpha(lexer->lookahead)) {
lexer->mark_end(lexer);
char word[32];
int len = 0;
while (is_ascii_alnum(lexer->lookahead) || lexer->lookahead == '_') {
if (len < 30) word[len++] = ascii_tolower(lexer->lookahead);
lexer->advance(lexer, false);
}
word[len] = '\0';
if (
strcmp(word, "then") == 0 ||
strcmp(word, "loop") == 0 ||
strcmp(word, "into") == 0 ||
strcmp(word, "using") == 0 ||
strcmp(word, "when") == 0 ||
strcmp(word, "elsif") == 0 ||
strcmp(word, "elseif") == 0 ||
strcmp(word, "else") == 0 ||
strcmp(word, "end") == 0 ||
strcmp(word, "declare") == 0 ||
strcmp(word, "begin") == 0 ||
strcmp(word, "exception") == 0 ||
strcmp(word, "if") == 0 ||
strcmp(word, "case") == 0 ||
strcmp(word, "for") == 0 ||
strcmp(word, "foreach") == 0 ||
strcmp(word, "while") == 0 ||
strcmp(word, "return") == 0 ||
strcmp(word, "raise") == 0 ||
strcmp(word, "assert") == 0 ||
strcmp(word, "execute") == 0 ||
strcmp(word, "perform") == 0 ||
strcmp(word, "call") == 0 ||
strcmp(word, "open") == 0 ||
strcmp(word, "fetch") == 0 ||
strcmp(word, "move") == 0 ||
strcmp(word, "close") == 0 ||
strcmp(word, "null") == 0 ||
strcmp(word, "exit") == 0 ||
strcmp(word, "continue") == 0 ||
strcmp(word, "commit") == 0 ||
strcmp(word, "rollback") == 0 ||
strcmp(word, "get") == 0 ||
strcmp(word, "do") == 0 ||
strcmp(word, "next") == 0 ||
strcmp(word, "query") == 0 ||
strcmp(word, "reverse") == 0 ||
strcmp(word, "by") == 0 ||
strcmp(word, "alias") == 0 ||
strcmp(word, "strict") == 0 ||
strcmp(word, "cursor") == 0 ||
strcmp(word, "slice") == 0 ||
strcmp(word, "array") == 0 ||
strcmp(word, "all") == 0) {
if (has_content) {
lexer->result_symbol = SQL_BODY;
return true;
}
return false;
}
has_content = true;
continue;
}
if (depth == 0 && (lexer->lookahead == '_' || (lexer->lookahead >= 0x80))) {
while (is_ascii_alnum(lexer->lookahead) || lexer->lookahead == '_' ||
lexer->lookahead == '$' || lexer->lookahead >= 0x80) {
lexer->advance(lexer, false);
}
has_content = true;
continue;
}
if (depth > 0 && (is_ascii_alpha(lexer->lookahead) || lexer->lookahead == '_')) {
while (is_ascii_alnum(lexer->lookahead) || lexer->lookahead == '_' ||
lexer->lookahead == '$') {
lexer->advance(lexer, false);
}
has_content = true;
continue;
}
lexer->advance(lexer, false);
has_content = true;
}
if (has_content) {
lexer->mark_end(lexer);
lexer->result_symbol = SQL_BODY;
return true;
}
return false;
}