aboutsummaryrefslogtreecommitdiff
path: root/vendor/tree-sitter/lib/src/language.h
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2023-11-07 16:38:48 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2023-11-07 16:38:48 +0100
commitc0377818aa198a5b5d0d3c7697373c5b6828d5fa (patch)
tree8deb7109e9c996884a6a86ab46ec6190e793c532 /vendor/tree-sitter/lib/src/language.h
parentf9dcd08833afdfb3b4446cb842d3ecd4469c5638 (diff)
downloadcrep-c0377818aa198a5b5d0d3c7697373c5b6828d5fa.tar.gz
Added tree-sitter vendor library
Diffstat (limited to 'vendor/tree-sitter/lib/src/language.h')
-rw-r--r--vendor/tree-sitter/lib/src/language.h296
1 files changed, 296 insertions, 0 deletions
diff --git a/vendor/tree-sitter/lib/src/language.h b/vendor/tree-sitter/lib/src/language.h
new file mode 100644
index 0000000..55b5d89
--- /dev/null
+++ b/vendor/tree-sitter/lib/src/language.h
@@ -0,0 +1,296 @@
1#ifndef TREE_SITTER_LANGUAGE_H_
2#define TREE_SITTER_LANGUAGE_H_
3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
8#include "./subtree.h"
9#include "tree_sitter/parser.h"
10
11#define ts_builtin_sym_error_repeat (ts_builtin_sym_error - 1)
12
13typedef struct {
14 const TSParseAction *actions;
15 uint32_t action_count;
16 bool is_reusable;
17} TableEntry;
18
19typedef struct {
20 const TSLanguage *language;
21 const uint16_t *data;
22 const uint16_t *group_end;
23 TSStateId state;
24 uint16_t table_value;
25 uint16_t section_index;
26 uint16_t group_count;
27 bool is_small_state;
28
29 const TSParseAction *actions;
30 TSSymbol symbol;
31 TSStateId next_state;
32 uint16_t action_count;
33} LookaheadIterator;
34
35void ts_language_table_entry(const TSLanguage *, TSStateId, TSSymbol, TableEntry *);
36
37TSSymbolMetadata ts_language_symbol_metadata(const TSLanguage *, TSSymbol);
38
39TSSymbol ts_language_public_symbol(const TSLanguage *, TSSymbol);
40
41TSStateId ts_language_next_state(const TSLanguage *self, TSStateId state, TSSymbol symbol);
42
43static inline bool ts_language_is_symbol_external(const TSLanguage *self, TSSymbol symbol) {
44 return 0 < symbol && symbol < self->external_token_count + 1;
45}
46
47static inline const TSParseAction *ts_language_actions(
48 const TSLanguage *self,
49 TSStateId state,
50 TSSymbol symbol,
51 uint32_t *count
52) {
53 TableEntry entry;
54 ts_language_table_entry(self, state, symbol, &entry);
55 *count = entry.action_count;
56 return entry.actions;
57}
58
59static inline bool ts_language_has_reduce_action(
60 const TSLanguage *self,
61 TSStateId state,
62 TSSymbol symbol
63) {
64 TableEntry entry;
65 ts_language_table_entry(self, state, symbol, &entry);
66 return entry.action_count > 0 && entry.actions[0].type == TSParseActionTypeReduce;
67}
68
69// Lookup the table value for a given symbol and state.
70//
71// For non-terminal symbols, the table value represents a successor state.
72// For terminal symbols, it represents an index in the actions table.
73// For 'large' parse states, this is a direct lookup. For 'small' parse
74// states, this requires searching through the symbol groups to find
75// the given symbol.
76static inline uint16_t ts_language_lookup(
77 const TSLanguage *self,
78 TSStateId state,
79 TSSymbol symbol
80) {
81 if (state >= self->large_state_count) {
82 uint32_t index = self->small_parse_table_map[state - self->large_state_count];
83 const uint16_t *data = &self->small_parse_table[index];
84 uint16_t group_count = *(data++);
85 for (unsigned i = 0; i < group_count; i++) {
86 uint16_t section_value = *(data++);
87 uint16_t symbol_count = *(data++);
88 for (unsigned j = 0; j < symbol_count; j++) {
89 if (*(data++) == symbol) return section_value;
90 }
91 }
92 return 0;
93 } else {
94 return self->parse_table[state * self->symbol_count + symbol];
95 }
96}
97
98static inline bool ts_language_has_actions(
99 const TSLanguage *self,
100 TSStateId state,
101 TSSymbol symbol
102) {
103 return ts_language_lookup(self, state, symbol) != 0;
104}
105
106// Iterate over all of the symbols that are valid in the given state.
107//
108// For 'large' parse states, this just requires iterating through
109// all possible symbols and checking the parse table for each one.
110// For 'small' parse states, this exploits the structure of the
111// table to only visit the valid symbols.
112static inline LookaheadIterator ts_language_lookaheads(
113 const TSLanguage *self,
114 TSStateId state
115) {
116 bool is_small_state = state >= self->large_state_count;
117 const uint16_t *data;
118 const uint16_t *group_end = NULL;
119 uint16_t group_count = 0;
120 if (is_small_state) {
121 uint32_t index = self->small_parse_table_map[state - self->large_state_count];
122 data = &self->small_parse_table[index];
123 group_end = data + 1;
124 group_count = *data;
125 } else {
126 data = &self->parse_table[state * self->symbol_count] - 1;
127 }
128 return (LookaheadIterator) {
129 .language = self,
130 .data = data,
131 .group_end = group_end,
132 .group_count = group_count,
133 .is_small_state = is_small_state,
134 .symbol = UINT16_MAX,
135 .next_state = 0,
136 };
137}
138
139static inline bool ts_lookahead_iterator__next(LookaheadIterator *self) {
140 // For small parse states, valid symbols are listed explicitly,
141 // grouped by their value. There's no need to look up the actions
142 // again until moving to the next group.
143 if (self->is_small_state) {
144 self->data++;
145 if (self->data == self->group_end) {
146 if (self->group_count == 0) return false;
147 self->group_count--;
148 self->table_value = *(self->data++);
149 unsigned symbol_count = *(self->data++);
150 self->group_end = self->data + symbol_count;
151 self->symbol = *self->data;
152 } else {
153 self->symbol = *self->data;
154 return true;
155 }
156 }
157
158 // For large parse states, iterate through every symbol until one
159 // is found that has valid actions.
160 else {
161 do {
162 self->data++;
163 self->symbol++;
164 if (self->symbol >= self->language->symbol_count) return false;
165 self->table_value = *self->data;
166 } while (!self->table_value);
167 }
168
169 // Depending on if the symbols is terminal or non-terminal, the table value either
170 // represents a list of actions or a successor state.
171 if (self->symbol < self->language->token_count) {
172 const TSParseActionEntry *entry = &self->language->parse_actions[self->table_value];
173 self->action_count = entry->entry.count;
174 self->actions = (const TSParseAction *)(entry + 1);
175 self->next_state = 0;
176 } else {
177 self->action_count = 0;
178 self->next_state = self->table_value;
179 }
180 return true;
181}
182
183// Whether the state is a "primary state". If this returns false, it indicates that there exists
184// another state that behaves identically to this one with respect to query analysis.
185static inline bool ts_language_state_is_primary(
186 const TSLanguage *self,
187 TSStateId state
188) {
189 if (self->version >= 14) {
190 return state == self->primary_state_ids[state];
191 } else {
192 return true;
193 }
194}
195
196static inline const bool *ts_language_enabled_external_tokens(
197 const TSLanguage *self,
198 unsigned external_scanner_state
199) {
200 if (external_scanner_state == 0) {
201 return NULL;
202 } else {
203 return self->external_scanner.states + self->external_token_count * external_scanner_state;
204 }
205}
206
207static inline const TSSymbol *ts_language_alias_sequence(
208 const TSLanguage *self,
209 uint32_t production_id
210) {
211 return production_id ?
212 &self->alias_sequences[production_id * self->max_alias_sequence_length] :
213 NULL;
214}
215
216static inline TSSymbol ts_language_alias_at(
217 const TSLanguage *self,
218 uint32_t production_id,
219 uint32_t child_index
220) {
221 return production_id ?
222 self->alias_sequences[production_id * self->max_alias_sequence_length + child_index] :
223 0;
224}
225
226static inline void ts_language_field_map(
227 const TSLanguage *self,
228 uint32_t production_id,
229 const TSFieldMapEntry **start,
230 const TSFieldMapEntry **end
231) {
232 if (self->field_count == 0) {
233 *start = NULL;
234 *end = NULL;
235 return;
236 }
237
238 TSFieldMapSlice slice = self->field_map_slices[production_id];
239 *start = &self->field_map_entries[slice.index];
240 *end = &self->field_map_entries[slice.index] + slice.length;
241}
242
243static inline void ts_language_aliases_for_symbol(
244 const TSLanguage *self,
245 TSSymbol original_symbol,
246 const TSSymbol **start,
247 const TSSymbol **end
248) {
249 *start = &self->public_symbol_map[original_symbol];
250 *end = *start + 1;
251
252 unsigned idx = 0;
253 for (;;) {
254 TSSymbol symbol = self->alias_map[idx++];
255 if (symbol == 0 || symbol > original_symbol) break;
256 uint16_t count = self->alias_map[idx++];
257 if (symbol == original_symbol) {
258 *start = &self->alias_map[idx];
259 *end = &self->alias_map[idx + count];
260 break;
261 }
262 idx += count;
263 }
264}
265
266static inline void ts_language_write_symbol_as_dot_string(
267 const TSLanguage *self,
268 FILE *f,
269 TSSymbol symbol
270) {
271 const char *name = ts_language_symbol_name(self, symbol);
272 for (const char *chr = name; *chr; chr++) {
273 switch (*chr) {
274 case '"':
275 case '\\':
276 fputc('\\', f);
277 fputc(*chr, f);
278 break;
279 case '\n':
280 fputs("\\n", f);
281 break;
282 case '\t':
283 fputs("\\t", f);
284 break;
285 default:
286 fputc(*chr, f);
287 break;
288 }
289 }
290}
291
292#ifdef __cplusplus
293}
294#endif
295
296#endif // TREE_SITTER_LANGUAGE_H_