summaryrefslogtreecommitdiff
path: root/vendor/tree-sitter-lua/src/scanner.c
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2026-01-22 11:19:54 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2026-01-22 11:19:54 +0100
commit19dadd080226d2e7c6dc44a53eb0ee3ee2afcbae (patch)
tree97f0b4b584b33bc11da1edac1ab9b7eea3413888 /vendor/tree-sitter-lua/src/scanner.c
parent5ed59329be62c0b3a59fb47a89fd8c00a74bed5d (diff)
downloadcrep-19dadd080226d2e7c6dc44a53eb0ee3ee2afcbae.tar.gz
Add Lua grammar
Diffstat (limited to 'vendor/tree-sitter-lua/src/scanner.c')
-rw-r--r--vendor/tree-sitter-lua/src/scanner.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/vendor/tree-sitter-lua/src/scanner.c b/vendor/tree-sitter-lua/src/scanner.c
new file mode 100644
index 0000000..58db18b
--- /dev/null
+++ b/vendor/tree-sitter-lua/src/scanner.c
@@ -0,0 +1,194 @@
+#include <stdio.h>
+#include "tree_sitter/parser.h"
+#include <wctype.h>
+
+enum TokenType {
+ BLOCK_COMMENT_START,
+ BLOCK_COMMENT_CONTENT,
+ BLOCK_COMMENT_END,
+
+ BLOCK_STRING_START,
+ BLOCK_STRING_CONTENT,
+ BLOCK_STRING_END,
+};
+
+static inline void consume(TSLexer *lexer) { lexer->advance(lexer, false); }
+
+static inline void skip(TSLexer *lexer) { lexer->advance(lexer, true); }
+
+static inline bool consume_char(char c, TSLexer *lexer) {
+ if (lexer->lookahead != c) {
+ return false;
+ }
+
+ consume(lexer);
+ return true;
+}
+
+static inline uint8_t consume_and_count_char(char c, TSLexer *lexer) {
+ uint8_t count = 0;
+ while (lexer->lookahead == c) {
+ ++count;
+ consume(lexer);
+ }
+ return count;
+}
+
+static inline void skip_whitespaces(TSLexer *lexer) {
+ while (iswspace(lexer->lookahead)) {
+ skip(lexer);
+ }
+}
+
+typedef struct {
+ char ending_char;
+ uint8_t level_count;
+} Scanner;
+
+static inline void reset_state(Scanner *scanner) {
+ scanner->ending_char = 0;
+ scanner->level_count = 0;
+}
+
+void *tree_sitter_lua_external_scanner_create() {
+ Scanner *scanner = calloc(1, sizeof(Scanner));
+ return scanner;
+}
+
+void tree_sitter_lua_external_scanner_destroy(void *payload) {
+ Scanner *scanner = (Scanner *)payload;
+ free(scanner);
+}
+
+unsigned tree_sitter_lua_external_scanner_serialize(void *payload, char *buffer) {
+ Scanner *scanner = (Scanner *)payload;
+ buffer[0] = scanner->ending_char;
+ buffer[1] = (char)scanner->level_count;
+ return 2;
+}
+
+void tree_sitter_lua_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
+ Scanner *scanner = (Scanner *)payload;
+ if (length == 0) return;
+ scanner->ending_char = buffer[0];
+ if (length == 1) return;
+ scanner->level_count = buffer[1];
+}
+
+static bool scan_block_start(Scanner *scanner, TSLexer *lexer) {
+ if (consume_char('[', lexer)) {
+ uint8_t level = consume_and_count_char('=', lexer);
+
+ if (consume_char('[', lexer)) {
+ scanner->level_count = level;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool scan_block_end(Scanner *scanner, TSLexer *lexer) {
+ if (consume_char(']', lexer)) {
+ uint8_t level = consume_and_count_char('=', lexer);
+
+ if (scanner->level_count == level && consume_char(']', lexer)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool scan_block_content(Scanner *scanner, TSLexer *lexer) {
+ while (lexer->lookahead != 0) {
+ if (lexer->lookahead == ']') {
+ lexer->mark_end(lexer);
+
+ if (scan_block_end(scanner, lexer)) {
+ return true;
+ }
+ } else {
+ consume(lexer);
+ }
+ }
+
+ return false;
+}
+
+static bool scan_comment_start(Scanner *scanner, TSLexer *lexer) {
+ if (consume_char('-', lexer) && consume_char('-', lexer)) {
+ lexer->mark_end(lexer);
+
+ if (scan_block_start(scanner, lexer)) {
+ lexer->mark_end(lexer);
+ lexer->result_symbol = BLOCK_COMMENT_START;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool scan_comment_content(Scanner *scanner, TSLexer *lexer) {
+ if (scanner->ending_char == 0) { // block comment
+ if (scan_block_content(scanner, lexer)) {
+ lexer->result_symbol = BLOCK_COMMENT_CONTENT;
+ return true;
+ }
+
+ return false;
+ }
+
+ while (lexer->lookahead != 0) {
+ if (lexer->lookahead == scanner->ending_char) {
+ reset_state(scanner);
+ lexer->result_symbol = BLOCK_COMMENT_CONTENT;
+ return true;
+ }
+
+ consume(lexer);
+ }
+
+ return false;
+}
+
+bool tree_sitter_lua_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) {
+ Scanner *scanner = (Scanner *)payload;
+
+ if (valid_symbols[BLOCK_STRING_END] && scan_block_end(scanner, lexer)) {
+ reset_state(scanner);
+ lexer->result_symbol = BLOCK_STRING_END;
+ return true;
+ }
+
+ if (valid_symbols[BLOCK_STRING_CONTENT] && scan_block_content(scanner, lexer)) {
+ lexer->result_symbol = BLOCK_STRING_CONTENT;
+ return true;
+ }
+
+ if (valid_symbols[BLOCK_COMMENT_END] && scanner->ending_char == 0 && scan_block_end(scanner, lexer)) {
+ reset_state(scanner);
+ lexer->result_symbol = BLOCK_COMMENT_END;
+ return true;
+ }
+
+ if (valid_symbols[BLOCK_COMMENT_CONTENT] && scan_comment_content(scanner, lexer)) {
+ return true;
+ }
+
+ skip_whitespaces(lexer);
+
+ if (valid_symbols[BLOCK_STRING_START] && scan_block_start(scanner, lexer)) {
+ lexer->result_symbol = BLOCK_STRING_START;
+ return true;
+ }
+
+ if (valid_symbols[BLOCK_COMMENT_START]) {
+ if (scan_comment_start(scanner, lexer)) {
+ return true;
+ }
+ }
+
+ return false;
+}