@ast-grep/lang-elixir 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +24 -0
- package/index.d.ts +10 -0
- package/index.js +9 -0
- package/package.json +46 -0
- package/postinstall.js +4 -0
- package/prebuilds/prebuild-Linux-X64/parser.so +0 -0
- package/prebuilds/prebuild-Windows-X64/parser.so +0 -0
- package/prebuilds/prebuild-macOS-ARM64/parser.so +0 -0
- package/src/grammar.json +6760 -0
- package/src/node-types.json +3497 -0
- package/src/parser.c +428397 -0
- package/src/scanner.c +638 -0
- package/src/tree_sitter/alloc.h +54 -0
- package/src/tree_sitter/array.h +290 -0
- package/src/tree_sitter/parser.h +266 -0
- package/type.d.ts +2777 -0
package/src/scanner.c
ADDED
|
@@ -0,0 +1,638 @@
|
|
|
1
|
+
#include "tree_sitter/parser.h"
|
|
2
|
+
|
|
3
|
+
// See references in grammar.externals
|
|
4
|
+
enum TokenType {
|
|
5
|
+
QUOTED_CONTENT_I_SINGLE,
|
|
6
|
+
QUOTED_CONTENT_I_DOUBLE,
|
|
7
|
+
QUOTED_CONTENT_I_HEREDOC_SINGLE,
|
|
8
|
+
QUOTED_CONTENT_I_HEREDOC_DOUBLE,
|
|
9
|
+
QUOTED_CONTENT_I_PARENTHESIS,
|
|
10
|
+
QUOTED_CONTENT_I_CURLY,
|
|
11
|
+
QUOTED_CONTENT_I_SQUARE,
|
|
12
|
+
QUOTED_CONTENT_I_ANGLE,
|
|
13
|
+
QUOTED_CONTENT_I_BAR,
|
|
14
|
+
QUOTED_CONTENT_I_SLASH,
|
|
15
|
+
QUOTED_CONTENT_SINGLE,
|
|
16
|
+
QUOTED_CONTENT_DOUBLE,
|
|
17
|
+
QUOTED_CONTENT_HEREDOC_SINGLE,
|
|
18
|
+
QUOTED_CONTENT_HEREDOC_DOUBLE,
|
|
19
|
+
QUOTED_CONTENT_PARENTHESIS,
|
|
20
|
+
QUOTED_CONTENT_CURLY,
|
|
21
|
+
QUOTED_CONTENT_SQUARE,
|
|
22
|
+
QUOTED_CONTENT_ANGLE,
|
|
23
|
+
QUOTED_CONTENT_BAR,
|
|
24
|
+
QUOTED_CONTENT_SLASH,
|
|
25
|
+
|
|
26
|
+
NEWLINE_BEFORE_DO,
|
|
27
|
+
NEWLINE_BEFORE_BINARY_OPERATOR,
|
|
28
|
+
NEWLINE_BEFORE_COMMENT,
|
|
29
|
+
|
|
30
|
+
BEFORE_UNARY_OPERATOR,
|
|
31
|
+
|
|
32
|
+
NOT_IN,
|
|
33
|
+
|
|
34
|
+
QUOTED_ATOM_START
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
static inline void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
|
|
38
|
+
|
|
39
|
+
static inline void skip(TSLexer *lexer) { lexer->advance(lexer, true); }
|
|
40
|
+
|
|
41
|
+
// Note: some checks require several lexer steps of lookahead
|
|
42
|
+
// and alter its state, for these we use names check_*
|
|
43
|
+
|
|
44
|
+
static inline bool is_whitespace(int32_t c) {
|
|
45
|
+
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static inline bool is_inline_whitespace(int32_t c) {
|
|
49
|
+
return c == ' ' || c == '\t';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static inline bool is_newline(int32_t c) {
|
|
53
|
+
// Note: this implies \r\n is treated as two line breaks,
|
|
54
|
+
// but in our case it's fine, since multiple line breaks
|
|
55
|
+
// make no difference
|
|
56
|
+
return c == '\n' || c == '\r';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
static inline bool is_digit(int32_t c) { return '0' <= c && c <= '9'; }
|
|
60
|
+
|
|
61
|
+
static inline bool check_keyword_end(TSLexer *lexer) {
|
|
62
|
+
if (lexer->lookahead == ':') {
|
|
63
|
+
advance(lexer);
|
|
64
|
+
return is_whitespace(lexer->lookahead);
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static bool check_operator_end(TSLexer *lexer) {
|
|
70
|
+
// Keyword
|
|
71
|
+
if (lexer->lookahead == ':') {
|
|
72
|
+
return !check_keyword_end(lexer);
|
|
73
|
+
}
|
|
74
|
+
while (is_inline_whitespace(lexer->lookahead)) {
|
|
75
|
+
advance(lexer);
|
|
76
|
+
}
|
|
77
|
+
// Operator identifier with arity
|
|
78
|
+
if (lexer->lookahead == '/') {
|
|
79
|
+
advance(lexer);
|
|
80
|
+
while (is_whitespace(lexer->lookahead)) {
|
|
81
|
+
advance(lexer);
|
|
82
|
+
}
|
|
83
|
+
if (is_digit(lexer->lookahead)) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const char token_terminators[] = {
|
|
92
|
+
// Operator starts
|
|
93
|
+
'@', '.', '+', '-', '^', '-', '*', '/', '<', '>', '|', '~', '=', '&', '\\',
|
|
94
|
+
'%',
|
|
95
|
+
// Delimiters
|
|
96
|
+
'{', '}', '[', ']', '(', ')', '"', '\'',
|
|
97
|
+
// Separators
|
|
98
|
+
',', ';',
|
|
99
|
+
// Comment
|
|
100
|
+
'#'};
|
|
101
|
+
|
|
102
|
+
const uint8_t token_terminators_length =
|
|
103
|
+
sizeof(token_terminators) / sizeof(char);
|
|
104
|
+
|
|
105
|
+
// Note: this is a heuristic as we only use this to distinguish word
|
|
106
|
+
// operators and we don't want to include complex Unicode ranges
|
|
107
|
+
static inline bool is_token_end(int32_t c) {
|
|
108
|
+
for (uint8_t i = 0; i < token_terminators_length; i++) {
|
|
109
|
+
if (c == token_terminators[i]) {
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return is_whitespace(c);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
typedef struct {
|
|
118
|
+
const enum TokenType token_type;
|
|
119
|
+
const bool supports_interpol;
|
|
120
|
+
const int32_t end_delimiter;
|
|
121
|
+
const uint8_t delimiter_length;
|
|
122
|
+
} QuotedContentInfo;
|
|
123
|
+
|
|
124
|
+
const QuotedContentInfo quoted_content_infos[] = {
|
|
125
|
+
{QUOTED_CONTENT_I_SINGLE, true, '\'', 1},
|
|
126
|
+
{QUOTED_CONTENT_I_DOUBLE, true, '"', 1},
|
|
127
|
+
{QUOTED_CONTENT_I_HEREDOC_SINGLE, true, '\'', 3},
|
|
128
|
+
{QUOTED_CONTENT_I_HEREDOC_DOUBLE, true, '"', 3},
|
|
129
|
+
{QUOTED_CONTENT_I_PARENTHESIS, true, ')', 1},
|
|
130
|
+
{QUOTED_CONTENT_I_CURLY, true, '}', 1},
|
|
131
|
+
{QUOTED_CONTENT_I_SQUARE, true, ']', 1},
|
|
132
|
+
{QUOTED_CONTENT_I_ANGLE, true, '>', 1},
|
|
133
|
+
{QUOTED_CONTENT_I_BAR, true, '|', 1},
|
|
134
|
+
{QUOTED_CONTENT_I_SLASH, true, '/', 1},
|
|
135
|
+
{QUOTED_CONTENT_SINGLE, false, '\'', 1},
|
|
136
|
+
{QUOTED_CONTENT_DOUBLE, false, '"', 1},
|
|
137
|
+
{QUOTED_CONTENT_HEREDOC_SINGLE, false, '\'', 3},
|
|
138
|
+
{QUOTED_CONTENT_HEREDOC_DOUBLE, false, '"', 3},
|
|
139
|
+
{QUOTED_CONTENT_PARENTHESIS, false, ')', 1},
|
|
140
|
+
{QUOTED_CONTENT_CURLY, false, '}', 1},
|
|
141
|
+
{QUOTED_CONTENT_SQUARE, false, ']', 1},
|
|
142
|
+
{QUOTED_CONTENT_ANGLE, false, '>', 1},
|
|
143
|
+
{QUOTED_CONTENT_BAR, false, '|', 1},
|
|
144
|
+
{QUOTED_CONTENT_SLASH, false, '/', 1},
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const uint8_t quoted_content_infos_length =
|
|
148
|
+
sizeof(quoted_content_infos) / sizeof(QuotedContentInfo);
|
|
149
|
+
|
|
150
|
+
static inline int8_t find_quoted_token_info(const bool *valid_symbols) {
|
|
151
|
+
// Quoted tokens are mutually exclusive and only one should be valid
|
|
152
|
+
// at a time. If multiple are valid it means we parse an arbitrary
|
|
153
|
+
// code outside quotes, in which case we don't want to tokenize it as
|
|
154
|
+
// quoted content.
|
|
155
|
+
if (valid_symbols[QUOTED_CONTENT_I_SINGLE] &&
|
|
156
|
+
valid_symbols[QUOTED_CONTENT_I_DOUBLE]) {
|
|
157
|
+
return -1;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
for (uint8_t i = 0; i < quoted_content_infos_length; i++) {
|
|
161
|
+
if (valid_symbols[quoted_content_infos[i].token_type]) {
|
|
162
|
+
return i;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return -1;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
static bool scan_quoted_content(TSLexer *lexer, const QuotedContentInfo *info) {
|
|
170
|
+
lexer->result_symbol = info->token_type;
|
|
171
|
+
|
|
172
|
+
bool is_heredoc = (info->delimiter_length == 3);
|
|
173
|
+
|
|
174
|
+
for (bool has_content = false; true; has_content = true) {
|
|
175
|
+
bool newline = false;
|
|
176
|
+
|
|
177
|
+
if (is_newline(lexer->lookahead)) {
|
|
178
|
+
advance(lexer);
|
|
179
|
+
|
|
180
|
+
has_content = true;
|
|
181
|
+
newline = true;
|
|
182
|
+
|
|
183
|
+
while (is_whitespace(lexer->lookahead)) {
|
|
184
|
+
advance(lexer);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
lexer->mark_end(lexer);
|
|
189
|
+
|
|
190
|
+
if (lexer->lookahead == info->end_delimiter) {
|
|
191
|
+
uint8_t length = 1;
|
|
192
|
+
|
|
193
|
+
while (length < info->delimiter_length) {
|
|
194
|
+
advance(lexer);
|
|
195
|
+
if (lexer->lookahead == info->end_delimiter) {
|
|
196
|
+
length++;
|
|
197
|
+
} else {
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (length == info->delimiter_length && (!is_heredoc || newline)) {
|
|
203
|
+
return has_content;
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
if (lexer->lookahead == '#') {
|
|
207
|
+
advance(lexer);
|
|
208
|
+
if (info->supports_interpol && lexer->lookahead == '{') {
|
|
209
|
+
return has_content;
|
|
210
|
+
}
|
|
211
|
+
} else if (lexer->lookahead == '\\') {
|
|
212
|
+
advance(lexer);
|
|
213
|
+
if (is_heredoc && lexer->lookahead == '\n') {
|
|
214
|
+
// We need to know about the newline to correctly recognise
|
|
215
|
+
// heredoc end delimiter, so we intentionally ignore
|
|
216
|
+
// escaping
|
|
217
|
+
} else if (info->supports_interpol ||
|
|
218
|
+
lexer->lookahead == info->end_delimiter) {
|
|
219
|
+
return has_content;
|
|
220
|
+
}
|
|
221
|
+
} else if (lexer->lookahead == '\0') {
|
|
222
|
+
// If we reached the end of the file, this means there is no
|
|
223
|
+
// end delimiter, so the syntax is invalid. In that case we
|
|
224
|
+
// want to treat all the scanned content as quoted content.
|
|
225
|
+
return has_content;
|
|
226
|
+
} else {
|
|
227
|
+
advance(lexer);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
static bool scan_newline(TSLexer *lexer, const bool *valid_symbols) {
|
|
236
|
+
advance(lexer);
|
|
237
|
+
|
|
238
|
+
while (is_whitespace(lexer->lookahead)) {
|
|
239
|
+
advance(lexer);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Note we include all the whitespace after newline, so that the
|
|
243
|
+
// parser doesn't have to go through it again
|
|
244
|
+
lexer->mark_end(lexer);
|
|
245
|
+
|
|
246
|
+
if (lexer->lookahead == '#') {
|
|
247
|
+
lexer->result_symbol = NEWLINE_BEFORE_COMMENT;
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (lexer->lookahead == 'd' && valid_symbols[NEWLINE_BEFORE_DO]) {
|
|
252
|
+
lexer->result_symbol = NEWLINE_BEFORE_DO;
|
|
253
|
+
advance(lexer);
|
|
254
|
+
if (lexer->lookahead == 'o') {
|
|
255
|
+
advance(lexer);
|
|
256
|
+
return is_token_end(lexer->lookahead);
|
|
257
|
+
}
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (valid_symbols[NEWLINE_BEFORE_BINARY_OPERATOR]) {
|
|
262
|
+
lexer->result_symbol = NEWLINE_BEFORE_BINARY_OPERATOR;
|
|
263
|
+
|
|
264
|
+
// &&, &&&
|
|
265
|
+
if (lexer->lookahead == '&') {
|
|
266
|
+
advance(lexer);
|
|
267
|
+
if (lexer->lookahead == '&') {
|
|
268
|
+
advance(lexer);
|
|
269
|
+
if (lexer->lookahead == '&') {
|
|
270
|
+
advance(lexer);
|
|
271
|
+
return check_operator_end(lexer);
|
|
272
|
+
} else {
|
|
273
|
+
return check_operator_end(lexer);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// =, ==, ===, =~, =>
|
|
277
|
+
} else if (lexer->lookahead == '=') {
|
|
278
|
+
advance(lexer);
|
|
279
|
+
if (lexer->lookahead == '=') {
|
|
280
|
+
advance(lexer);
|
|
281
|
+
if (lexer->lookahead == '=') {
|
|
282
|
+
advance(lexer);
|
|
283
|
+
return check_operator_end(lexer);
|
|
284
|
+
} else {
|
|
285
|
+
return check_operator_end(lexer);
|
|
286
|
+
}
|
|
287
|
+
} else if (lexer->lookahead == '~') {
|
|
288
|
+
advance(lexer);
|
|
289
|
+
return check_operator_end(lexer);
|
|
290
|
+
} else if (lexer->lookahead == '>') {
|
|
291
|
+
advance(lexer);
|
|
292
|
+
return check_operator_end(lexer);
|
|
293
|
+
} else {
|
|
294
|
+
return check_operator_end(lexer);
|
|
295
|
+
}
|
|
296
|
+
// ::
|
|
297
|
+
} else if (lexer->lookahead == ':') {
|
|
298
|
+
advance(lexer);
|
|
299
|
+
if (lexer->lookahead == ':') {
|
|
300
|
+
advance(lexer);
|
|
301
|
+
// Ignore ::: atom
|
|
302
|
+
if (lexer->lookahead == ':')
|
|
303
|
+
return false;
|
|
304
|
+
return check_operator_end(lexer);
|
|
305
|
+
}
|
|
306
|
+
// ++, +++
|
|
307
|
+
} else if (lexer->lookahead == '+') {
|
|
308
|
+
advance(lexer);
|
|
309
|
+
if (lexer->lookahead == '+') {
|
|
310
|
+
advance(lexer);
|
|
311
|
+
if (lexer->lookahead == '+') {
|
|
312
|
+
advance(lexer);
|
|
313
|
+
return check_operator_end(lexer);
|
|
314
|
+
} else {
|
|
315
|
+
return check_operator_end(lexer);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// --, ---, ->
|
|
319
|
+
} else if (lexer->lookahead == '-') {
|
|
320
|
+
advance(lexer);
|
|
321
|
+
if (lexer->lookahead == '-') {
|
|
322
|
+
advance(lexer);
|
|
323
|
+
if (lexer->lookahead == '-') {
|
|
324
|
+
advance(lexer);
|
|
325
|
+
return check_operator_end(lexer);
|
|
326
|
+
} else {
|
|
327
|
+
return check_operator_end(lexer);
|
|
328
|
+
}
|
|
329
|
+
} else if (lexer->lookahead == '>') {
|
|
330
|
+
advance(lexer);
|
|
331
|
+
return check_operator_end(lexer);
|
|
332
|
+
}
|
|
333
|
+
// <, <=, <-, <>, <~, <~>, <|>, <<<, <<~
|
|
334
|
+
} else if (lexer->lookahead == '<') {
|
|
335
|
+
advance(lexer);
|
|
336
|
+
if (lexer->lookahead == '=' || lexer->lookahead == '-' ||
|
|
337
|
+
lexer->lookahead == '>') {
|
|
338
|
+
advance(lexer);
|
|
339
|
+
return check_operator_end(lexer);
|
|
340
|
+
} else if (lexer->lookahead == '~') {
|
|
341
|
+
advance(lexer);
|
|
342
|
+
if (lexer->lookahead == '>') {
|
|
343
|
+
advance(lexer);
|
|
344
|
+
return check_operator_end(lexer);
|
|
345
|
+
} else {
|
|
346
|
+
return check_operator_end(lexer);
|
|
347
|
+
}
|
|
348
|
+
} else if (lexer->lookahead == '|') {
|
|
349
|
+
advance(lexer);
|
|
350
|
+
if (lexer->lookahead == '>') {
|
|
351
|
+
advance(lexer);
|
|
352
|
+
return check_operator_end(lexer);
|
|
353
|
+
}
|
|
354
|
+
} else if (lexer->lookahead == '<') {
|
|
355
|
+
advance(lexer);
|
|
356
|
+
if (lexer->lookahead == '<' || lexer->lookahead == '~') {
|
|
357
|
+
advance(lexer);
|
|
358
|
+
return check_operator_end(lexer);
|
|
359
|
+
}
|
|
360
|
+
} else {
|
|
361
|
+
return check_operator_end(lexer);
|
|
362
|
+
}
|
|
363
|
+
// >, >=, >>>
|
|
364
|
+
} else if (lexer->lookahead == '>') {
|
|
365
|
+
advance(lexer);
|
|
366
|
+
if (lexer->lookahead == '=') {
|
|
367
|
+
advance(lexer);
|
|
368
|
+
return check_operator_end(lexer);
|
|
369
|
+
} else if (lexer->lookahead == '>') {
|
|
370
|
+
advance(lexer);
|
|
371
|
+
if (lexer->lookahead == '>') {
|
|
372
|
+
advance(lexer);
|
|
373
|
+
return check_operator_end(lexer);
|
|
374
|
+
}
|
|
375
|
+
} else {
|
|
376
|
+
return check_operator_end(lexer);
|
|
377
|
+
}
|
|
378
|
+
// ^^^
|
|
379
|
+
} else if (lexer->lookahead == '^') {
|
|
380
|
+
advance(lexer);
|
|
381
|
+
if (lexer->lookahead == '^') {
|
|
382
|
+
advance(lexer);
|
|
383
|
+
if (lexer->lookahead == '^') {
|
|
384
|
+
advance(lexer);
|
|
385
|
+
return check_operator_end(lexer);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
// !=, !==
|
|
389
|
+
} else if (lexer->lookahead == '!') {
|
|
390
|
+
advance(lexer);
|
|
391
|
+
if (lexer->lookahead == '=') {
|
|
392
|
+
advance(lexer);
|
|
393
|
+
if (lexer->lookahead == '=') {
|
|
394
|
+
advance(lexer);
|
|
395
|
+
return check_operator_end(lexer);
|
|
396
|
+
} else {
|
|
397
|
+
return check_operator_end(lexer);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
// ~>, ~>>
|
|
401
|
+
} else if (lexer->lookahead == '~') {
|
|
402
|
+
advance(lexer);
|
|
403
|
+
if (lexer->lookahead == '>') {
|
|
404
|
+
advance(lexer);
|
|
405
|
+
if (lexer->lookahead == '>') {
|
|
406
|
+
advance(lexer);
|
|
407
|
+
return check_operator_end(lexer);
|
|
408
|
+
} else {
|
|
409
|
+
return check_operator_end(lexer);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
// |, ||, |||, |>
|
|
413
|
+
} else if (lexer->lookahead == '|') {
|
|
414
|
+
advance(lexer);
|
|
415
|
+
if (lexer->lookahead == '|') {
|
|
416
|
+
advance(lexer);
|
|
417
|
+
if (lexer->lookahead == '|') {
|
|
418
|
+
advance(lexer);
|
|
419
|
+
return check_operator_end(lexer);
|
|
420
|
+
} else {
|
|
421
|
+
return check_operator_end(lexer);
|
|
422
|
+
}
|
|
423
|
+
} else if (lexer->lookahead == '>') {
|
|
424
|
+
advance(lexer);
|
|
425
|
+
return check_operator_end(lexer);
|
|
426
|
+
} else {
|
|
427
|
+
return check_operator_end(lexer);
|
|
428
|
+
}
|
|
429
|
+
// *, **
|
|
430
|
+
} else if (lexer->lookahead == '*') {
|
|
431
|
+
advance(lexer);
|
|
432
|
+
if (lexer->lookahead == '*') {
|
|
433
|
+
advance(lexer);
|
|
434
|
+
return check_operator_end(lexer);
|
|
435
|
+
} else {
|
|
436
|
+
return check_operator_end(lexer);
|
|
437
|
+
}
|
|
438
|
+
// / //
|
|
439
|
+
} else if (lexer->lookahead == '/') {
|
|
440
|
+
advance(lexer);
|
|
441
|
+
if (lexer->lookahead == '/') {
|
|
442
|
+
advance(lexer);
|
|
443
|
+
return check_operator_end(lexer);
|
|
444
|
+
} else {
|
|
445
|
+
return check_operator_end(lexer);
|
|
446
|
+
}
|
|
447
|
+
// ., ..
|
|
448
|
+
} else if (lexer->lookahead == '.') {
|
|
449
|
+
advance(lexer);
|
|
450
|
+
if (lexer->lookahead == '.') {
|
|
451
|
+
advance(lexer);
|
|
452
|
+
// Ignore ... identifier
|
|
453
|
+
if (lexer->lookahead == '.')
|
|
454
|
+
return false;
|
|
455
|
+
return check_operator_end(lexer);
|
|
456
|
+
} else {
|
|
457
|
+
return check_operator_end(lexer);
|
|
458
|
+
}
|
|
459
|
+
// double slash
|
|
460
|
+
} else if (lexer->lookahead == '\\') {
|
|
461
|
+
advance(lexer);
|
|
462
|
+
if (lexer->lookahead == '\\') {
|
|
463
|
+
advance(lexer);
|
|
464
|
+
return check_operator_end(lexer);
|
|
465
|
+
}
|
|
466
|
+
// when
|
|
467
|
+
} else if (lexer->lookahead == 'w') {
|
|
468
|
+
advance(lexer);
|
|
469
|
+
if (lexer->lookahead == 'h') {
|
|
470
|
+
advance(lexer);
|
|
471
|
+
if (lexer->lookahead == 'e') {
|
|
472
|
+
advance(lexer);
|
|
473
|
+
if (lexer->lookahead == 'n') {
|
|
474
|
+
advance(lexer);
|
|
475
|
+
return is_token_end(lexer->lookahead) && check_operator_end(lexer);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
// and
|
|
480
|
+
} else if (lexer->lookahead == 'a') {
|
|
481
|
+
advance(lexer);
|
|
482
|
+
if (lexer->lookahead == 'n') {
|
|
483
|
+
advance(lexer);
|
|
484
|
+
if (lexer->lookahead == 'd') {
|
|
485
|
+
advance(lexer);
|
|
486
|
+
return is_token_end(lexer->lookahead) && check_operator_end(lexer);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
// or
|
|
490
|
+
} else if (lexer->lookahead == 'o') {
|
|
491
|
+
advance(lexer);
|
|
492
|
+
if (lexer->lookahead == 'r') {
|
|
493
|
+
advance(lexer);
|
|
494
|
+
return is_token_end(lexer->lookahead) && check_operator_end(lexer);
|
|
495
|
+
}
|
|
496
|
+
// in
|
|
497
|
+
} else if (lexer->lookahead == 'i') {
|
|
498
|
+
advance(lexer);
|
|
499
|
+
if (lexer->lookahead == 'n') {
|
|
500
|
+
advance(lexer);
|
|
501
|
+
return is_token_end(lexer->lookahead) && check_operator_end(lexer);
|
|
502
|
+
}
|
|
503
|
+
// not in
|
|
504
|
+
} else if (lexer->lookahead == 'n') {
|
|
505
|
+
advance(lexer);
|
|
506
|
+
if (lexer->lookahead == 'o') {
|
|
507
|
+
advance(lexer);
|
|
508
|
+
if (lexer->lookahead == 't') {
|
|
509
|
+
advance(lexer);
|
|
510
|
+
while (is_inline_whitespace(lexer->lookahead)) {
|
|
511
|
+
advance(lexer);
|
|
512
|
+
}
|
|
513
|
+
if (lexer->lookahead == 'i') {
|
|
514
|
+
advance(lexer);
|
|
515
|
+
if (lexer->lookahead == 'n') {
|
|
516
|
+
advance(lexer);
|
|
517
|
+
return is_token_end(lexer->lookahead) &&
|
|
518
|
+
check_operator_end(lexer);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
return false;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
static bool scan(TSLexer *lexer, const bool *valid_symbols) {
|
|
530
|
+
int8_t quoted_content_info_idx = find_quoted_token_info(valid_symbols);
|
|
531
|
+
|
|
532
|
+
// Quoted content, which matches any character except for close
|
|
533
|
+
// delimiters, escapes and interpolations
|
|
534
|
+
if (quoted_content_info_idx != -1) {
|
|
535
|
+
const QuotedContentInfo info =
|
|
536
|
+
quoted_content_infos[quoted_content_info_idx];
|
|
537
|
+
return scan_quoted_content(lexer, &info);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
bool skipped_whitespace = false;
|
|
541
|
+
|
|
542
|
+
while (is_inline_whitespace(lexer->lookahead)) {
|
|
543
|
+
skipped_whitespace = true;
|
|
544
|
+
skip(lexer);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Newline, which is either tokenized as a special newline or ignored
|
|
548
|
+
if (is_newline(lexer->lookahead) &&
|
|
549
|
+
(valid_symbols[NEWLINE_BEFORE_DO] ||
|
|
550
|
+
valid_symbols[NEWLINE_BEFORE_BINARY_OPERATOR] ||
|
|
551
|
+
valid_symbols[NEWLINE_BEFORE_COMMENT])) {
|
|
552
|
+
return scan_newline(lexer, valid_symbols);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// before unary +
|
|
556
|
+
if (lexer->lookahead == '+') {
|
|
557
|
+
if (skipped_whitespace && valid_symbols[BEFORE_UNARY_OPERATOR]) {
|
|
558
|
+
lexer->mark_end(lexer);
|
|
559
|
+
advance(lexer);
|
|
560
|
+
if (lexer->lookahead == '+' || lexer->lookahead == ':' ||
|
|
561
|
+
lexer->lookahead == '/') {
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
if (is_whitespace(lexer->lookahead)) {
|
|
565
|
+
return false;
|
|
566
|
+
}
|
|
567
|
+
lexer->result_symbol = BEFORE_UNARY_OPERATOR;
|
|
568
|
+
return true;
|
|
569
|
+
}
|
|
570
|
+
// before unary -
|
|
571
|
+
} else if (lexer->lookahead == '-') {
|
|
572
|
+
if (skipped_whitespace && valid_symbols[BEFORE_UNARY_OPERATOR]) {
|
|
573
|
+
lexer->mark_end(lexer);
|
|
574
|
+
lexer->result_symbol = BEFORE_UNARY_OPERATOR;
|
|
575
|
+
advance(lexer);
|
|
576
|
+
if (lexer->lookahead == '-' || lexer->lookahead == '>' ||
|
|
577
|
+
lexer->lookahead == ':' || lexer->lookahead == '/') {
|
|
578
|
+
return false;
|
|
579
|
+
}
|
|
580
|
+
if (is_whitespace(lexer->lookahead)) {
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
return true;
|
|
584
|
+
}
|
|
585
|
+
// not in
|
|
586
|
+
} else if (lexer->lookahead == 'n') {
|
|
587
|
+
if (valid_symbols[NOT_IN]) {
|
|
588
|
+
lexer->result_symbol = NOT_IN;
|
|
589
|
+
advance(lexer);
|
|
590
|
+
if (lexer->lookahead == 'o') {
|
|
591
|
+
advance(lexer);
|
|
592
|
+
if (lexer->lookahead == 't') {
|
|
593
|
+
advance(lexer);
|
|
594
|
+
while (is_inline_whitespace(lexer->lookahead)) {
|
|
595
|
+
advance(lexer);
|
|
596
|
+
}
|
|
597
|
+
if (lexer->lookahead == 'i') {
|
|
598
|
+
advance(lexer);
|
|
599
|
+
if (lexer->lookahead == 'n') {
|
|
600
|
+
advance(lexer);
|
|
601
|
+
return is_token_end(lexer->lookahead);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
// quoted atom start
|
|
608
|
+
} else if (lexer->lookahead == ':') {
|
|
609
|
+
if (valid_symbols[QUOTED_ATOM_START]) {
|
|
610
|
+
advance(lexer);
|
|
611
|
+
lexer->mark_end(lexer);
|
|
612
|
+
lexer->result_symbol = QUOTED_ATOM_START;
|
|
613
|
+
if (lexer->lookahead == '"' || lexer->lookahead == '\'') {
|
|
614
|
+
return true;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
return false;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
void *tree_sitter_elixir_external_scanner_create() { return NULL; }
|
|
623
|
+
|
|
624
|
+
bool tree_sitter_elixir_external_scanner_scan(void *payload, TSLexer *lexer,
|
|
625
|
+
const bool *valid_symbols) {
|
|
626
|
+
return scan(lexer, valid_symbols);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
unsigned tree_sitter_elixir_external_scanner_serialize(void *payload,
|
|
630
|
+
char *buffer) {
|
|
631
|
+
return 0;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
void tree_sitter_elixir_external_scanner_deserialize(void *payload,
|
|
635
|
+
const char *buffer,
|
|
636
|
+
unsigned length) {}
|
|
637
|
+
|
|
638
|
+
void tree_sitter_elixir_external_scanner_destroy(void *payload) {}
|
|
@@ -0,0 +1,54 @@
|
|
|
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_
|