192 lines
4.6 KiB
C
Generated
192 lines
4.6 KiB
C
Generated
#include <string.h>
|
|
#include "tree_sitter/alloc.h"
|
|
#include "tree_sitter/parser.h"
|
|
#include <wctype.h>
|
|
|
|
enum TokenType {
|
|
BRACKET_ARGUMENT_OPEN,
|
|
BRACKET_ARGUMENT_CONTENT,
|
|
BRACKET_ARGUMENT_CLOSE,
|
|
BRACKET_COMMENT_OPEN,
|
|
BRACKET_COMMENT_CONTENT,
|
|
BRACKET_COMMENT_CLOSE,
|
|
LINE_COMMENT,
|
|
};
|
|
|
|
struct TreeSitterCMakeState {
|
|
unsigned level;
|
|
enum TokenType token;
|
|
};
|
|
|
|
#define STATE_SIZE sizeof(struct TreeSitterCMakeState)
|
|
|
|
static void skip(TSLexer *lexer) { lexer->advance(lexer, true); }
|
|
static void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
|
|
static void mark_end(TSLexer *lexer) { lexer->mark_end(lexer); }
|
|
static void advance_mark(TSLexer *lexer) {
|
|
advance(lexer);
|
|
mark_end(lexer);
|
|
}
|
|
|
|
static void skip_wspace(TSLexer *lexer) {
|
|
while (iswspace(lexer->lookahead)) {
|
|
skip(lexer);
|
|
}
|
|
}
|
|
|
|
static bool is_open_brackets(struct TreeSitterCMakeState *state,
|
|
TSLexer *lexer) {
|
|
if (lexer->lookahead != '[') {
|
|
return false;
|
|
}
|
|
|
|
advance(lexer);
|
|
|
|
unsigned level = 0;
|
|
while (lexer->lookahead == '=') {
|
|
++level;
|
|
advance(lexer);
|
|
}
|
|
|
|
if (lexer->lookahead != '[') {
|
|
return false;
|
|
}
|
|
|
|
advance_mark(lexer);
|
|
|
|
state->level = level;
|
|
return true;
|
|
}
|
|
|
|
static void parse_bracketed_content(struct TreeSitterCMakeState *state,
|
|
TSLexer *lexer) {
|
|
while (lexer->lookahead) {
|
|
if (lexer->lookahead == ']') {
|
|
mark_end(lexer);
|
|
|
|
unsigned level = 0;
|
|
advance(lexer);
|
|
while (lexer->lookahead == '=') {
|
|
++level;
|
|
advance(lexer);
|
|
}
|
|
|
|
if (level == state->level && lexer->lookahead == ']') {
|
|
break;
|
|
}
|
|
}
|
|
|
|
advance_mark(lexer);
|
|
}
|
|
}
|
|
|
|
static bool is_close_brackets(struct TreeSitterCMakeState *state,
|
|
TSLexer *lexer) {
|
|
if (lexer->lookahead != ']') {
|
|
return false;
|
|
}
|
|
|
|
unsigned level = 0;
|
|
advance(lexer);
|
|
while (lexer->lookahead == '=') {
|
|
++level;
|
|
advance(lexer);
|
|
}
|
|
|
|
if (level != state->level || lexer->lookahead != ']') {
|
|
return false;
|
|
}
|
|
|
|
advance_mark(lexer);
|
|
|
|
state->level = 0;
|
|
return true;
|
|
}
|
|
|
|
void *tree_sitter_cmake_external_scanner_create() {
|
|
return ts_malloc(sizeof(struct TreeSitterCMakeState));
|
|
}
|
|
|
|
void tree_sitter_cmake_external_scanner_destroy(void *payload) {
|
|
ts_free(payload);
|
|
}
|
|
|
|
unsigned tree_sitter_cmake_external_scanner_serialize(void *payload,
|
|
char *buffer) {
|
|
memcpy(buffer, payload, STATE_SIZE);
|
|
return STATE_SIZE;
|
|
}
|
|
|
|
void tree_sitter_cmake_external_scanner_deserialize(void *payload,
|
|
char const *buffer,
|
|
unsigned length) {
|
|
if (length == STATE_SIZE) {
|
|
memcpy(payload, buffer, length);
|
|
} else {
|
|
struct TreeSitterCMakeState *state = payload;
|
|
state->level = 0;
|
|
}
|
|
}
|
|
|
|
bool tree_sitter_cmake_external_scanner_scan(void *payload, TSLexer *lexer,
|
|
bool const *valid_symbols) {
|
|
|
|
struct TreeSitterCMakeState *state = payload;
|
|
|
|
skip_wspace(lexer);
|
|
|
|
if (valid_symbols[BRACKET_ARGUMENT_OPEN]) {
|
|
if (is_open_brackets(payload, lexer)) {
|
|
state->token = lexer->result_symbol = BRACKET_ARGUMENT_OPEN;
|
|
return true;
|
|
}
|
|
}
|
|
if (valid_symbols[BRACKET_ARGUMENT_CONTENT] &&
|
|
state->token == BRACKET_ARGUMENT_OPEN) {
|
|
parse_bracketed_content(payload, lexer);
|
|
state->token = lexer->result_symbol = BRACKET_ARGUMENT_CONTENT;
|
|
return true;
|
|
}
|
|
if (valid_symbols[BRACKET_ARGUMENT_CLOSE] &&
|
|
state->token == BRACKET_ARGUMENT_CONTENT) {
|
|
if (is_close_brackets(payload, lexer)) {
|
|
lexer->result_symbol = BRACKET_ARGUMENT_CLOSE;
|
|
return true;
|
|
}
|
|
}
|
|
if (lexer->lookahead == '#') {
|
|
if (!valid_symbols[BRACKET_COMMENT_OPEN] && !valid_symbols[LINE_COMMENT]) {
|
|
return false;
|
|
}
|
|
|
|
advance(lexer);
|
|
if (is_open_brackets(payload, lexer)) {
|
|
state->token = lexer->result_symbol = BRACKET_COMMENT_OPEN;
|
|
return true;
|
|
}
|
|
|
|
while (lexer->lookahead != '\r' && lexer->lookahead != '\n' &&
|
|
lexer->lookahead != '\0') {
|
|
advance(lexer);
|
|
}
|
|
|
|
mark_end(lexer);
|
|
lexer->result_symbol = LINE_COMMENT;
|
|
return true;
|
|
}
|
|
if (valid_symbols[BRACKET_COMMENT_CONTENT] &&
|
|
state->token == BRACKET_COMMENT_OPEN) {
|
|
parse_bracketed_content(payload, lexer);
|
|
state->token = lexer->result_symbol = BRACKET_COMMENT_CONTENT;
|
|
return true;
|
|
}
|
|
if (valid_symbols[BRACKET_COMMENT_CLOSE] &&
|
|
state->token == BRACKET_COMMENT_CONTENT) {
|
|
if (is_close_brackets(payload, lexer)) {
|
|
lexer->result_symbol = BRACKET_COMMENT_CLOSE;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
} |