tree-sitter implementation for the confindent configuration language

tree-sitter generate

+856
+22
src/grammar.json
··· 1 + { 2 + "$schema": "https://tree-sitter.github.io/tree-sitter/assets/schemas/grammar.schema.json", 3 + "name": "confindent", 4 + "rules": { 5 + "source_file": { 6 + "type": "STRING", 7 + "value": "hello" 8 + } 9 + }, 10 + "extras": [ 11 + { 12 + "type": "PATTERN", 13 + "value": "\\s" 14 + } 15 + ], 16 + "conflicts": [], 17 + "precedences": [], 18 + "externals": [], 19 + "inline": [], 20 + "supertypes": [], 21 + "reserved": {} 22 + }
+12
src/node-types.json
··· 1 + [ 2 + { 3 + "type": "source_file", 4 + "named": true, 5 + "root": true, 6 + "fields": {} 7 + }, 8 + { 9 + "type": "hello", 10 + "named": false 11 + } 12 + ]
+190
src/parser.c
··· 1 + /* Automatically generated by tree-sitter v0.25.3 */ 2 + 3 + #include "tree_sitter/parser.h" 4 + 5 + #if defined(__GNUC__) || defined(__clang__) 6 + #pragma GCC diagnostic ignored "-Wmissing-field-initializers" 7 + #endif 8 + 9 + #define LANGUAGE_VERSION 15 10 + #define STATE_COUNT 4 11 + #define LARGE_STATE_COUNT 2 12 + #define SYMBOL_COUNT 3 13 + #define ALIAS_COUNT 0 14 + #define TOKEN_COUNT 2 15 + #define EXTERNAL_TOKEN_COUNT 0 16 + #define FIELD_COUNT 0 17 + #define MAX_ALIAS_SEQUENCE_LENGTH 1 18 + #define MAX_RESERVED_WORD_SET_SIZE 0 19 + #define PRODUCTION_ID_COUNT 1 20 + #define SUPERTYPE_COUNT 0 21 + 22 + enum ts_symbol_identifiers { 23 + anon_sym_hello = 1, 24 + sym_source_file = 2, 25 + }; 26 + 27 + static const char * const ts_symbol_names[] = { 28 + [ts_builtin_sym_end] = "end", 29 + [anon_sym_hello] = "hello", 30 + [sym_source_file] = "source_file", 31 + }; 32 + 33 + static const TSSymbol ts_symbol_map[] = { 34 + [ts_builtin_sym_end] = ts_builtin_sym_end, 35 + [anon_sym_hello] = anon_sym_hello, 36 + [sym_source_file] = sym_source_file, 37 + }; 38 + 39 + static const TSSymbolMetadata ts_symbol_metadata[] = { 40 + [ts_builtin_sym_end] = { 41 + .visible = false, 42 + .named = true, 43 + }, 44 + [anon_sym_hello] = { 45 + .visible = true, 46 + .named = false, 47 + }, 48 + [sym_source_file] = { 49 + .visible = true, 50 + .named = true, 51 + }, 52 + }; 53 + 54 + static const TSSymbol ts_alias_sequences[PRODUCTION_ID_COUNT][MAX_ALIAS_SEQUENCE_LENGTH] = { 55 + [0] = {0}, 56 + }; 57 + 58 + static const uint16_t ts_non_terminal_alias_map[] = { 59 + 0, 60 + }; 61 + 62 + static const TSStateId ts_primary_state_ids[STATE_COUNT] = { 63 + [0] = 0, 64 + [1] = 1, 65 + [2] = 2, 66 + [3] = 3, 67 + }; 68 + 69 + static bool ts_lex(TSLexer *lexer, TSStateId state) { 70 + START_LEXER(); 71 + eof = lexer->eof(lexer); 72 + switch (state) { 73 + case 0: 74 + if (eof) ADVANCE(5); 75 + if (lookahead == 'h') ADVANCE(1); 76 + if (('\t' <= lookahead && lookahead <= '\r') || 77 + lookahead == ' ') SKIP(0); 78 + END_STATE(); 79 + case 1: 80 + if (lookahead == 'e') ADVANCE(3); 81 + END_STATE(); 82 + case 2: 83 + if (lookahead == 'l') ADVANCE(4); 84 + END_STATE(); 85 + case 3: 86 + if (lookahead == 'l') ADVANCE(2); 87 + END_STATE(); 88 + case 4: 89 + if (lookahead == 'o') ADVANCE(6); 90 + END_STATE(); 91 + case 5: 92 + ACCEPT_TOKEN(ts_builtin_sym_end); 93 + END_STATE(); 94 + case 6: 95 + ACCEPT_TOKEN(anon_sym_hello); 96 + END_STATE(); 97 + default: 98 + return false; 99 + } 100 + } 101 + 102 + static const TSLexerMode ts_lex_modes[STATE_COUNT] = { 103 + [0] = {.lex_state = 0}, 104 + [1] = {.lex_state = 0}, 105 + [2] = {.lex_state = 0}, 106 + [3] = {.lex_state = 0}, 107 + }; 108 + 109 + static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { 110 + [STATE(0)] = { 111 + [ts_builtin_sym_end] = ACTIONS(1), 112 + [anon_sym_hello] = ACTIONS(1), 113 + }, 114 + [STATE(1)] = { 115 + [sym_source_file] = STATE(3), 116 + [anon_sym_hello] = ACTIONS(3), 117 + }, 118 + }; 119 + 120 + static const uint16_t ts_small_parse_table[] = { 121 + [0] = 1, 122 + ACTIONS(5), 1, 123 + ts_builtin_sym_end, 124 + [4] = 1, 125 + ACTIONS(7), 1, 126 + ts_builtin_sym_end, 127 + }; 128 + 129 + static const uint32_t ts_small_parse_table_map[] = { 130 + [SMALL_STATE(2)] = 0, 131 + [SMALL_STATE(3)] = 4, 132 + }; 133 + 134 + static const TSParseActionEntry ts_parse_actions[] = { 135 + [0] = {.entry = {.count = 0, .reusable = false}}, 136 + [1] = {.entry = {.count = 1, .reusable = false}}, RECOVER(), 137 + [3] = {.entry = {.count = 1, .reusable = true}}, SHIFT(2), 138 + [5] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source_file, 1, 0, 0), 139 + [7] = {.entry = {.count = 1, .reusable = true}}, ACCEPT_INPUT(), 140 + }; 141 + 142 + #ifdef __cplusplus 143 + extern "C" { 144 + #endif 145 + #ifdef TREE_SITTER_HIDE_SYMBOLS 146 + #define TS_PUBLIC 147 + #elif defined(_WIN32) 148 + #define TS_PUBLIC __declspec(dllexport) 149 + #else 150 + #define TS_PUBLIC __attribute__((visibility("default"))) 151 + #endif 152 + 153 + TS_PUBLIC const TSLanguage *tree_sitter_confindent(void) { 154 + static const TSLanguage language = { 155 + .abi_version = LANGUAGE_VERSION, 156 + .symbol_count = SYMBOL_COUNT, 157 + .alias_count = ALIAS_COUNT, 158 + .token_count = TOKEN_COUNT, 159 + .external_token_count = EXTERNAL_TOKEN_COUNT, 160 + .state_count = STATE_COUNT, 161 + .large_state_count = LARGE_STATE_COUNT, 162 + .production_id_count = PRODUCTION_ID_COUNT, 163 + .supertype_count = SUPERTYPE_COUNT, 164 + .field_count = FIELD_COUNT, 165 + .max_alias_sequence_length = MAX_ALIAS_SEQUENCE_LENGTH, 166 + .parse_table = &ts_parse_table[0][0], 167 + .small_parse_table = ts_small_parse_table, 168 + .small_parse_table_map = ts_small_parse_table_map, 169 + .parse_actions = ts_parse_actions, 170 + .symbol_names = ts_symbol_names, 171 + .symbol_metadata = ts_symbol_metadata, 172 + .public_symbol_map = ts_symbol_map, 173 + .alias_map = ts_non_terminal_alias_map, 174 + .alias_sequences = &ts_alias_sequences[0][0], 175 + .lex_modes = (const void*)ts_lex_modes, 176 + .lex_fn = ts_lex, 177 + .primary_state_ids = ts_primary_state_ids, 178 + .name = "confindent", 179 + .max_reserved_word_set_size = 0, 180 + .metadata = { 181 + .major_version = 0, 182 + .minor_version = 1, 183 + .patch_version = 0, 184 + }, 185 + }; 186 + return &language; 187 + } 188 + #ifdef __cplusplus 189 + } 190 + #endif
+54
src/tree_sitter/alloc.h
··· 1 + #ifndef TREE_SITTER_ALLOC_H_ 2 + #define TREE_SITTER_ALLOC_H_ 3 + 4 + #ifdef __cplusplus 5 + extern "C" { 6 + #endif 7 + 8 + #include <stdbool.h> 9 + #include <stdio.h> 10 + #include <stdlib.h> 11 + 12 + // Allow clients to override allocation functions 13 + #ifdef TREE_SITTER_REUSE_ALLOCATOR 14 + 15 + extern void *(*ts_current_malloc)(size_t size); 16 + extern void *(*ts_current_calloc)(size_t count, size_t size); 17 + extern void *(*ts_current_realloc)(void *ptr, size_t size); 18 + extern void (*ts_current_free)(void *ptr); 19 + 20 + #ifndef ts_malloc 21 + #define ts_malloc ts_current_malloc 22 + #endif 23 + #ifndef ts_calloc 24 + #define ts_calloc ts_current_calloc 25 + #endif 26 + #ifndef ts_realloc 27 + #define ts_realloc ts_current_realloc 28 + #endif 29 + #ifndef ts_free 30 + #define ts_free ts_current_free 31 + #endif 32 + 33 + #else 34 + 35 + #ifndef ts_malloc 36 + #define ts_malloc malloc 37 + #endif 38 + #ifndef ts_calloc 39 + #define ts_calloc calloc 40 + #endif 41 + #ifndef ts_realloc 42 + #define ts_realloc realloc 43 + #endif 44 + #ifndef ts_free 45 + #define ts_free free 46 + #endif 47 + 48 + #endif 49 + 50 + #ifdef __cplusplus 51 + } 52 + #endif 53 + 54 + #endif // TREE_SITTER_ALLOC_H_
+291
src/tree_sitter/array.h
··· 1 + #ifndef TREE_SITTER_ARRAY_H_ 2 + #define TREE_SITTER_ARRAY_H_ 3 + 4 + #ifdef __cplusplus 5 + extern "C" { 6 + #endif 7 + 8 + #include "./alloc.h" 9 + 10 + #include <assert.h> 11 + #include <stdbool.h> 12 + #include <stdint.h> 13 + #include <stdlib.h> 14 + #include <string.h> 15 + 16 + #ifdef _MSC_VER 17 + #pragma warning(push) 18 + #pragma warning(disable : 4101) 19 + #elif defined(__GNUC__) || defined(__clang__) 20 + #pragma GCC diagnostic push 21 + #pragma GCC diagnostic ignored "-Wunused-variable" 22 + #endif 23 + 24 + #define Array(T) \ 25 + struct { \ 26 + T *contents; \ 27 + uint32_t size; \ 28 + uint32_t capacity; \ 29 + } 30 + 31 + /// Initialize an array. 32 + #define array_init(self) \ 33 + ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL) 34 + 35 + /// Create an empty array. 36 + #define array_new() \ 37 + { NULL, 0, 0 } 38 + 39 + /// Get a pointer to the element at a given `index` in the array. 40 + #define array_get(self, _index) \ 41 + (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index]) 42 + 43 + /// Get a pointer to the first element in the array. 44 + #define array_front(self) array_get(self, 0) 45 + 46 + /// Get a pointer to the last element in the array. 47 + #define array_back(self) array_get(self, (self)->size - 1) 48 + 49 + /// Clear the array, setting its size to zero. Note that this does not free any 50 + /// memory allocated for the array's contents. 51 + #define array_clear(self) ((self)->size = 0) 52 + 53 + /// Reserve `new_capacity` elements of space in the array. If `new_capacity` is 54 + /// less than the array's current capacity, this function has no effect. 55 + #define array_reserve(self, new_capacity) \ 56 + _array__reserve((Array *)(self), array_elem_size(self), new_capacity) 57 + 58 + /// Free any memory allocated for this array. Note that this does not free any 59 + /// memory allocated for the array's contents. 60 + #define array_delete(self) _array__delete((Array *)(self)) 61 + 62 + /// Push a new `element` onto the end of the array. 63 + #define array_push(self, element) \ 64 + (_array__grow((Array *)(self), 1, array_elem_size(self)), \ 65 + (self)->contents[(self)->size++] = (element)) 66 + 67 + /// Increase the array's size by `count` elements. 68 + /// New elements are zero-initialized. 69 + #define array_grow_by(self, count) \ 70 + do { \ 71 + if ((count) == 0) break; \ 72 + _array__grow((Array *)(self), count, array_elem_size(self)); \ 73 + memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \ 74 + (self)->size += (count); \ 75 + } while (0) 76 + 77 + /// Append all elements from one array to the end of another. 78 + #define array_push_all(self, other) \ 79 + array_extend((self), (other)->size, (other)->contents) 80 + 81 + /// Append `count` elements to the end of the array, reading their values from the 82 + /// `contents` pointer. 83 + #define array_extend(self, count, contents) \ 84 + _array__splice( \ 85 + (Array *)(self), array_elem_size(self), (self)->size, \ 86 + 0, count, contents \ 87 + ) 88 + 89 + /// Remove `old_count` elements from the array starting at the given `index`. At 90 + /// the same index, insert `new_count` new elements, reading their values from the 91 + /// `new_contents` pointer. 92 + #define array_splice(self, _index, old_count, new_count, new_contents) \ 93 + _array__splice( \ 94 + (Array *)(self), array_elem_size(self), _index, \ 95 + old_count, new_count, new_contents \ 96 + ) 97 + 98 + /// Insert one `element` into the array at the given `index`. 99 + #define array_insert(self, _index, element) \ 100 + _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element)) 101 + 102 + /// Remove one element from the array at the given `index`. 103 + #define array_erase(self, _index) \ 104 + _array__erase((Array *)(self), array_elem_size(self), _index) 105 + 106 + /// Pop the last element off the array, returning the element by value. 107 + #define array_pop(self) ((self)->contents[--(self)->size]) 108 + 109 + /// Assign the contents of one array to another, reallocating if necessary. 110 + #define array_assign(self, other) \ 111 + _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self)) 112 + 113 + /// Swap one array with another 114 + #define array_swap(self, other) \ 115 + _array__swap((Array *)(self), (Array *)(other)) 116 + 117 + /// Get the size of the array contents 118 + #define array_elem_size(self) (sizeof *(self)->contents) 119 + 120 + /// Search a sorted array for a given `needle` value, using the given `compare` 121 + /// callback to determine the order. 122 + /// 123 + /// If an existing element is found to be equal to `needle`, then the `index` 124 + /// out-parameter is set to the existing value's index, and the `exists` 125 + /// out-parameter is set to true. Otherwise, `index` is set to an index where 126 + /// `needle` should be inserted in order to preserve the sorting, and `exists` 127 + /// is set to false. 128 + #define array_search_sorted_with(self, compare, needle, _index, _exists) \ 129 + _array__search_sorted(self, 0, compare, , needle, _index, _exists) 130 + 131 + /// Search a sorted array for a given `needle` value, using integer comparisons 132 + /// of a given struct field (specified with a leading dot) to determine the order. 133 + /// 134 + /// See also `array_search_sorted_with`. 135 + #define array_search_sorted_by(self, field, needle, _index, _exists) \ 136 + _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists) 137 + 138 + /// Insert a given `value` into a sorted array, using the given `compare` 139 + /// callback to determine the order. 140 + #define array_insert_sorted_with(self, compare, value) \ 141 + do { \ 142 + unsigned _index, _exists; \ 143 + array_search_sorted_with(self, compare, &(value), &_index, &_exists); \ 144 + if (!_exists) array_insert(self, _index, value); \ 145 + } while (0) 146 + 147 + /// Insert a given `value` into a sorted array, using integer comparisons of 148 + /// a given struct field (specified with a leading dot) to determine the order. 149 + /// 150 + /// See also `array_search_sorted_by`. 151 + #define array_insert_sorted_by(self, field, value) \ 152 + do { \ 153 + unsigned _index, _exists; \ 154 + array_search_sorted_by(self, field, (value) field, &_index, &_exists); \ 155 + if (!_exists) array_insert(self, _index, value); \ 156 + } while (0) 157 + 158 + // Private 159 + 160 + typedef Array(void) Array; 161 + 162 + /// This is not what you're looking for, see `array_delete`. 163 + static inline void _array__delete(Array *self) { 164 + if (self->contents) { 165 + ts_free(self->contents); 166 + self->contents = NULL; 167 + self->size = 0; 168 + self->capacity = 0; 169 + } 170 + } 171 + 172 + /// This is not what you're looking for, see `array_erase`. 173 + static inline void _array__erase(Array *self, size_t element_size, 174 + uint32_t index) { 175 + assert(index < self->size); 176 + char *contents = (char *)self->contents; 177 + memmove(contents + index * element_size, contents + (index + 1) * element_size, 178 + (self->size - index - 1) * element_size); 179 + self->size--; 180 + } 181 + 182 + /// This is not what you're looking for, see `array_reserve`. 183 + static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) { 184 + if (new_capacity > self->capacity) { 185 + if (self->contents) { 186 + self->contents = ts_realloc(self->contents, new_capacity * element_size); 187 + } else { 188 + self->contents = ts_malloc(new_capacity * element_size); 189 + } 190 + self->capacity = new_capacity; 191 + } 192 + } 193 + 194 + /// This is not what you're looking for, see `array_assign`. 195 + static inline void _array__assign(Array *self, const Array *other, size_t element_size) { 196 + _array__reserve(self, element_size, other->size); 197 + self->size = other->size; 198 + memcpy(self->contents, other->contents, self->size * element_size); 199 + } 200 + 201 + /// This is not what you're looking for, see `array_swap`. 202 + static inline void _array__swap(Array *self, Array *other) { 203 + Array swap = *other; 204 + *other = *self; 205 + *self = swap; 206 + } 207 + 208 + /// This is not what you're looking for, see `array_push` or `array_grow_by`. 209 + static inline void _array__grow(Array *self, uint32_t count, size_t element_size) { 210 + uint32_t new_size = self->size + count; 211 + if (new_size > self->capacity) { 212 + uint32_t new_capacity = self->capacity * 2; 213 + if (new_capacity < 8) new_capacity = 8; 214 + if (new_capacity < new_size) new_capacity = new_size; 215 + _array__reserve(self, element_size, new_capacity); 216 + } 217 + } 218 + 219 + /// This is not what you're looking for, see `array_splice`. 220 + static inline void _array__splice(Array *self, size_t element_size, 221 + uint32_t index, uint32_t old_count, 222 + uint32_t new_count, const void *elements) { 223 + uint32_t new_size = self->size + new_count - old_count; 224 + uint32_t old_end = index + old_count; 225 + uint32_t new_end = index + new_count; 226 + assert(old_end <= self->size); 227 + 228 + _array__reserve(self, element_size, new_size); 229 + 230 + char *contents = (char *)self->contents; 231 + if (self->size > old_end) { 232 + memmove( 233 + contents + new_end * element_size, 234 + contents + old_end * element_size, 235 + (self->size - old_end) * element_size 236 + ); 237 + } 238 + if (new_count > 0) { 239 + if (elements) { 240 + memcpy( 241 + (contents + index * element_size), 242 + elements, 243 + new_count * element_size 244 + ); 245 + } else { 246 + memset( 247 + (contents + index * element_size), 248 + 0, 249 + new_count * element_size 250 + ); 251 + } 252 + } 253 + self->size += new_count - old_count; 254 + } 255 + 256 + /// A binary search routine, based on Rust's `std::slice::binary_search_by`. 257 + /// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`. 258 + #define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \ 259 + do { \ 260 + *(_index) = start; \ 261 + *(_exists) = false; \ 262 + uint32_t size = (self)->size - *(_index); \ 263 + if (size == 0) break; \ 264 + int comparison; \ 265 + while (size > 1) { \ 266 + uint32_t half_size = size / 2; \ 267 + uint32_t mid_index = *(_index) + half_size; \ 268 + comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \ 269 + if (comparison <= 0) *(_index) = mid_index; \ 270 + size -= half_size; \ 271 + } \ 272 + comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \ 273 + if (comparison == 0) *(_exists) = true; \ 274 + else if (comparison < 0) *(_index) += 1; \ 275 + } while (0) 276 + 277 + /// Helper macro for the `_sorted_by` routines below. This takes the left (existing) 278 + /// parameter by reference in order to work with the generic sorting function above. 279 + #define _compare_int(a, b) ((int)*(a) - (int)(b)) 280 + 281 + #ifdef _MSC_VER 282 + #pragma warning(pop) 283 + #elif defined(__GNUC__) || defined(__clang__) 284 + #pragma GCC diagnostic pop 285 + #endif 286 + 287 + #ifdef __cplusplus 288 + } 289 + #endif 290 + 291 + #endif // TREE_SITTER_ARRAY_H_
+287
src/tree_sitter/parser.h
··· 1 + #ifndef TREE_SITTER_PARSER_H_ 2 + #define TREE_SITTER_PARSER_H_ 3 + 4 + #ifdef __cplusplus 5 + extern "C" { 6 + #endif 7 + 8 + #include <stdbool.h> 9 + #include <stdint.h> 10 + #include <stdlib.h> 11 + 12 + #define ts_builtin_sym_error ((TSSymbol)-1) 13 + #define ts_builtin_sym_end 0 14 + #define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024 15 + 16 + #ifndef TREE_SITTER_API_H_ 17 + typedef uint16_t TSStateId; 18 + typedef uint16_t TSSymbol; 19 + typedef uint16_t TSFieldId; 20 + typedef struct TSLanguage TSLanguage; 21 + typedef struct TSLanguageMetadata TSLanguageMetadata; 22 + typedef struct TSLanguageMetadata { 23 + uint8_t major_version; 24 + uint8_t minor_version; 25 + uint8_t patch_version; 26 + } TSLanguageMetadata; 27 + #endif 28 + 29 + typedef struct { 30 + TSFieldId field_id; 31 + uint8_t child_index; 32 + bool inherited; 33 + } TSFieldMapEntry; 34 + 35 + // Used to index the field and supertype maps. 36 + typedef struct { 37 + uint16_t index; 38 + uint16_t length; 39 + } TSMapSlice; 40 + 41 + typedef struct { 42 + bool visible; 43 + bool named; 44 + bool supertype; 45 + } TSSymbolMetadata; 46 + 47 + typedef struct TSLexer TSLexer; 48 + 49 + struct TSLexer { 50 + int32_t lookahead; 51 + TSSymbol result_symbol; 52 + void (*advance)(TSLexer *, bool); 53 + void (*mark_end)(TSLexer *); 54 + uint32_t (*get_column)(TSLexer *); 55 + bool (*is_at_included_range_start)(const TSLexer *); 56 + bool (*eof)(const TSLexer *); 57 + void (*log)(const TSLexer *, const char *, ...); 58 + }; 59 + 60 + typedef enum { 61 + TSParseActionTypeShift, 62 + TSParseActionTypeReduce, 63 + TSParseActionTypeAccept, 64 + TSParseActionTypeRecover, 65 + } TSParseActionType; 66 + 67 + typedef union { 68 + struct { 69 + uint8_t type; 70 + TSStateId state; 71 + bool extra; 72 + bool repetition; 73 + } shift; 74 + struct { 75 + uint8_t type; 76 + uint8_t child_count; 77 + TSSymbol symbol; 78 + int16_t dynamic_precedence; 79 + uint16_t production_id; 80 + } reduce; 81 + uint8_t type; 82 + } TSParseAction; 83 + 84 + typedef struct { 85 + uint16_t lex_state; 86 + uint16_t external_lex_state; 87 + } TSLexMode; 88 + 89 + typedef struct { 90 + uint16_t lex_state; 91 + uint16_t external_lex_state; 92 + uint16_t reserved_word_set_id; 93 + } TSLexerMode; 94 + 95 + typedef union { 96 + TSParseAction action; 97 + struct { 98 + uint8_t count; 99 + bool reusable; 100 + } entry; 101 + } TSParseActionEntry; 102 + 103 + typedef struct { 104 + int32_t start; 105 + int32_t end; 106 + } TSCharacterRange; 107 + 108 + struct TSLanguage { 109 + uint32_t abi_version; 110 + uint32_t symbol_count; 111 + uint32_t alias_count; 112 + uint32_t token_count; 113 + uint32_t external_token_count; 114 + uint32_t state_count; 115 + uint32_t large_state_count; 116 + uint32_t production_id_count; 117 + uint32_t field_count; 118 + uint16_t max_alias_sequence_length; 119 + const uint16_t *parse_table; 120 + const uint16_t *small_parse_table; 121 + const uint32_t *small_parse_table_map; 122 + const TSParseActionEntry *parse_actions; 123 + const char * const *symbol_names; 124 + const char * const *field_names; 125 + const TSMapSlice *field_map_slices; 126 + const TSFieldMapEntry *field_map_entries; 127 + const TSSymbolMetadata *symbol_metadata; 128 + const TSSymbol *public_symbol_map; 129 + const uint16_t *alias_map; 130 + const TSSymbol *alias_sequences; 131 + const TSLexerMode *lex_modes; 132 + bool (*lex_fn)(TSLexer *, TSStateId); 133 + bool (*keyword_lex_fn)(TSLexer *, TSStateId); 134 + TSSymbol keyword_capture_token; 135 + struct { 136 + const bool *states; 137 + const TSSymbol *symbol_map; 138 + void *(*create)(void); 139 + void (*destroy)(void *); 140 + bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); 141 + unsigned (*serialize)(void *, char *); 142 + void (*deserialize)(void *, const char *, unsigned); 143 + } external_scanner; 144 + const TSStateId *primary_state_ids; 145 + const char *name; 146 + const TSSymbol *reserved_words; 147 + uint16_t max_reserved_word_set_size; 148 + uint32_t supertype_count; 149 + const TSSymbol *supertype_symbols; 150 + const TSMapSlice *supertype_map_slices; 151 + const TSSymbol *supertype_map_entries; 152 + TSLanguageMetadata metadata; 153 + }; 154 + 155 + static inline bool set_contains(const TSCharacterRange *ranges, uint32_t len, int32_t lookahead) { 156 + uint32_t index = 0; 157 + uint32_t size = len - index; 158 + while (size > 1) { 159 + uint32_t half_size = size / 2; 160 + uint32_t mid_index = index + half_size; 161 + const TSCharacterRange *range = &ranges[mid_index]; 162 + if (lookahead >= range->start && lookahead <= range->end) { 163 + return true; 164 + } else if (lookahead > range->end) { 165 + index = mid_index; 166 + } 167 + size -= half_size; 168 + } 169 + const TSCharacterRange *range = &ranges[index]; 170 + return (lookahead >= range->start && lookahead <= range->end); 171 + } 172 + 173 + /* 174 + * Lexer Macros 175 + */ 176 + 177 + #ifdef _MSC_VER 178 + #define UNUSED __pragma(warning(suppress : 4101)) 179 + #else 180 + #define UNUSED __attribute__((unused)) 181 + #endif 182 + 183 + #define START_LEXER() \ 184 + bool result = false; \ 185 + bool skip = false; \ 186 + UNUSED \ 187 + bool eof = false; \ 188 + int32_t lookahead; \ 189 + goto start; \ 190 + next_state: \ 191 + lexer->advance(lexer, skip); \ 192 + start: \ 193 + skip = false; \ 194 + lookahead = lexer->lookahead; 195 + 196 + #define ADVANCE(state_value) \ 197 + { \ 198 + state = state_value; \ 199 + goto next_state; \ 200 + } 201 + 202 + #define ADVANCE_MAP(...) \ 203 + { \ 204 + static const uint16_t map[] = { __VA_ARGS__ }; \ 205 + for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ 206 + if (map[i] == lookahead) { \ 207 + state = map[i + 1]; \ 208 + goto next_state; \ 209 + } \ 210 + } \ 211 + } 212 + 213 + #define SKIP(state_value) \ 214 + { \ 215 + skip = true; \ 216 + state = state_value; \ 217 + goto next_state; \ 218 + } 219 + 220 + #define ACCEPT_TOKEN(symbol_value) \ 221 + result = true; \ 222 + lexer->result_symbol = symbol_value; \ 223 + lexer->mark_end(lexer); 224 + 225 + #define END_STATE() return result; 226 + 227 + /* 228 + * Parse Table Macros 229 + */ 230 + 231 + #define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) 232 + 233 + #define STATE(id) id 234 + 235 + #define ACTIONS(id) id 236 + 237 + #define SHIFT(state_value) \ 238 + {{ \ 239 + .shift = { \ 240 + .type = TSParseActionTypeShift, \ 241 + .state = (state_value) \ 242 + } \ 243 + }} 244 + 245 + #define SHIFT_REPEAT(state_value) \ 246 + {{ \ 247 + .shift = { \ 248 + .type = TSParseActionTypeShift, \ 249 + .state = (state_value), \ 250 + .repetition = true \ 251 + } \ 252 + }} 253 + 254 + #define SHIFT_EXTRA() \ 255 + {{ \ 256 + .shift = { \ 257 + .type = TSParseActionTypeShift, \ 258 + .extra = true \ 259 + } \ 260 + }} 261 + 262 + #define REDUCE(symbol_name, children, precedence, prod_id) \ 263 + {{ \ 264 + .reduce = { \ 265 + .type = TSParseActionTypeReduce, \ 266 + .symbol = symbol_name, \ 267 + .child_count = children, \ 268 + .dynamic_precedence = precedence, \ 269 + .production_id = prod_id \ 270 + }, \ 271 + }} 272 + 273 + #define RECOVER() \ 274 + {{ \ 275 + .type = TSParseActionTypeRecover \ 276 + }} 277 + 278 + #define ACCEPT_INPUT() \ 279 + {{ \ 280 + .type = TSParseActionTypeAccept \ 281 + }} 282 + 283 + #ifdef __cplusplus 284 + } 285 + #endif 286 + 287 + #endif // TREE_SITTER_PARSER_H_