#include "tree_sitter/parser.h"
#include <stdbool.h>
enum TokenType {
PCT_LET,
PCT_MACRO,
PCT_MEND,
PCT_INCLUDE,
BARE_PCT,
};
void *tree_sitter_sas_external_scanner_create(void) { return NULL; }
void tree_sitter_sas_external_scanner_destroy(void *payload) { (void)payload; }
unsigned tree_sitter_sas_external_scanner_serialize(void *payload, char *buffer) {
(void)payload; (void)buffer; return 0;
}
void tree_sitter_sas_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
(void)payload; (void)buffer; (void)length;
}
static int32_t to_lower(int32_t c) {
return (c >= 'A' && c <= 'Z') ? c + 32 : c;
}
static bool is_ident_char(int32_t c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') || c == '_';
}
static bool advance_if(TSLexer *lexer, char expected) {
if (to_lower(lexer->lookahead) == (int32_t)expected) {
lexer->advance(lexer, false);
return true;
}
return false;
}
bool tree_sitter_sas_external_scanner_scan(
void *payload,
TSLexer *lexer,
const bool *valid_symbols
) {
(void)payload;
while (lexer->lookahead == ' ' || lexer->lookahead == '\t' ||
lexer->lookahead == '\n' || lexer->lookahead == '\r') {
lexer->advance(lexer, true);
}
if (lexer->lookahead != '%') return false;
lexer->advance(lexer, false);
int32_t c = to_lower(lexer->lookahead);
if (valid_symbols[BARE_PCT] && !is_ident_char(c) && c != '*') {
lexer->result_symbol = BARE_PCT;
return true;
}
if (c == 'l' && valid_symbols[PCT_LET]) {
lexer->advance(lexer, false);
if (advance_if(lexer, 'e') && advance_if(lexer, 't') &&
!is_ident_char(lexer->lookahead)) {
lexer->result_symbol = PCT_LET;
return true;
}
return false;
}
if (c == 'm') {
lexer->advance(lexer, false); int32_t c2 = to_lower(lexer->lookahead);
if (c2 == 'a' && valid_symbols[PCT_MACRO]) {
lexer->advance(lexer, false);
if (advance_if(lexer, 'c') && advance_if(lexer, 'r') &&
advance_if(lexer, 'o') && !is_ident_char(lexer->lookahead)) {
lexer->result_symbol = PCT_MACRO;
return true;
}
return false;
}
if (c2 == 'e' && valid_symbols[PCT_MEND]) {
lexer->advance(lexer, false);
if (advance_if(lexer, 'n') && advance_if(lexer, 'd') &&
!is_ident_char(lexer->lookahead)) {
lexer->result_symbol = PCT_MEND;
return true;
}
return false;
}
return false;
}
if (c == 'i' && valid_symbols[PCT_INCLUDE]) {
lexer->advance(lexer, false);
if (advance_if(lexer, 'n') && advance_if(lexer, 'c') &&
advance_if(lexer, 'l') && advance_if(lexer, 'u') &&
advance_if(lexer, 'd') && advance_if(lexer, 'e') &&
!is_ident_char(lexer->lookahead)) {
lexer->result_symbol = PCT_INCLUDE;
return true;
}
return false;
}
return false;
}