tree-sitter-sed 0.1.0

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.
@@ -0,0 +1,3142 @@
1
+ #ifndef TREE_SITTER_POSIX_SED_COMMON_SCANNER_H_
2
+ #define TREE_SITTER_POSIX_SED_COMMON_SCANNER_H_
3
+
4
+ #ifndef SED_REGEX_EXTENDED
5
+ #error "SED_REGEX_EXTENDED must be defined before including scanner.h"
6
+ #endif
7
+ #include "tree_sitter/alloc.h"
8
+ #include "tree_sitter/parser.h"
9
+
10
+ #include <stdbool.h>
11
+ #include <stdint.h>
12
+
13
+ enum TokenType {
14
+ REGEX_ADDRESS_START,
15
+ ESCAPED_REGEX_ADDRESS_START,
16
+ REGEX_ADDRESS_END,
17
+ SUBSTITUTE_START,
18
+ SUBSTITUTE_MIDDLE,
19
+ SUBSTITUTE_END,
20
+ TRANSLATE_START,
21
+ TRANSLATE_MIDDLE,
22
+ TRANSLATE_END,
23
+ REGEX_LITERAL,
24
+ REGEX_BEGINNING_ANCHOR,
25
+ REGEX_END_ANCHOR,
26
+ REGEX_PERIOD,
27
+ REGEX_QUOTED_ESCAPE,
28
+ REGEX_NEWLINE_ESCAPE,
29
+ REGEX_ESCAPED_DELIMITER,
30
+ REGEX_SPECIAL_ESCAPED_DELIMITER,
31
+ REGEX_GROUP_OPEN,
32
+ REGEX_GROUP_CLOSE,
33
+ REGEX_UNCLOSED_GROUP,
34
+ #if !SED_REGEX_EXTENDED
35
+ REGEX_UNMATCHED_GROUP_CLOSE,
36
+ REGEX_BRE_VERTICAL_LINE_ESCAPE,
37
+ REGEX_BRE_QUESTION_MARK_ESCAPE,
38
+ REGEX_BRE_PLUS_ESCAPE,
39
+ REGEX_BRE_SUBEXPRESSION_CARET,
40
+ REGEX_BRE_SUBEXPRESSION_DOLLAR,
41
+ BRE_VERTICAL_LINE_ESCAPE_MARKER,
42
+ BRE_QUESTION_MARK_ESCAPE_MARKER,
43
+ BRE_PLUS_ESCAPE_MARKER,
44
+ REGEX_UNMATCHED_INTERVAL_CLOSE,
45
+ UNMATCHED_INTERVAL_CLOSE_MARKER,
46
+ #endif
47
+ #if SED_REGEX_EXTENDED
48
+ REGEX_ALTERNATION_OPERATOR,
49
+ #endif
50
+ REGEX_LEADING_DUPLICATION_MARKER,
51
+ REGEX_ADJACENT_DUPLICATION_MARKER,
52
+ REGEX_ZERO_OR_MORE,
53
+ #if SED_REGEX_EXTENDED
54
+ REGEX_ONE_OR_MORE,
55
+ REGEX_ZERO_OR_ONE,
56
+ REGEX_REPETITION_MODIFIER,
57
+ #endif
58
+ REGEX_INTERVAL_OPEN,
59
+ REGEX_DUP_COUNT,
60
+ REGEX_INTERVAL_SEPARATOR,
61
+ REGEX_INTERVAL_CLOSE,
62
+ #if !SED_REGEX_EXTENDED
63
+ REGEX_BACKREFERENCE,
64
+ #endif
65
+ REGEX_INVALID_INTERVAL,
66
+ REGEX_NONPORTABLE_ESCAPE,
67
+ REGEX_INCOMPLETE_ESCAPE,
68
+ REGEX_BRACKET_OPEN,
69
+ REGEX_BRACKET_CLOSE,
70
+ REGEX_BRACKET_LITERAL,
71
+ REGEX_BRACKET_NEGATION,
72
+ REGEX_BRACKET_HYPHEN,
73
+ REGEX_BRACKET_RANGE_END_HYPHEN,
74
+ REGEX_BRACKET_TRAILING_HYPHEN,
75
+ REGEX_OPEN_COLON,
76
+ REGEX_CLASS_NAME,
77
+ REGEX_COLON_CLOSE,
78
+ REGEX_OPEN_DOT,
79
+ REGEX_COLL_ELEM_SINGLE,
80
+ REGEX_COLL_ELEM_MULTI,
81
+ REGEX_META_CHAR,
82
+ REGEX_DOT_CLOSE,
83
+ REGEX_OPEN_EQUAL,
84
+ REGEX_EQUAL_CLOSE,
85
+ REGEX_MALFORMED_BRACKET_TERM,
86
+ REGEX_SHARED_RANGE_ENDPOINT,
87
+ AMBIGUOUS_BRACKET_EXPRESSION_MARKER,
88
+ MISSING_BRACKET_LIST_MARKER,
89
+ UNCLOSED_BRACKET_EXPRESSION_MARKER,
90
+ NONPORTABLE_RANGE_START_MARKER,
91
+ NONPORTABLE_RANGE_END_MARKER,
92
+ REGEX_UNTERMINATED_ADDRESS,
93
+ REGEX_UNTERMINATED_SUBSTITUTE,
94
+ REPLACEMENT_LITERAL,
95
+ REPLACEMENT_MATCH_REFERENCE,
96
+ REPLACEMENT_BACKREFERENCE,
97
+ REPLACEMENT_ESCAPED_DELIMITER,
98
+ REPLACEMENT_AMPERSAND_ESCAPED_DELIMITER,
99
+ REPLACEMENT_ESCAPE_SEQUENCE,
100
+ REPLACEMENT_NONPORTABLE_ESCAPE,
101
+ REPLACEMENT_ESCAPED_NEWLINE,
102
+ REPLACEMENT_INCOMPLETE_ESCAPE,
103
+ REPLACEMENT_UNTERMINATED,
104
+ TRANSLATE_LITERAL,
105
+ TRANSLATE_ESCAPED_DELIMITER,
106
+ TRANSLATE_ESCAPE,
107
+ TRANSLATE_NONPORTABLE_ESCAPE,
108
+ TRANSLATE_INCOMPLETE_ESCAPE,
109
+ TRANSLATE_UNTERMINATED_SOURCE,
110
+ TRANSLATE_UNTERMINATED_DESTINATION,
111
+ INVALID_SUBSTITUTION_FLAG,
112
+ TEXT_COMMAND_START,
113
+ TEXT_LITERAL,
114
+ TEXT_BACKSLASH_ESCAPE,
115
+ TEXT_ESCAPED_NEWLINE,
116
+ TEXT_UNSPECIFIED_ESCAPE,
117
+ TEXT_LINE_END,
118
+ TEXT_EOF,
119
+ DEFAULT_OUTPUT_SUPPRESSION,
120
+ COMMENT_TEXT,
121
+ FILE_ARGUMENT,
122
+ SUBSTITUTION_WFILE_ARGUMENT,
123
+ LINE_WORD,
124
+ RIGHT_BRACE,
125
+ RESERVED_UNKNOWN_FUNCTION,
126
+ REGEX_INCOMPLETE_GROUP,
127
+ REGEX_INCOMPLETE_BRACKET_TERM,
128
+ REGEX_INCOMPLETE_INTERVAL,
129
+ REGEX_FORBIDDEN_NEWLINE_ESCAPE,
130
+ REGEX_LINE_UNTERMINATED_ADDRESS,
131
+ REGEX_LINE_UNTERMINATED_SUBSTITUTE,
132
+ REPLACEMENT_LINE_UNTERMINATED,
133
+ TRANSLATE_LINE_UNTERMINATED_SOURCE,
134
+ TRANSLATE_LINE_UNTERMINATED_DESTINATION,
135
+ OMITTED_ADDRESS_MARKER,
136
+ OMITTED_FIRST_ADDRESS_MARKER,
137
+ EMPTY_SUBEXPRESSION_MARKER,
138
+ MISSING_SUBEXPRESSION_MARKER,
139
+ #if SED_REGEX_EXTENDED
140
+ EMPTY_ALTERNATIVE_MARKER,
141
+ #endif
142
+ EXCESS_ADDRESSES_MARKER,
143
+ ADDITIONAL_ADDRESS_MARKER,
144
+ MISSING_FUNCTION_MARKER,
145
+ MISSING_LABEL_MARKER,
146
+ MISSING_RFILE_MARKER,
147
+ MISSING_WFILE_MARKER,
148
+ OMITTED_FILE_SEPARATOR_MARKER,
149
+ MISSING_TEXT_INTRODUCER_MARKER,
150
+ MISSING_TEXT_MARKER,
151
+ MISSING_COMMAND_SEPARATOR_MARKER,
152
+ BLANKS_AROUND_ADDRESS_SEPARATOR_MARKER,
153
+ MISSING_ADDRESS_SEPARATOR_MARKER,
154
+ DUPLICATE_NEGATION_MARKER,
155
+ MISSING_CLOSING_BRACE_MARKER,
156
+ MISSING_OPENING_DELIMITER_MARKER,
157
+ MISSING_SEPARATOR_BEFORE_UNMATCHED_BRACE_MARKER,
158
+ MISSING_SEPARATOR_AFTER_UNMATCHED_BRACE_MARKER,
159
+ NONCONFORMING_MISSING_FUNCTION_MARKER,
160
+ NONCONFORMING_MISSING_LABEL_MARKER,
161
+ NONCONFORMING_MISSING_RFILE_MARKER,
162
+ NONCONFORMING_MISSING_WFILE_MARKER,
163
+ NONCONFORMING_MISSING_TEXT_INTRODUCER_MARKER,
164
+ NONCONFORMING_MISSING_OPENING_DELIMITER_MARKER,
165
+ MISSING_SUBEXPRESSION_PLACEHOLDER_MARKER,
166
+ INCOMPLETE_BRACKET_LIST_MARKER,
167
+ INCOMPLETE_BRACKET_EXPRESSION_MARKER,
168
+ #if SED_REGEX_EXTENDED
169
+ INCOMPLETE_ALTERNATIVE_MARKER,
170
+ #endif
171
+ INCOMPLETE_COMMAND_SEPARATOR_MARKER,
172
+ ERROR_SENTINEL,
173
+ };
174
+
175
+ enum ScannerMode {
176
+ MODE_NONE,
177
+ MODE_REGEX_ADDRESS,
178
+ MODE_SUBSTITUTE_PATTERN,
179
+ MODE_SUBSTITUTE_REPLACEMENT,
180
+ MODE_TRANSLATE_SOURCE,
181
+ MODE_TRANSLATE_DESTINATION,
182
+ MODE_TEXT,
183
+ };
184
+
185
+ enum RegexState {
186
+ REGEX_OUTSIDE_BRACKET,
187
+ REGEX_BRACKET_FIRST,
188
+ REGEX_BRACKET_AFTER_CARET,
189
+ REGEX_BRACKET_BODY,
190
+ };
191
+
192
+ enum TextState {
193
+ TEXT_EMPTY,
194
+ TEXT_HAS_CONTENT,
195
+ TEXT_AFTER_ESCAPED_NEWLINE,
196
+ };
197
+
198
+ enum RegexIntervalState {
199
+ REGEX_INTERVAL_NONE,
200
+ REGEX_INTERVAL_EXPECT_MINIMUM,
201
+ REGEX_INTERVAL_AFTER_MINIMUM,
202
+ REGEX_INTERVAL_EXPECT_MAXIMUM,
203
+ REGEX_INTERVAL_AFTER_MAXIMUM,
204
+ };
205
+
206
+ enum RegexDuplicationState {
207
+ REGEX_DUPLICATION_NONE,
208
+ REGEX_AFTER_DUPLICATION_SYMBOL,
209
+ REGEX_AFTER_REPETITION_MODIFIER,
210
+ };
211
+
212
+ enum RegexBracketTermState {
213
+ REGEX_BRACKET_TERM_NONE,
214
+ REGEX_BRACKET_TERM_COLON,
215
+ REGEX_BRACKET_TERM_DOT,
216
+ REGEX_BRACKET_TERM_EQUAL,
217
+ };
218
+
219
+ enum RegexBracketPendingElement {
220
+ REGEX_BRACKET_PENDING_NONE,
221
+ REGEX_BRACKET_PENDING_OTHER,
222
+ REGEX_BRACKET_PENDING_DOT,
223
+ REGEX_BRACKET_PENDING_EQUAL,
224
+ REGEX_BRACKET_PENDING_COLON,
225
+ };
226
+
227
+ typedef struct {
228
+ int32_t delimiter;
229
+ enum ScannerMode mode;
230
+ enum RegexState regex_state;
231
+ bool regex_at_branch_start;
232
+ enum RegexDuplicationState regex_duplication_state;
233
+ bool regex_after_alternation;
234
+ bool regex_after_anchor;
235
+ enum TextState text_state;
236
+ enum RegexIntervalState regex_interval_state;
237
+ enum RegexBracketTermState regex_bracket_term_state;
238
+ enum RegexBracketPendingElement regex_bracket_pending_element;
239
+ enum RegexBracketPendingElement regex_bracket_first_element;
240
+ enum RegexBracketPendingElement regex_bracket_last_element;
241
+ uint8_t regex_bracket_element_count;
242
+ bool regex_bracket_range_pending;
243
+ uint16_t regex_group_depth;
244
+ } ScannerState;
245
+
246
+ enum {
247
+ SCANNER_SERIALIZATION_VERSION = 14,
248
+ SCANNER_SERIALIZED_STATE_SIZE = 17,
249
+ };
250
+
251
+ static void reset_bracket_tracking(ScannerState *state) {
252
+ state->regex_bracket_term_state = REGEX_BRACKET_TERM_NONE;
253
+ state->regex_bracket_pending_element = REGEX_BRACKET_PENDING_NONE;
254
+ state->regex_bracket_first_element = REGEX_BRACKET_PENDING_NONE;
255
+ state->regex_bracket_last_element = REGEX_BRACKET_PENDING_NONE;
256
+ state->regex_bracket_element_count = 0;
257
+ state->regex_bracket_range_pending = false;
258
+ }
259
+
260
+ static void set_regex_position(
261
+ ScannerState *state,
262
+ bool at_branch_start,
263
+ enum RegexDuplicationState duplication_state,
264
+ bool after_alternation,
265
+ bool after_anchor
266
+ ) {
267
+ state->regex_at_branch_start = at_branch_start;
268
+ state->regex_duplication_state = duplication_state;
269
+ state->regex_after_alternation = after_alternation;
270
+ state->regex_after_anchor = after_anchor;
271
+ }
272
+
273
+ static void reset_mode_tracking(ScannerState *state) {
274
+ state->regex_state = REGEX_OUTSIDE_BRACKET;
275
+ state->regex_at_branch_start = false;
276
+ state->regex_duplication_state = REGEX_DUPLICATION_NONE;
277
+ state->regex_after_alternation = false;
278
+ state->regex_after_anchor = false;
279
+ state->text_state = TEXT_EMPTY;
280
+ state->regex_interval_state = REGEX_INTERVAL_NONE;
281
+ reset_bracket_tracking(state);
282
+ state->regex_group_depth = 0;
283
+ }
284
+
285
+ static void reset_state(ScannerState *state) {
286
+ state->delimiter = 0;
287
+ state->mode = MODE_NONE;
288
+ reset_mode_tracking(state);
289
+ }
290
+
291
+ static void *sed_scanner_create(void) {
292
+ return ts_calloc(1, sizeof(ScannerState));
293
+ }
294
+
295
+ static void sed_scanner_destroy(void *payload) {
296
+ ts_free(payload);
297
+ }
298
+
299
+ static void serialize_uint16(char *buffer, unsigned offset, uint16_t value) {
300
+ buffer[offset] = (char)(value & UINT16_C(0xff));
301
+ buffer[offset + 1] = (char)((value >> 8) & UINT16_C(0xff));
302
+ }
303
+
304
+ static uint16_t deserialize_uint16(const char *buffer, unsigned offset) {
305
+ return (uint16_t)((uint16_t)(unsigned char)buffer[offset] |
306
+ ((uint16_t)(unsigned char)buffer[offset + 1] << 8));
307
+ }
308
+
309
+ static unsigned sed_scanner_serialize(void *payload, char *buffer) {
310
+ const ScannerState *state = payload;
311
+ const uint32_t delimiter = (uint32_t)state->delimiter;
312
+
313
+ buffer[0] = SCANNER_SERIALIZATION_VERSION;
314
+ buffer[1] = (char)state->mode;
315
+ buffer[2] = (char)state->regex_state;
316
+ buffer[3] = (state->regex_at_branch_start ? 1 : 0) |
317
+ (state->regex_after_alternation ? 2 : 0) |
318
+ (state->regex_after_anchor ? 4 : 0) |
319
+ ((unsigned char)state->text_state << 3);
320
+ buffer[4] = (char)(delimiter & UINT32_C(0xff));
321
+ buffer[5] = (char)((delimiter >> 8) & UINT32_C(0xff));
322
+ buffer[6] = (char)((delimiter >> 16) & UINT32_C(0xff));
323
+ buffer[7] = (char)((delimiter >> 24) & UINT32_C(0xff));
324
+ serialize_uint16(buffer, 8, state->regex_group_depth);
325
+ buffer[10] = (char)state->regex_interval_state;
326
+ buffer[11] = (char)state->regex_bracket_term_state;
327
+ buffer[12] = (char)state->regex_bracket_pending_element;
328
+ buffer[13] = (char)state->regex_bracket_first_element;
329
+ buffer[14] = (char)state->regex_bracket_last_element;
330
+ buffer[15] = (char)state->regex_bracket_element_count;
331
+ buffer[16] = (state->regex_bracket_range_pending ? 1 : 0) |
332
+ ((unsigned char)state->regex_duplication_state << 1);
333
+ return SCANNER_SERIALIZED_STATE_SIZE;
334
+ }
335
+
336
+ static void
337
+ sed_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
338
+ ScannerState *state = payload;
339
+ reset_state(state);
340
+
341
+ if (
342
+ length !=
343
+ SCANNER_SERIALIZED_STATE_SIZE ||
344
+ (unsigned char)buffer[0] != SCANNER_SERIALIZATION_VERSION
345
+ ) {
346
+ return;
347
+ }
348
+
349
+ const enum ScannerMode mode = (enum ScannerMode)(unsigned char)buffer[1];
350
+ const enum RegexState regex_state = (enum RegexState)(unsigned char)buffer[2];
351
+ const unsigned char mode_flags = (unsigned char)buffer[3];
352
+ const uint32_t delimiter = (uint32_t)(unsigned char)buffer[4] |
353
+ ((uint32_t)(unsigned char)buffer[5] << 8) |
354
+ ((uint32_t)(unsigned char)buffer[6] << 16) |
355
+ ((uint32_t)(unsigned char)buffer[7] << 24);
356
+ const uint16_t regex_group_depth = deserialize_uint16(buffer, 8);
357
+ const enum RegexIntervalState regex_interval_state =
358
+ (enum RegexIntervalState)(unsigned char)buffer[10];
359
+ const enum RegexBracketTermState regex_bracket_term_state =
360
+ (enum RegexBracketTermState)(unsigned char)buffer[11];
361
+ const enum RegexBracketPendingElement regex_bracket_pending_element =
362
+ (enum RegexBracketPendingElement)(unsigned char)buffer[12];
363
+ const enum RegexBracketPendingElement regex_bracket_first_element =
364
+ (enum RegexBracketPendingElement)(unsigned char)buffer[13];
365
+ const enum RegexBracketPendingElement regex_bracket_last_element =
366
+ (enum RegexBracketPendingElement)(unsigned char)buffer[14];
367
+ const uint8_t regex_bracket_element_count =
368
+ (uint8_t)(unsigned char)buffer[15];
369
+ const unsigned char regex_bracket_flags = (unsigned char)buffer[16];
370
+ const bool regex_bracket_range_pending = (regex_bracket_flags & 1U) != 0;
371
+ const enum RegexDuplicationState regex_duplication_state =
372
+ (enum RegexDuplicationState)((regex_bracket_flags >> 1) & 3U);
373
+
374
+ if (mode > MODE_TEXT) {
375
+ return;
376
+ }
377
+
378
+ if (regex_state > REGEX_BRACKET_BODY) {
379
+ return;
380
+ }
381
+
382
+ if ((mode_flags & (unsigned char)~31U) != 0) {
383
+ return;
384
+ }
385
+ const bool regex_at_branch_start = (mode_flags & 1U) != 0;
386
+ const bool regex_after_alternation = (mode_flags & 2U) != 0;
387
+ const bool regex_after_anchor = (mode_flags & 4U) != 0;
388
+ const enum TextState text_state = (enum TextState)((mode_flags >> 3) & 3U);
389
+ if (text_state > TEXT_AFTER_ESCAPED_NEWLINE) {
390
+ return;
391
+ }
392
+ #if !SED_REGEX_EXTENDED
393
+ if (regex_after_alternation) {
394
+ return;
395
+ }
396
+ #endif
397
+
398
+ if (regex_interval_state > REGEX_INTERVAL_AFTER_MAXIMUM) {
399
+ return;
400
+ }
401
+ if (regex_bracket_term_state > REGEX_BRACKET_TERM_EQUAL) {
402
+ return;
403
+ }
404
+ if (
405
+ regex_bracket_pending_element >
406
+ REGEX_BRACKET_PENDING_COLON ||
407
+ regex_bracket_first_element >
408
+ REGEX_BRACKET_PENDING_COLON ||
409
+ regex_bracket_last_element >
410
+ REGEX_BRACKET_PENDING_COLON ||
411
+ regex_bracket_element_count >
412
+ 3U ||
413
+ (regex_bracket_flags & (unsigned char)~7U) !=
414
+ 0 ||
415
+ #if SED_REGEX_EXTENDED
416
+ regex_duplication_state > REGEX_AFTER_REPETITION_MODIFIER
417
+ #else
418
+ regex_duplication_state > REGEX_AFTER_DUPLICATION_SYMBOL
419
+ #endif
420
+ ) {
421
+ return;
422
+ }
423
+ if (
424
+ (regex_bracket_element_count ==
425
+ 0 &&
426
+ (regex_bracket_first_element !=
427
+ REGEX_BRACKET_PENDING_NONE ||
428
+ regex_bracket_last_element != REGEX_BRACKET_PENDING_NONE)) ||
429
+ (regex_bracket_element_count >
430
+ 0 &&
431
+ (regex_bracket_first_element ==
432
+ REGEX_BRACKET_PENDING_NONE ||
433
+ regex_bracket_last_element == REGEX_BRACKET_PENDING_NONE)) ||
434
+ (regex_bracket_pending_element !=
435
+ REGEX_BRACKET_PENDING_NONE &&
436
+ regex_bracket_range_pending)
437
+ ) {
438
+ return;
439
+ }
440
+
441
+ if (mode == MODE_NONE) {
442
+ return;
443
+ }
444
+
445
+ if (mode == MODE_TEXT) {
446
+ if (
447
+ delimiter ==
448
+ 0 &&
449
+ regex_state ==
450
+ REGEX_OUTSIDE_BRACKET &&
451
+ !regex_at_branch_start &&
452
+ regex_duplication_state ==
453
+ REGEX_DUPLICATION_NONE &&
454
+ regex_group_depth ==
455
+ 0 &&
456
+ !regex_after_anchor &&
457
+ regex_interval_state ==
458
+ REGEX_INTERVAL_NONE &&
459
+ !regex_after_alternation &&
460
+ regex_bracket_term_state ==
461
+ REGEX_BRACKET_TERM_NONE &&
462
+ regex_bracket_pending_element ==
463
+ REGEX_BRACKET_PENDING_NONE &&
464
+ regex_bracket_first_element ==
465
+ REGEX_BRACKET_PENDING_NONE &&
466
+ regex_bracket_last_element ==
467
+ REGEX_BRACKET_PENDING_NONE &&
468
+ regex_bracket_element_count ==
469
+ 0 &&
470
+ !regex_bracket_range_pending
471
+ ) {
472
+ state->mode = mode;
473
+ state->text_state = text_state;
474
+ }
475
+ return;
476
+ }
477
+
478
+ if (
479
+ delimiter ==
480
+ 0 ||
481
+ delimiter >
482
+ UINT32_C(0x10ffff) ||
483
+ (delimiter >= UINT32_C(0xd800) && delimiter <= UINT32_C(0xdfff)) ||
484
+ delimiter ==
485
+ (uint32_t)'\\' ||
486
+ delimiter == (uint32_t)'\n'
487
+ ) {
488
+ return;
489
+ }
490
+
491
+ if (
492
+ mode !=
493
+ MODE_REGEX_ADDRESS &&
494
+ mode !=
495
+ MODE_SUBSTITUTE_PATTERN &&
496
+ (regex_state !=
497
+ REGEX_OUTSIDE_BRACKET ||
498
+ regex_at_branch_start ||
499
+ regex_duplication_state !=
500
+ REGEX_DUPLICATION_NONE ||
501
+ regex_after_alternation ||
502
+ regex_after_anchor ||
503
+ text_state !=
504
+ TEXT_EMPTY ||
505
+ regex_interval_state !=
506
+ REGEX_INTERVAL_NONE ||
507
+ regex_bracket_term_state !=
508
+ REGEX_BRACKET_TERM_NONE ||
509
+ regex_bracket_pending_element !=
510
+ REGEX_BRACKET_PENDING_NONE ||
511
+ regex_bracket_first_element !=
512
+ REGEX_BRACKET_PENDING_NONE ||
513
+ regex_bracket_last_element !=
514
+ REGEX_BRACKET_PENDING_NONE ||
515
+ regex_bracket_element_count !=
516
+ 0 ||
517
+ regex_bracket_range_pending)
518
+ ) {
519
+ return;
520
+ }
521
+
522
+ if (
523
+ regex_state !=
524
+ REGEX_OUTSIDE_BRACKET &&
525
+ (regex_at_branch_start ||
526
+ regex_duplication_state !=
527
+ REGEX_DUPLICATION_NONE ||
528
+ regex_after_alternation ||
529
+ regex_after_anchor)
530
+ ) {
531
+ return;
532
+ }
533
+
534
+ if (
535
+ regex_state ==
536
+ REGEX_OUTSIDE_BRACKET &&
537
+ (regex_bracket_term_state !=
538
+ REGEX_BRACKET_TERM_NONE ||
539
+ regex_bracket_pending_element !=
540
+ REGEX_BRACKET_PENDING_NONE ||
541
+ regex_bracket_first_element !=
542
+ REGEX_BRACKET_PENDING_NONE ||
543
+ regex_bracket_last_element !=
544
+ REGEX_BRACKET_PENDING_NONE ||
545
+ regex_bracket_element_count !=
546
+ 0 ||
547
+ regex_bracket_range_pending)
548
+ ) {
549
+ return;
550
+ }
551
+
552
+ if (
553
+ (regex_state ==
554
+ REGEX_BRACKET_FIRST ||
555
+ regex_state == REGEX_BRACKET_AFTER_CARET) &&
556
+ (regex_bracket_term_state !=
557
+ REGEX_BRACKET_TERM_NONE ||
558
+ regex_bracket_pending_element !=
559
+ REGEX_BRACKET_PENDING_NONE ||
560
+ regex_bracket_element_count !=
561
+ 0 ||
562
+ regex_bracket_range_pending)
563
+ ) {
564
+ return;
565
+ }
566
+
567
+ if (
568
+ (mode == MODE_REGEX_ADDRESS || mode == MODE_SUBSTITUTE_PATTERN) &&
569
+ text_state != TEXT_EMPTY
570
+ ) {
571
+ return;
572
+ }
573
+
574
+ if (
575
+ mode !=
576
+ MODE_REGEX_ADDRESS &&
577
+ mode !=
578
+ MODE_SUBSTITUTE_PATTERN &&
579
+ regex_group_depth != 0
580
+ ) {
581
+ return;
582
+ }
583
+
584
+ state->mode = mode;
585
+ state->delimiter = (int32_t)delimiter;
586
+ state->regex_state = regex_state;
587
+ state->regex_at_branch_start = regex_at_branch_start;
588
+ state->regex_duplication_state = regex_duplication_state;
589
+ state->regex_after_alternation = regex_after_alternation;
590
+ state->regex_after_anchor = regex_after_anchor;
591
+ state->regex_interval_state = regex_interval_state;
592
+ state->regex_bracket_term_state = regex_bracket_term_state;
593
+ state->regex_bracket_pending_element = regex_bracket_pending_element;
594
+ state->regex_bracket_first_element = regex_bracket_first_element;
595
+ state->regex_bracket_last_element = regex_bracket_last_element;
596
+ state->regex_bracket_element_count = regex_bracket_element_count;
597
+ state->regex_bracket_range_pending = regex_bracket_range_pending;
598
+ state->regex_group_depth = regex_group_depth;
599
+ }
600
+
601
+ static void advance(TSLexer *lexer) {
602
+ lexer->advance(lexer, false);
603
+ }
604
+
605
+ static bool is_blank(int32_t character) {
606
+ return character == ' ' || character == '\t';
607
+ }
608
+
609
+ static bool is_digit(int32_t character) {
610
+ return character >= '0' && character <= '9';
611
+ }
612
+
613
+ static void advance_past_blanks(TSLexer *lexer) {
614
+ while (is_blank(lexer->lookahead)) {
615
+ advance(lexer);
616
+ }
617
+ }
618
+
619
+ static void advance_past_escaped_character(TSLexer *lexer) {
620
+ if (!lexer->eof(lexer) && lexer->lookahead != '\n') {
621
+ advance(lexer);
622
+ }
623
+ }
624
+
625
+ static void skip_blanks(TSLexer *lexer) {
626
+ while (is_blank(lexer->lookahead)) {
627
+ lexer->advance(lexer, true);
628
+ }
629
+ }
630
+
631
+ static bool invalid_delimiter(TSLexer *lexer) {
632
+ return lexer->eof(lexer) ||
633
+ lexer->lookahead ==
634
+ 0 ||
635
+ lexer->lookahead ==
636
+ '\\' ||
637
+ lexer->lookahead == '\n';
638
+ }
639
+
640
+ static bool delimiter_is_missing(TSLexer *lexer) {
641
+ return lexer->eof(lexer) || lexer->lookahead == '\n';
642
+ }
643
+
644
+ static bool scan_simple_delimiter(
645
+ TSLexer *lexer,
646
+ ScannerState *state,
647
+ enum ScannerMode next_mode
648
+ ) {
649
+ if (invalid_delimiter(lexer)) {
650
+ return false;
651
+ }
652
+
653
+ state->delimiter = lexer->lookahead;
654
+ state->mode = next_mode;
655
+ reset_mode_tracking(state);
656
+ state->regex_at_branch_start =
657
+ next_mode == MODE_REGEX_ADDRESS || next_mode == MODE_SUBSTITUTE_PATTERN;
658
+ advance(lexer);
659
+ lexer->mark_end(lexer);
660
+ return true;
661
+ }
662
+
663
+ static bool scan_mode_delimiter(
664
+ TSLexer *lexer,
665
+ ScannerState *state,
666
+ enum ScannerMode next_mode
667
+ ) {
668
+ if (lexer->lookahead != state->delimiter) {
669
+ return false;
670
+ }
671
+
672
+ state->mode = next_mode;
673
+ reset_mode_tracking(state);
674
+ if (next_mode == MODE_NONE) {
675
+ state->delimiter = 0;
676
+ }
677
+ advance(lexer);
678
+ lexer->mark_end(lexer);
679
+ return true;
680
+ }
681
+
682
+ static bool scan_active_mode_delimiter(
683
+ TSLexer *lexer,
684
+ ScannerState *state,
685
+ const bool *valid_symbols,
686
+ TSSymbol *symbol
687
+ ) {
688
+ TSSymbol candidate;
689
+ enum ScannerMode next_mode;
690
+
691
+ switch (state->mode) {
692
+ case MODE_REGEX_ADDRESS:
693
+ candidate = REGEX_ADDRESS_END;
694
+ next_mode = MODE_NONE;
695
+ break;
696
+ case MODE_SUBSTITUTE_PATTERN:
697
+ candidate = SUBSTITUTE_MIDDLE;
698
+ next_mode = MODE_SUBSTITUTE_REPLACEMENT;
699
+ break;
700
+ case MODE_SUBSTITUTE_REPLACEMENT:
701
+ candidate = SUBSTITUTE_END;
702
+ next_mode = MODE_NONE;
703
+ break;
704
+ case MODE_TRANSLATE_SOURCE:
705
+ candidate = TRANSLATE_MIDDLE;
706
+ next_mode = MODE_TRANSLATE_DESTINATION;
707
+ break;
708
+ case MODE_TRANSLATE_DESTINATION:
709
+ candidate = TRANSLATE_END;
710
+ next_mode = MODE_NONE;
711
+ break;
712
+ case MODE_NONE:
713
+ case MODE_TEXT:
714
+ return false;
715
+ }
716
+
717
+ if (
718
+ !valid_symbols[candidate] || !scan_mode_delimiter(lexer, state, next_mode)
719
+ ) {
720
+ return false;
721
+ }
722
+
723
+ *symbol = candidate;
724
+ return true;
725
+ }
726
+
727
+ static void consume(TSLexer *lexer) {
728
+ advance(lexer);
729
+ lexer->mark_end(lexer);
730
+ }
731
+
732
+ static bool scan_text_command_start(TSLexer *lexer, ScannerState *state) {
733
+ if (state->mode != MODE_NONE || lexer->lookahead != '\\') {
734
+ return false;
735
+ }
736
+
737
+ lexer->mark_end(lexer);
738
+ advance(lexer);
739
+
740
+ if (lexer->lookahead != '\n') {
741
+ return false;
742
+ }
743
+
744
+ consume(lexer);
745
+ state->mode = MODE_TEXT;
746
+ return true;
747
+ }
748
+
749
+ static bool scan_to_physical_line_end(TSLexer *lexer, bool consumed) {
750
+ while (!lexer->eof(lexer)) {
751
+ if (lexer->lookahead == '\n') {
752
+ return consumed;
753
+ }
754
+
755
+ consume(lexer);
756
+ consumed = true;
757
+ }
758
+
759
+ return consumed;
760
+ }
761
+
762
+ static bool scan_file_argument(TSLexer *lexer) {
763
+ if (
764
+ lexer->eof(lexer) || is_blank(lexer->lookahead) || lexer->lookahead == '\n'
765
+ ) {
766
+ return false;
767
+ }
768
+
769
+ consume(lexer);
770
+ return scan_to_physical_line_end(lexer, true);
771
+ }
772
+
773
+ static bool scan_substitution_wfile_argument(TSLexer *lexer) {
774
+ if (
775
+ lexer->eof(lexer) ||
776
+ is_blank(lexer->lookahead) ||
777
+ lexer->lookahead ==
778
+ '\n' ||
779
+ lexer->lookahead == ';'
780
+ ) {
781
+ return false;
782
+ }
783
+
784
+ do {
785
+ consume(lexer);
786
+ } while (
787
+ !lexer->eof(lexer) && lexer->lookahead != '\n' && lexer->lookahead != ';'
788
+ );
789
+ return true;
790
+ }
791
+
792
+ static bool scan_right_brace(TSLexer *lexer, ScannerState *state) {
793
+ if (state->mode != MODE_NONE) {
794
+ return false;
795
+ }
796
+
797
+ skip_blanks(lexer);
798
+
799
+ if (lexer->lookahead != '}') {
800
+ return false;
801
+ }
802
+
803
+ consume(lexer);
804
+ return true;
805
+ }
806
+
807
+ static bool scan_reserved_unknown_function(TSLexer *lexer) {
808
+ const int32_t character = lexer->lookahead;
809
+ if (
810
+ !is_digit(character) &&
811
+ character !=
812
+ '$' &&
813
+ character !=
814
+ '/' &&
815
+ character != '\\'
816
+ ) {
817
+ return false;
818
+ }
819
+
820
+ consume(lexer);
821
+ return true;
822
+ }
823
+
824
+ enum LiteralScanResult {
825
+ LITERAL_SCAN_NONE,
826
+ LITERAL_SCAN_TOKEN,
827
+ LITERAL_SCAN_LINE_END,
828
+ };
829
+
830
+ static bool
831
+ emit_symbol(const bool *valid_symbols, TSSymbol candidate, TSSymbol *symbol) {
832
+ if (!valid_symbols[candidate]) {
833
+ return false;
834
+ }
835
+
836
+ *symbol = candidate;
837
+ return true;
838
+ }
839
+
840
+ static bool emit_missing_marker(
841
+ TSLexer *lexer,
842
+ const bool *valid_symbols,
843
+ TSSymbol candidate,
844
+ TSSymbol *symbol
845
+ ) {
846
+ if (!valid_symbols[candidate]) {
847
+ return false;
848
+ }
849
+
850
+ lexer->mark_end(lexer);
851
+ *symbol = candidate;
852
+ return true;
853
+ }
854
+
855
+ static bool at_command_boundary(TSLexer *lexer) {
856
+ return lexer->eof(lexer) ||
857
+ lexer->lookahead ==
858
+ '\n' ||
859
+ lexer->lookahead ==
860
+ ';' ||
861
+ lexer->lookahead == '}';
862
+ }
863
+
864
+ static bool can_start_address(TSLexer *lexer) {
865
+ return is_digit(lexer->lookahead) ||
866
+ lexer->lookahead ==
867
+ '$' ||
868
+ lexer->lookahead ==
869
+ '/' ||
870
+ lexer->lookahead == '\\';
871
+ }
872
+
873
+ enum PostBlankRecoveryScan {
874
+ POST_BLANK_RECOVERY_SKIPPED,
875
+ POST_BLANK_RECOVERY_TOKEN,
876
+ POST_BLANK_RECOVERY_FAILED,
877
+ };
878
+
879
+ static enum PostBlankRecoveryScan scan_post_blank_recovery(
880
+ TSLexer *lexer,
881
+ const bool *valid_symbols,
882
+ TSSymbol *symbol
883
+ ) {
884
+ if (
885
+ !valid_symbols[OMITTED_ADDRESS_MARKER] &&
886
+ !valid_symbols[ADDITIONAL_ADDRESS_MARKER] &&
887
+ !valid_symbols[BLANKS_AROUND_ADDRESS_SEPARATOR_MARKER] &&
888
+ !valid_symbols[MISSING_ADDRESS_SEPARATOR_MARKER] &&
889
+ !valid_symbols[MISSING_SEPARATOR_BEFORE_UNMATCHED_BRACE_MARKER] &&
890
+ !valid_symbols[MISSING_COMMAND_SEPARATOR_MARKER] &&
891
+ !valid_symbols[INCOMPLETE_COMMAND_SEPARATOR_MARKER]
892
+ ) {
893
+ return POST_BLANK_RECOVERY_SKIPPED;
894
+ }
895
+
896
+ lexer->mark_end(lexer);
897
+ advance_past_blanks(lexer);
898
+
899
+ if (valid_symbols[OMITTED_ADDRESS_MARKER] && !can_start_address(lexer)) {
900
+ *symbol = OMITTED_ADDRESS_MARKER;
901
+ return POST_BLANK_RECOVERY_TOKEN;
902
+ }
903
+ if (
904
+ valid_symbols[ADDITIONAL_ADDRESS_MARKER] &&
905
+ (lexer->lookahead == ',' || can_start_address(lexer))
906
+ ) {
907
+ *symbol = ADDITIONAL_ADDRESS_MARKER;
908
+ return POST_BLANK_RECOVERY_TOKEN;
909
+ }
910
+ if (
911
+ valid_symbols[BLANKS_AROUND_ADDRESS_SEPARATOR_MARKER] &&
912
+ lexer->lookahead == ','
913
+ ) {
914
+ *symbol = BLANKS_AROUND_ADDRESS_SEPARATOR_MARKER;
915
+ return POST_BLANK_RECOVERY_TOKEN;
916
+ }
917
+ if (
918
+ valid_symbols[MISSING_ADDRESS_SEPARATOR_MARKER] && can_start_address(lexer)
919
+ ) {
920
+ *symbol = MISSING_ADDRESS_SEPARATOR_MARKER;
921
+ return POST_BLANK_RECOVERY_TOKEN;
922
+ }
923
+ if (lexer->lookahead == '}') {
924
+ if (valid_symbols[MISSING_SEPARATOR_BEFORE_UNMATCHED_BRACE_MARKER]) {
925
+ *symbol = MISSING_SEPARATOR_BEFORE_UNMATCHED_BRACE_MARKER;
926
+ return POST_BLANK_RECOVERY_TOKEN;
927
+ }
928
+ if (valid_symbols[MISSING_COMMAND_SEPARATOR_MARKER]) {
929
+ *symbol = MISSING_COMMAND_SEPARATOR_MARKER;
930
+ return POST_BLANK_RECOVERY_TOKEN;
931
+ }
932
+ return POST_BLANK_RECOVERY_FAILED;
933
+ }
934
+ if (lexer->eof(lexer) && valid_symbols[INCOMPLETE_COMMAND_SEPARATOR_MARKER]) {
935
+ *symbol = INCOMPLETE_COMMAND_SEPARATOR_MARKER;
936
+ return POST_BLANK_RECOVERY_TOKEN;
937
+ }
938
+ return POST_BLANK_RECOVERY_FAILED;
939
+ }
940
+
941
+ static bool scan_text_token(
942
+ TSLexer *lexer,
943
+ ScannerState *state,
944
+ const bool *valid_symbols,
945
+ TSSymbol *symbol
946
+ ) {
947
+ if (lexer->eof(lexer)) {
948
+ if (state->text_state == TEXT_AFTER_ESCAPED_NEWLINE) {
949
+ if (!emit_missing_marker(
950
+ lexer,
951
+ valid_symbols,
952
+ MISSING_TEXT_MARKER,
953
+ symbol
954
+ )) {
955
+ return false;
956
+ }
957
+ state->text_state = TEXT_HAS_CONTENT;
958
+ return true;
959
+ }
960
+ if (
961
+ state->text_state ==
962
+ TEXT_EMPTY &&
963
+ emit_missing_marker(lexer, valid_symbols, MISSING_TEXT_MARKER, symbol)
964
+ ) {
965
+ state->text_state = TEXT_HAS_CONTENT;
966
+ return true;
967
+ }
968
+ if (!valid_symbols[TEXT_EOF]) {
969
+ return false;
970
+ }
971
+ lexer->mark_end(lexer);
972
+ reset_state(state);
973
+ *symbol = TEXT_EOF;
974
+ return true;
975
+ }
976
+
977
+ if (lexer->lookahead == '\n') {
978
+ if (!valid_symbols[TEXT_LINE_END]) {
979
+ return false;
980
+ }
981
+ lexer->mark_end(lexer);
982
+ reset_state(state);
983
+ *symbol = TEXT_LINE_END;
984
+ return true;
985
+ }
986
+
987
+ if (lexer->lookahead == '\\') {
988
+ advance(lexer);
989
+ lexer->mark_end(lexer);
990
+
991
+ if (lexer->eof(lexer)) {
992
+ state->text_state = TEXT_HAS_CONTENT;
993
+ return emit_symbol(valid_symbols, TEXT_UNSPECIFIED_ESCAPE, symbol);
994
+ }
995
+ if (lexer->lookahead == '\\') {
996
+ consume(lexer);
997
+ state->text_state = TEXT_HAS_CONTENT;
998
+ return emit_symbol(valid_symbols, TEXT_BACKSLASH_ESCAPE, symbol);
999
+ }
1000
+ if (lexer->lookahead == '\n') {
1001
+ consume(lexer);
1002
+ state->text_state = TEXT_AFTER_ESCAPED_NEWLINE;
1003
+ return emit_symbol(valid_symbols, TEXT_ESCAPED_NEWLINE, symbol);
1004
+ }
1005
+
1006
+ consume(lexer);
1007
+ state->text_state = TEXT_HAS_CONTENT;
1008
+ return emit_symbol(valid_symbols, TEXT_UNSPECIFIED_ESCAPE, symbol);
1009
+ }
1010
+
1011
+ if (!valid_symbols[TEXT_LITERAL]) {
1012
+ return false;
1013
+ }
1014
+ do {
1015
+ consume(lexer);
1016
+ } while (
1017
+ !lexer->eof(lexer) && lexer->lookahead != '\\' && lexer->lookahead != '\n'
1018
+ );
1019
+ state->text_state = TEXT_HAS_CONTENT;
1020
+ *symbol = TEXT_LITERAL;
1021
+ return true;
1022
+ }
1023
+
1024
+ static bool is_regex_mode(enum ScannerMode mode) {
1025
+ return mode == MODE_REGEX_ADDRESS || mode == MODE_SUBSTITUTE_PATTERN;
1026
+ }
1027
+
1028
+ static bool regex_is_inside_bracket(const ScannerState *state) {
1029
+ return state->regex_state != REGEX_OUTSIDE_BRACKET;
1030
+ }
1031
+
1032
+ static enum RegexBracketPendingElement
1033
+ bracket_element_for_character(int32_t character) {
1034
+ switch (character) {
1035
+ case '.':
1036
+ return REGEX_BRACKET_PENDING_DOT;
1037
+ case '=':
1038
+ return REGEX_BRACKET_PENDING_EQUAL;
1039
+ case ':':
1040
+ return REGEX_BRACKET_PENDING_COLON;
1041
+ default:
1042
+ return REGEX_BRACKET_PENDING_OTHER;
1043
+ }
1044
+ }
1045
+
1046
+ static void record_bracket_element(
1047
+ ScannerState *state,
1048
+ enum RegexBracketPendingElement element
1049
+ ) {
1050
+ if (state->regex_bracket_element_count == 0) {
1051
+ state->regex_bracket_first_element = element;
1052
+ }
1053
+ if (state->regex_bracket_element_count < 3U) {
1054
+ state->regex_bracket_element_count++;
1055
+ }
1056
+ state->regex_bracket_last_element = element;
1057
+ }
1058
+
1059
+ static void commit_pending_bracket_element(ScannerState *state) {
1060
+ if (state->regex_bracket_pending_element == REGEX_BRACKET_PENDING_NONE) {
1061
+ return;
1062
+ }
1063
+
1064
+ record_bracket_element(state, state->regex_bracket_pending_element);
1065
+ state->regex_bracket_pending_element = REGEX_BRACKET_PENDING_NONE;
1066
+ }
1067
+
1068
+ static void
1069
+ begin_single_bracket_element(ScannerState *state, int32_t character) {
1070
+ if (state->regex_bracket_range_pending) {
1071
+ record_bracket_element(state, REGEX_BRACKET_PENDING_OTHER);
1072
+ state->regex_bracket_range_pending = false;
1073
+ return;
1074
+ }
1075
+
1076
+ commit_pending_bracket_element(state);
1077
+ state->regex_bracket_pending_element =
1078
+ bracket_element_for_character(character);
1079
+ }
1080
+
1081
+ static void begin_compound_bracket_element(ScannerState *state) {
1082
+ if (!state->regex_bracket_range_pending) {
1083
+ commit_pending_bracket_element(state);
1084
+ }
1085
+ }
1086
+
1087
+ static void finish_compound_bracket_element(ScannerState *state) {
1088
+ if (state->regex_bracket_range_pending) {
1089
+ record_bracket_element(state, REGEX_BRACKET_PENDING_OTHER);
1090
+ state->regex_bracket_range_pending = false;
1091
+ return;
1092
+ }
1093
+
1094
+ state->regex_bracket_pending_element = REGEX_BRACKET_PENDING_OTHER;
1095
+ }
1096
+
1097
+ static bool bracket_expression_is_ambiguous(const ScannerState *state) {
1098
+ return state->regex_bracket_element_count >=
1099
+ 3U &&
1100
+ state->regex_bracket_first_element >=
1101
+ REGEX_BRACKET_PENDING_DOT &&
1102
+ state->regex_bracket_first_element == state->regex_bracket_last_element;
1103
+ }
1104
+
1105
+ static void finish_first_bracket_element(ScannerState *state) {
1106
+ if (
1107
+ state->regex_state ==
1108
+ REGEX_BRACKET_FIRST ||
1109
+ state->regex_state == REGEX_BRACKET_AFTER_CARET
1110
+ ) {
1111
+ state->regex_state = REGEX_BRACKET_BODY;
1112
+ }
1113
+ }
1114
+
1115
+ static void
1116
+ update_bracket_state_after_literal(ScannerState *state, int32_t character) {
1117
+ if (state->regex_state == REGEX_BRACKET_FIRST) {
1118
+ state->regex_state =
1119
+ character == '^' ? REGEX_BRACKET_AFTER_CARET : REGEX_BRACKET_BODY;
1120
+ } else if (state->regex_state == REGEX_BRACKET_AFTER_CARET) {
1121
+ state->regex_state = REGEX_BRACKET_BODY;
1122
+ }
1123
+ }
1124
+
1125
+ static bool
1126
+ regex_literal_boundary(const ScannerState *state, int32_t character) {
1127
+ if (state->regex_state == REGEX_OUTSIDE_BRACKET) {
1128
+ return character ==
1129
+ state->delimiter ||
1130
+ character ==
1131
+ '\\' ||
1132
+ character ==
1133
+ '(' ||
1134
+ character ==
1135
+ ')' ||
1136
+ character ==
1137
+ '[' ||
1138
+ character ==
1139
+ '*' ||
1140
+ character ==
1141
+ '+' ||
1142
+ character ==
1143
+ '?' ||
1144
+ character ==
1145
+ '|' ||
1146
+ character ==
1147
+ '{' ||
1148
+ character ==
1149
+ '.' ||
1150
+ character ==
1151
+ '^' ||
1152
+ character == '$';
1153
+ }
1154
+
1155
+ if (
1156
+ character ==
1157
+ '[' ||
1158
+ (state->regex_state == REGEX_BRACKET_FIRST && character == '^') ||
1159
+ (state->regex_state == REGEX_BRACKET_BODY && character == '-') ||
1160
+ (state->regex_state == REGEX_BRACKET_BODY && character == ']')
1161
+ ) {
1162
+ return true;
1163
+ }
1164
+
1165
+ return false;
1166
+ }
1167
+
1168
+ static enum LiteralScanResult
1169
+ scan_regex_literal(TSLexer *lexer, ScannerState *state) {
1170
+ lexer->mark_end(lexer);
1171
+
1172
+ if (lexer->eof(lexer) || lexer->lookahead == '\n') {
1173
+ return LITERAL_SCAN_LINE_END;
1174
+ }
1175
+
1176
+ if (regex_literal_boundary(state, lexer->lookahead)) {
1177
+ return LITERAL_SCAN_NONE;
1178
+ }
1179
+
1180
+ const int32_t character = lexer->lookahead;
1181
+ consume(lexer);
1182
+ if (regex_is_inside_bracket(state)) {
1183
+ begin_single_bracket_element(state, character);
1184
+ }
1185
+ update_bracket_state_after_literal(state, character);
1186
+ return LITERAL_SCAN_TOKEN;
1187
+ }
1188
+
1189
+ static TSSymbol
1190
+ regex_unterminated_symbol(enum ScannerMode mode, bool at_end_of_source) {
1191
+ if (mode == MODE_REGEX_ADDRESS) {
1192
+ return at_end_of_source ? REGEX_UNTERMINATED_ADDRESS
1193
+ : REGEX_LINE_UNTERMINATED_ADDRESS;
1194
+ }
1195
+ return at_end_of_source ? REGEX_UNTERMINATED_SUBSTITUTE
1196
+ : REGEX_LINE_UNTERMINATED_SUBSTITUTE;
1197
+ }
1198
+
1199
+ static bool emit_unterminated(
1200
+ ScannerState *state,
1201
+ const bool *valid_symbols,
1202
+ TSSymbol candidate,
1203
+ TSSymbol *symbol
1204
+ ) {
1205
+ if (!emit_symbol(valid_symbols, candidate, symbol)) {
1206
+ return false;
1207
+ }
1208
+
1209
+ reset_state(state);
1210
+ return true;
1211
+ }
1212
+
1213
+ static bool scan_regex_bracket_opener(
1214
+ TSLexer *lexer,
1215
+ ScannerState *state,
1216
+ const bool *valid_symbols,
1217
+ TSSymbol *symbol
1218
+ ) {
1219
+ lexer->mark_end(lexer);
1220
+ advance(lexer);
1221
+
1222
+ if (
1223
+ valid_symbols[NONPORTABLE_RANGE_END_MARKER] &&
1224
+ (lexer->lookahead == ':' || lexer->lookahead == '=')
1225
+ ) {
1226
+ *symbol = NONPORTABLE_RANGE_END_MARKER;
1227
+ return true;
1228
+ }
1229
+
1230
+ lexer->mark_end(lexer);
1231
+
1232
+ TSSymbol candidate;
1233
+ switch (lexer->lookahead) {
1234
+ case ':':
1235
+ candidate = REGEX_OPEN_COLON;
1236
+ break;
1237
+ case '.':
1238
+ candidate = REGEX_OPEN_DOT;
1239
+ break;
1240
+ case '=':
1241
+ candidate = REGEX_OPEN_EQUAL;
1242
+ break;
1243
+ default:
1244
+ begin_single_bracket_element(state, '[');
1245
+ finish_first_bracket_element(state);
1246
+ return emit_symbol(valid_symbols, REGEX_BRACKET_LITERAL, symbol);
1247
+ }
1248
+
1249
+ if (!valid_symbols[candidate]) {
1250
+ return false;
1251
+ }
1252
+ consume(lexer);
1253
+ begin_compound_bracket_element(state);
1254
+ finish_first_bracket_element(state);
1255
+ state->regex_bracket_term_state = candidate == REGEX_OPEN_COLON
1256
+ ? REGEX_BRACKET_TERM_COLON
1257
+ : candidate == REGEX_OPEN_DOT ? REGEX_BRACKET_TERM_DOT
1258
+ : REGEX_BRACKET_TERM_EQUAL;
1259
+ *symbol = candidate;
1260
+ return true;
1261
+ }
1262
+
1263
+ static void record_bracket_term_character(
1264
+ uint8_t *character_count,
1265
+ int32_t *single_character,
1266
+ int32_t character
1267
+ ) {
1268
+ if (*character_count == 0) {
1269
+ *single_character = character;
1270
+ }
1271
+ if (*character_count < 2U) {
1272
+ (*character_count)++;
1273
+ }
1274
+ }
1275
+
1276
+ static bool bracket_meta_character(int32_t character) {
1277
+ return character == '^' || character == '-' || character == ']';
1278
+ }
1279
+
1280
+ static TSSymbol regex_bracket_term_content_symbol(
1281
+ const ScannerState *state,
1282
+ uint8_t character_count,
1283
+ int32_t single_character
1284
+ ) {
1285
+ if (state->regex_bracket_term_state == REGEX_BRACKET_TERM_COLON) {
1286
+ return REGEX_CLASS_NAME;
1287
+ }
1288
+ if (character_count > 1U) {
1289
+ return REGEX_COLL_ELEM_MULTI;
1290
+ }
1291
+ if (
1292
+ state->regex_bracket_term_state ==
1293
+ REGEX_BRACKET_TERM_DOT &&
1294
+ bracket_meta_character(single_character)
1295
+ ) {
1296
+ return REGEX_META_CHAR;
1297
+ }
1298
+ return REGEX_COLL_ELEM_SINGLE;
1299
+ }
1300
+
1301
+ static bool scan_regex_bracket_term_content(
1302
+ TSLexer *lexer,
1303
+ ScannerState *state,
1304
+ int32_t close_marker,
1305
+ const bool *valid_symbols,
1306
+ TSSymbol *symbol
1307
+ ) {
1308
+ uint8_t character_count = 0;
1309
+ int32_t single_character = 0;
1310
+ bool stopped_at_close = false;
1311
+ lexer->mark_end(lexer);
1312
+
1313
+ if (
1314
+ lexer->lookahead ==
1315
+ ']' &&
1316
+ state->regex_bracket_term_state != REGEX_BRACKET_TERM_COLON
1317
+ ) {
1318
+ advance(lexer);
1319
+ lexer->mark_end(lexer);
1320
+ record_bracket_term_character(&character_count, &single_character, ']');
1321
+ if (lexer->lookahead == close_marker) {
1322
+ advance(lexer);
1323
+ if (lexer->lookahead == ']') {
1324
+ const TSSymbol candidate = regex_bracket_term_content_symbol(
1325
+ state,
1326
+ character_count,
1327
+ single_character
1328
+ );
1329
+ return emit_symbol(valid_symbols, candidate, symbol);
1330
+ }
1331
+ lexer->mark_end(lexer);
1332
+ record_bracket_term_character(
1333
+ &character_count,
1334
+ &single_character,
1335
+ close_marker
1336
+ );
1337
+ }
1338
+ }
1339
+
1340
+ for (;;) {
1341
+ if (
1342
+ lexer->eof(lexer) || lexer->lookahead == '\n' || lexer->lookahead == ']'
1343
+ ) {
1344
+ break;
1345
+ }
1346
+
1347
+ if (lexer->lookahead == close_marker) {
1348
+ advance(lexer);
1349
+ if (lexer->lookahead == ']') {
1350
+ stopped_at_close = true;
1351
+ break;
1352
+ }
1353
+ lexer->mark_end(lexer);
1354
+ record_bracket_term_character(
1355
+ &character_count,
1356
+ &single_character,
1357
+ close_marker
1358
+ );
1359
+ continue;
1360
+ }
1361
+
1362
+ const int32_t character = lexer->lookahead;
1363
+ consume(lexer);
1364
+ record_bracket_term_character(
1365
+ &character_count,
1366
+ &single_character,
1367
+ character
1368
+ );
1369
+ }
1370
+
1371
+ if (character_count == 0) {
1372
+ if (!stopped_at_close) {
1373
+ state->regex_bracket_term_state = REGEX_BRACKET_TERM_NONE;
1374
+ finish_compound_bracket_element(state);
1375
+ }
1376
+ return emit_symbol(valid_symbols, REGEX_MALFORMED_BRACKET_TERM, symbol);
1377
+ }
1378
+ const TSSymbol candidate =
1379
+ regex_bracket_term_content_symbol(state, character_count, single_character);
1380
+ return emit_symbol(valid_symbols, candidate, symbol);
1381
+ }
1382
+
1383
+ static bool scan_regex_bracket_term_close(
1384
+ TSLexer *lexer,
1385
+ ScannerState *state,
1386
+ int32_t marker,
1387
+ TSSymbol candidate,
1388
+ const bool *valid_symbols,
1389
+ TSSymbol *symbol
1390
+ ) {
1391
+ if (lexer->lookahead != marker) {
1392
+ return false;
1393
+ }
1394
+
1395
+ advance(lexer);
1396
+ if (lexer->lookahead != ']') {
1397
+ return false;
1398
+ }
1399
+ consume(lexer);
1400
+ state->regex_bracket_term_state = REGEX_BRACKET_TERM_NONE;
1401
+ finish_compound_bracket_element(state);
1402
+ return emit_symbol(valid_symbols, candidate, symbol);
1403
+ }
1404
+
1405
+ enum RegexIntervalPartResult {
1406
+ REGEX_INTERVAL_PART_END,
1407
+ REGEX_INTERVAL_PART_ESCAPED_CLOSE,
1408
+ REGEX_INTERVAL_PART_INVALID,
1409
+ };
1410
+
1411
+ static enum RegexIntervalPartResult scan_regex_interval_digits(
1412
+ TSLexer *lexer,
1413
+ const ScannerState *state,
1414
+ bool escaped_close,
1415
+ bool *has_digits
1416
+ ) {
1417
+ for (;;) {
1418
+ if (is_digit(lexer->lookahead) && lexer->lookahead != state->delimiter) {
1419
+ advance(lexer);
1420
+ if (has_digits != NULL) {
1421
+ *has_digits = true;
1422
+ }
1423
+ continue;
1424
+ }
1425
+
1426
+ if (escaped_close && lexer->lookahead == '\\') {
1427
+ advance(lexer);
1428
+ if (lexer->lookahead == '}' && state->delimiter != '}') {
1429
+ return REGEX_INTERVAL_PART_ESCAPED_CLOSE;
1430
+ }
1431
+ advance_past_escaped_character(lexer);
1432
+ return REGEX_INTERVAL_PART_INVALID;
1433
+ }
1434
+
1435
+ return REGEX_INTERVAL_PART_END;
1436
+ }
1437
+ }
1438
+
1439
+ static bool
1440
+ scan_regex_interval_separator(TSLexer *lexer, const ScannerState *state) {
1441
+ if (lexer->lookahead != ',' || state->delimiter == ',') {
1442
+ return false;
1443
+ }
1444
+
1445
+ advance(lexer);
1446
+ return true;
1447
+ }
1448
+
1449
+ static bool scan_regex_interval_tail(
1450
+ TSLexer *lexer,
1451
+ const ScannerState *state,
1452
+ bool escaped_close
1453
+ ) {
1454
+ bool has_minimum = false;
1455
+ enum RegexIntervalPartResult result =
1456
+ scan_regex_interval_digits(lexer, state, escaped_close, &has_minimum);
1457
+ if (result == REGEX_INTERVAL_PART_INVALID) {
1458
+ return false;
1459
+ }
1460
+ if (result == REGEX_INTERVAL_PART_ESCAPED_CLOSE) {
1461
+ advance(lexer);
1462
+ return has_minimum;
1463
+ }
1464
+
1465
+ const bool has_separator = scan_regex_interval_separator(lexer, state);
1466
+ if (!has_minimum) {
1467
+ return false;
1468
+ }
1469
+
1470
+ if (has_separator) {
1471
+ result = scan_regex_interval_digits(lexer, state, escaped_close, NULL);
1472
+ if (result == REGEX_INTERVAL_PART_INVALID) {
1473
+ return false;
1474
+ }
1475
+ if (result == REGEX_INTERVAL_PART_ESCAPED_CLOSE) {
1476
+ advance(lexer);
1477
+ return true;
1478
+ }
1479
+ }
1480
+
1481
+ if (escaped_close) {
1482
+ if (lexer->lookahead != '\\') {
1483
+ return false;
1484
+ }
1485
+ advance(lexer);
1486
+ if (lexer->lookahead != '}' || state->delimiter == '}') {
1487
+ advance_past_escaped_character(lexer);
1488
+ return false;
1489
+ }
1490
+ }
1491
+
1492
+ if (lexer->lookahead != '}' || state->delimiter == '}') {
1493
+ return false;
1494
+ }
1495
+
1496
+ advance(lexer);
1497
+ return true;
1498
+ }
1499
+
1500
+ static bool scan_regex_interval(
1501
+ TSLexer *lexer,
1502
+ ScannerState *state,
1503
+ const bool *valid_symbols,
1504
+ TSSymbol *symbol
1505
+ ) {
1506
+ advance(lexer);
1507
+ lexer->mark_end(lexer);
1508
+ state->regex_interval_state = REGEX_INTERVAL_EXPECT_MINIMUM;
1509
+ return emit_symbol(valid_symbols, REGEX_INTERVAL_OPEN, symbol);
1510
+ }
1511
+
1512
+ static bool
1513
+ scan_invalid_interval_remainder(TSLexer *lexer, ScannerState *state);
1514
+
1515
+ #if !SED_REGEX_EXTENDED
1516
+ static bool scan_regex_after_backslash(
1517
+ TSLexer *lexer,
1518
+ ScannerState *state,
1519
+ const bool *valid_symbols,
1520
+ TSSymbol *symbol
1521
+ );
1522
+ #endif
1523
+
1524
+ static bool raw_duplication_symbol_follows(
1525
+ const TSLexer *lexer,
1526
+ const ScannerState *state
1527
+ ) {
1528
+ #if SED_REGEX_EXTENDED
1529
+ (void)state;
1530
+ return lexer->lookahead ==
1531
+ '*' ||
1532
+ lexer->lookahead ==
1533
+ '+' ||
1534
+ lexer->lookahead == '?';
1535
+ #else
1536
+ return lexer->lookahead == '*' && !state->regex_at_branch_start;
1537
+ #endif
1538
+ }
1539
+
1540
+ enum DuplicationContextScan {
1541
+ DUPLICATION_CONTEXT_SKIPPED,
1542
+ DUPLICATION_CONTEXT_TOKEN,
1543
+ DUPLICATION_CONTEXT_CONSUMED,
1544
+ };
1545
+
1546
+ static enum DuplicationContextScan scan_regex_duplication_context_marker(
1547
+ TSLexer *lexer,
1548
+ ScannerState *state,
1549
+ const bool *valid_symbols,
1550
+ TSSymbol *symbol
1551
+ ) {
1552
+ TSSymbol candidate;
1553
+ if (state->regex_at_branch_start) {
1554
+ candidate = REGEX_LEADING_DUPLICATION_MARKER;
1555
+ } else if (state->regex_duplication_state != REGEX_DUPLICATION_NONE) {
1556
+ #if SED_REGEX_EXTENDED
1557
+ if (
1558
+ state->regex_duplication_state ==
1559
+ REGEX_AFTER_DUPLICATION_SYMBOL &&
1560
+ lexer->lookahead == '?'
1561
+ ) {
1562
+ return DUPLICATION_CONTEXT_SKIPPED;
1563
+ }
1564
+ #endif
1565
+ candidate = REGEX_ADJACENT_DUPLICATION_MARKER;
1566
+ } else {
1567
+ return DUPLICATION_CONTEXT_SKIPPED;
1568
+ }
1569
+
1570
+ if (!valid_symbols[candidate]) {
1571
+ return DUPLICATION_CONTEXT_SKIPPED;
1572
+ }
1573
+
1574
+ lexer->mark_end(lexer);
1575
+ if (raw_duplication_symbol_follows(lexer, state)) {
1576
+ *symbol = candidate;
1577
+ return DUPLICATION_CONTEXT_TOKEN;
1578
+ }
1579
+
1580
+ #if SED_REGEX_EXTENDED
1581
+ if (lexer->lookahead != '{' || state->delimiter == '{') {
1582
+ return DUPLICATION_CONTEXT_SKIPPED;
1583
+ }
1584
+ advance(lexer);
1585
+ if (scan_regex_interval_tail(lexer, state, false)) {
1586
+ *symbol = candidate;
1587
+ return DUPLICATION_CONTEXT_TOKEN;
1588
+ }
1589
+ #else
1590
+ if (lexer->lookahead != '\\') {
1591
+ return DUPLICATION_CONTEXT_SKIPPED;
1592
+ }
1593
+ advance(lexer);
1594
+ if (lexer->lookahead != '{' || state->delimiter == '{') {
1595
+ return scan_regex_after_backslash(lexer, state, valid_symbols, symbol)
1596
+ ? DUPLICATION_CONTEXT_TOKEN
1597
+ : DUPLICATION_CONTEXT_CONSUMED;
1598
+ }
1599
+ advance(lexer);
1600
+ if (scan_regex_interval_tail(lexer, state, true)) {
1601
+ *symbol = candidate;
1602
+ return DUPLICATION_CONTEXT_TOKEN;
1603
+ }
1604
+ #endif
1605
+
1606
+ if (lexer->eof(lexer) && valid_symbols[REGEX_INCOMPLETE_INTERVAL]) {
1607
+ lexer->mark_end(lexer);
1608
+ state->regex_interval_state = REGEX_INTERVAL_NONE;
1609
+ *symbol = REGEX_INCOMPLETE_INTERVAL;
1610
+ return DUPLICATION_CONTEXT_TOKEN;
1611
+ }
1612
+
1613
+ if (!valid_symbols[REGEX_INVALID_INTERVAL]) {
1614
+ *symbol = candidate;
1615
+ return DUPLICATION_CONTEXT_TOKEN;
1616
+ }
1617
+ scan_invalid_interval_remainder(lexer, state);
1618
+ lexer->mark_end(lexer);
1619
+ state->regex_interval_state = REGEX_INTERVAL_NONE;
1620
+ *symbol = REGEX_INVALID_INTERVAL;
1621
+ return DUPLICATION_CONTEXT_TOKEN;
1622
+ }
1623
+
1624
+ static bool scan_raw_regex_operator(
1625
+ TSLexer *lexer,
1626
+ ScannerState *state,
1627
+ const bool *valid_symbols,
1628
+ TSSymbol *symbol
1629
+ ) {
1630
+ const int32_t character = lexer->lookahead;
1631
+
1632
+ if (character == '{') {
1633
+ #if SED_REGEX_EXTENDED
1634
+ return scan_regex_interval(lexer, state, valid_symbols, symbol);
1635
+ #else
1636
+ consume(lexer);
1637
+ return emit_symbol(valid_symbols, REGEX_LITERAL, symbol);
1638
+ #endif
1639
+ }
1640
+
1641
+ consume(lexer);
1642
+
1643
+ if (character == '*') {
1644
+ #if SED_REGEX_EXTENDED
1645
+ return emit_symbol(valid_symbols, REGEX_ZERO_OR_MORE, symbol);
1646
+ #else
1647
+ return emit_symbol(
1648
+ valid_symbols,
1649
+ state->regex_at_branch_start ? REGEX_LITERAL : REGEX_ZERO_OR_MORE,
1650
+ symbol
1651
+ );
1652
+ #endif
1653
+ }
1654
+
1655
+ #if SED_REGEX_EXTENDED
1656
+ if (character == '(') {
1657
+ return emit_symbol(valid_symbols, REGEX_GROUP_OPEN, symbol);
1658
+ }
1659
+
1660
+ if (character == ')') {
1661
+ return emit_symbol(
1662
+ valid_symbols,
1663
+ state->regex_group_depth > 0 ? REGEX_GROUP_CLOSE : REGEX_LITERAL,
1664
+ symbol
1665
+ );
1666
+ }
1667
+
1668
+ if (character == '|') {
1669
+ return emit_symbol(valid_symbols, REGEX_ALTERNATION_OPERATOR, symbol);
1670
+ }
1671
+
1672
+ if (character == '+') {
1673
+ return emit_symbol(valid_symbols, REGEX_ONE_OR_MORE, symbol);
1674
+ }
1675
+
1676
+ if (character == '?') {
1677
+ if (
1678
+ state->regex_duplication_state ==
1679
+ REGEX_AFTER_DUPLICATION_SYMBOL &&
1680
+ valid_symbols[REGEX_REPETITION_MODIFIER]
1681
+ ) {
1682
+ return emit_symbol(valid_symbols, REGEX_REPETITION_MODIFIER, symbol);
1683
+ }
1684
+ return emit_symbol(valid_symbols, REGEX_ZERO_OR_ONE, symbol);
1685
+ }
1686
+ #endif
1687
+
1688
+ return emit_symbol(valid_symbols, REGEX_LITERAL, symbol);
1689
+ }
1690
+
1691
+ static bool regex_delimiter_is_special(int32_t character) {
1692
+ #if SED_REGEX_EXTENDED
1693
+ return character ==
1694
+ '.' ||
1695
+ character ==
1696
+ '[' ||
1697
+ character ==
1698
+ '(' ||
1699
+ character ==
1700
+ ')' ||
1701
+ character ==
1702
+ '*' ||
1703
+ character ==
1704
+ '+' ||
1705
+ character ==
1706
+ '?' ||
1707
+ character ==
1708
+ '{' ||
1709
+ character ==
1710
+ '|' ||
1711
+ character ==
1712
+ '^' ||
1713
+ character == '$';
1714
+ #else
1715
+ return character ==
1716
+ '.' ||
1717
+ character ==
1718
+ '[' ||
1719
+ character ==
1720
+ '*' ||
1721
+ character ==
1722
+ '^' ||
1723
+ character == '$';
1724
+ #endif
1725
+ }
1726
+
1727
+ static bool scan_regex_escaped_delimiter(
1728
+ TSLexer *lexer,
1729
+ const bool *valid_symbols,
1730
+ TSSymbol *symbol
1731
+ ) {
1732
+ const bool special = regex_delimiter_is_special(lexer->lookahead);
1733
+ consume(lexer);
1734
+ return emit_symbol(
1735
+ valid_symbols,
1736
+ special ? REGEX_SPECIAL_ESCAPED_DELIMITER : REGEX_ESCAPED_DELIMITER,
1737
+ symbol
1738
+ );
1739
+ }
1740
+
1741
+ static bool scan_regex_escape_after_backslash(
1742
+ TSLexer *lexer,
1743
+ ScannerState *state,
1744
+ const bool *valid_symbols,
1745
+ TSSymbol *symbol
1746
+ ) {
1747
+ if (lexer->eof(lexer)) {
1748
+ return emit_symbol(valid_symbols, REGEX_INCOMPLETE_ESCAPE, symbol);
1749
+ }
1750
+
1751
+ if (lexer->lookahead == '\n') {
1752
+ return emit_symbol(valid_symbols, REGEX_FORBIDDEN_NEWLINE_ESCAPE, symbol);
1753
+ }
1754
+
1755
+ if (lexer->lookahead == state->delimiter) {
1756
+ return scan_regex_escaped_delimiter(lexer, valid_symbols, symbol);
1757
+ }
1758
+
1759
+ #if !SED_REGEX_EXTENDED
1760
+ if (lexer->lookahead == '}') {
1761
+ if (valid_symbols[REGEX_INTERVAL_CLOSE]) {
1762
+ consume(lexer);
1763
+ state->regex_interval_state = REGEX_INTERVAL_NONE;
1764
+ return emit_symbol(valid_symbols, REGEX_INTERVAL_CLOSE, symbol);
1765
+ }
1766
+ if (valid_symbols[REGEX_UNMATCHED_INTERVAL_CLOSE]) {
1767
+ consume(lexer);
1768
+ return emit_symbol(valid_symbols, REGEX_UNMATCHED_INTERVAL_CLOSE, symbol);
1769
+ }
1770
+ }
1771
+ #endif
1772
+
1773
+ if (lexer->lookahead == '(' || lexer->lookahead == ')') {
1774
+ #if !SED_REGEX_EXTENDED
1775
+ const int32_t character = lexer->lookahead;
1776
+ #endif
1777
+ consume(lexer);
1778
+ #if SED_REGEX_EXTENDED
1779
+ return emit_symbol(valid_symbols, REGEX_QUOTED_ESCAPE, symbol);
1780
+ #else
1781
+ return character == '('
1782
+ ? emit_symbol(valid_symbols, REGEX_GROUP_OPEN, symbol)
1783
+ : emit_symbol(
1784
+ valid_symbols,
1785
+ state->regex_group_depth > 0 ? REGEX_GROUP_CLOSE
1786
+ : REGEX_UNMATCHED_GROUP_CLOSE,
1787
+ symbol
1788
+ );
1789
+ #endif
1790
+ }
1791
+
1792
+ if (lexer->lookahead >= '1' && lexer->lookahead <= '9') {
1793
+ #if SED_REGEX_EXTENDED
1794
+ consume(lexer);
1795
+ return emit_symbol(valid_symbols, REGEX_NONPORTABLE_ESCAPE, symbol);
1796
+ #else
1797
+ consume(lexer);
1798
+ return emit_symbol(valid_symbols, REGEX_BACKREFERENCE, symbol);
1799
+ #endif
1800
+ }
1801
+
1802
+ if (lexer->lookahead == '{') {
1803
+ #if SED_REGEX_EXTENDED
1804
+ consume(lexer);
1805
+ return emit_symbol(valid_symbols, REGEX_QUOTED_ESCAPE, symbol);
1806
+ #else
1807
+ return scan_regex_interval(lexer, state, valid_symbols, symbol);
1808
+ #endif
1809
+ }
1810
+
1811
+ if (
1812
+ lexer->lookahead ==
1813
+ '+' ||
1814
+ lexer->lookahead ==
1815
+ '?' ||
1816
+ lexer->lookahead == '|'
1817
+ ) {
1818
+ #if SED_REGEX_EXTENDED
1819
+ consume(lexer);
1820
+ return emit_symbol(valid_symbols, REGEX_QUOTED_ESCAPE, symbol);
1821
+ #else
1822
+ const int32_t character = lexer->lookahead;
1823
+ consume(lexer);
1824
+ if (character == '|') {
1825
+ return emit_symbol(valid_symbols, REGEX_BRE_VERTICAL_LINE_ESCAPE, symbol);
1826
+ }
1827
+ return emit_symbol(
1828
+ valid_symbols,
1829
+ character == '?' ? REGEX_BRE_QUESTION_MARK_ESCAPE : REGEX_BRE_PLUS_ESCAPE,
1830
+ symbol
1831
+ );
1832
+ #endif
1833
+ }
1834
+
1835
+ if (lexer->lookahead == 'n') {
1836
+ consume(lexer);
1837
+ return emit_symbol(valid_symbols, REGEX_NEWLINE_ESCAPE, symbol);
1838
+ }
1839
+
1840
+ const int32_t character = lexer->lookahead;
1841
+ const bool quotes_regex_syntax = character ==
1842
+ '.' ||
1843
+ character ==
1844
+ '*' ||
1845
+ character ==
1846
+ '^' ||
1847
+ character ==
1848
+ '$' ||
1849
+ character ==
1850
+ '[' ||
1851
+ character ==
1852
+ '\\' ||
1853
+ character ==
1854
+ ']' ||
1855
+ (SED_REGEX_EXTENDED && character == '}');
1856
+ if (!quotes_regex_syntax) {
1857
+ consume(lexer);
1858
+ return emit_symbol(valid_symbols, REGEX_NONPORTABLE_ESCAPE, symbol);
1859
+ }
1860
+
1861
+ consume(lexer);
1862
+ return emit_symbol(valid_symbols, REGEX_QUOTED_ESCAPE, symbol);
1863
+ }
1864
+
1865
+ #if !SED_REGEX_EXTENDED
1866
+ static bool scan_regex_after_backslash(
1867
+ TSLexer *lexer,
1868
+ ScannerState *state,
1869
+ const bool *valid_symbols,
1870
+ TSSymbol *symbol
1871
+ ) {
1872
+ if (lexer->lookahead == state->delimiter) {
1873
+ return scan_regex_escaped_delimiter(lexer, valid_symbols, symbol);
1874
+ }
1875
+
1876
+ if (lexer->lookahead == ')' && valid_symbols[EMPTY_SUBEXPRESSION_MARKER]) {
1877
+ *symbol = EMPTY_SUBEXPRESSION_MARKER;
1878
+ return true;
1879
+ }
1880
+
1881
+ lexer->mark_end(lexer);
1882
+ return scan_regex_escape_after_backslash(lexer, state, valid_symbols, symbol);
1883
+ }
1884
+ #endif
1885
+
1886
+ static bool scan_regex_dup_count(
1887
+ TSLexer *lexer,
1888
+ ScannerState *state,
1889
+ const bool *valid_symbols,
1890
+ TSSymbol *symbol
1891
+ ) {
1892
+ do {
1893
+ consume(lexer);
1894
+ } while (is_digit(lexer->lookahead) && lexer->lookahead != state->delimiter);
1895
+
1896
+ if (state->regex_interval_state == REGEX_INTERVAL_EXPECT_MINIMUM) {
1897
+ state->regex_interval_state = REGEX_INTERVAL_AFTER_MINIMUM;
1898
+ } else if (state->regex_interval_state == REGEX_INTERVAL_EXPECT_MAXIMUM) {
1899
+ state->regex_interval_state = REGEX_INTERVAL_AFTER_MAXIMUM;
1900
+ }
1901
+
1902
+ return emit_symbol(valid_symbols, REGEX_DUP_COUNT, symbol);
1903
+ }
1904
+
1905
+ static bool
1906
+ scan_invalid_interval_remainder(TSLexer *lexer, ScannerState *state) {
1907
+ bool consumed_character = false;
1908
+ while (
1909
+ !lexer->eof(lexer) &&
1910
+ lexer->lookahead !=
1911
+ '\n' &&
1912
+ lexer->lookahead != state->delimiter
1913
+ ) {
1914
+ const int32_t character = lexer->lookahead;
1915
+ consume(lexer);
1916
+ consumed_character = true;
1917
+ if (character == '}') {
1918
+ break;
1919
+ }
1920
+ if (character != '\\' || lexer->eof(lexer) || lexer->lookahead == '\n') {
1921
+ continue;
1922
+ }
1923
+ const int32_t escaped = lexer->lookahead;
1924
+ consume(lexer);
1925
+ if (!SED_REGEX_EXTENDED && escaped == '}') {
1926
+ break;
1927
+ }
1928
+ }
1929
+ if (consumed_character) {
1930
+ state->regex_interval_state = REGEX_INTERVAL_NONE;
1931
+ }
1932
+ return consumed_character;
1933
+ }
1934
+
1935
+ #if SED_REGEX_EXTENDED
1936
+ static bool scan_empty_regex_construct(
1937
+ TSLexer *lexer,
1938
+ const ScannerState *state,
1939
+ const bool *valid_symbols,
1940
+ TSSymbol *symbol
1941
+ ) {
1942
+ if (
1943
+ state->regex_group_depth >
1944
+ 0 &&
1945
+ lexer->lookahead ==
1946
+ ')' &&
1947
+ valid_symbols[EMPTY_SUBEXPRESSION_MARKER]
1948
+ ) {
1949
+ return emit_missing_marker(
1950
+ lexer,
1951
+ valid_symbols,
1952
+ EMPTY_SUBEXPRESSION_MARKER,
1953
+ symbol
1954
+ );
1955
+ }
1956
+ if (
1957
+ valid_symbols[EMPTY_ALTERNATIVE_MARKER] &&
1958
+ (lexer->lookahead ==
1959
+ '|' ||
1960
+ (state->regex_group_depth > 0 && lexer->lookahead == ')'))
1961
+ ) {
1962
+ return emit_missing_marker(
1963
+ lexer,
1964
+ valid_symbols,
1965
+ EMPTY_ALTERNATIVE_MARKER,
1966
+ symbol
1967
+ );
1968
+ }
1969
+ return false;
1970
+ }
1971
+ #endif
1972
+
1973
+ static bool scan_regex_token(
1974
+ TSLexer *lexer,
1975
+ ScannerState *state,
1976
+ const bool *valid_symbols,
1977
+ TSSymbol *symbol
1978
+ ) {
1979
+ switch (scan_regex_duplication_context_marker(
1980
+ lexer,
1981
+ state,
1982
+ valid_symbols,
1983
+ symbol
1984
+ )) {
1985
+ case DUPLICATION_CONTEXT_TOKEN:
1986
+ return true;
1987
+ case DUPLICATION_CONTEXT_CONSUMED:
1988
+ return false;
1989
+ case DUPLICATION_CONTEXT_SKIPPED:
1990
+ break;
1991
+ }
1992
+
1993
+ #if !SED_REGEX_EXTENDED
1994
+ if (lexer->lookahead == '\\' && valid_symbols[EMPTY_SUBEXPRESSION_MARKER]) {
1995
+ lexer->mark_end(lexer);
1996
+ advance(lexer);
1997
+ return scan_regex_after_backslash(lexer, state, valid_symbols, symbol);
1998
+ }
1999
+ #else
2000
+ if (scan_empty_regex_construct(lexer, state, valid_symbols, symbol)) {
2001
+ return true;
2002
+ }
2003
+ #endif
2004
+
2005
+ if (
2006
+ valid_symbols[REGEX_DUP_COUNT] &&
2007
+ is_digit(lexer->lookahead) &&
2008
+ lexer->lookahead != state->delimiter
2009
+ ) {
2010
+ return scan_regex_dup_count(lexer, state, valid_symbols, symbol);
2011
+ }
2012
+
2013
+ if (
2014
+ valid_symbols[REGEX_INTERVAL_SEPARATOR] &&
2015
+ lexer->lookahead ==
2016
+ ',' &&
2017
+ lexer->lookahead != state->delimiter
2018
+ ) {
2019
+ consume(lexer);
2020
+ state->regex_interval_state = REGEX_INTERVAL_EXPECT_MAXIMUM;
2021
+ *symbol = REGEX_INTERVAL_SEPARATOR;
2022
+ return true;
2023
+ }
2024
+
2025
+ #if SED_REGEX_EXTENDED
2026
+ if (
2027
+ valid_symbols[REGEX_INTERVAL_CLOSE] &&
2028
+ lexer->lookahead ==
2029
+ '}' &&
2030
+ lexer->lookahead != state->delimiter
2031
+ ) {
2032
+ consume(lexer);
2033
+ state->regex_interval_state = REGEX_INTERVAL_NONE;
2034
+ *symbol = REGEX_INTERVAL_CLOSE;
2035
+ return true;
2036
+ }
2037
+ #else
2038
+ if (
2039
+ state->regex_interval_state !=
2040
+ REGEX_INTERVAL_NONE &&
2041
+ lexer->lookahead == '\\'
2042
+ ) {
2043
+ advance(lexer);
2044
+ if (
2045
+ valid_symbols[REGEX_INTERVAL_CLOSE] &&
2046
+ lexer->lookahead ==
2047
+ '}' &&
2048
+ lexer->lookahead != state->delimiter
2049
+ ) {
2050
+ consume(lexer);
2051
+ state->regex_interval_state = REGEX_INTERVAL_NONE;
2052
+ *symbol = REGEX_INTERVAL_CLOSE;
2053
+ return true;
2054
+ }
2055
+ if (lexer->eof(lexer) && valid_symbols[REGEX_INCOMPLETE_INTERVAL]) {
2056
+ lexer->mark_end(lexer);
2057
+ state->regex_interval_state = REGEX_INTERVAL_NONE;
2058
+ *symbol = REGEX_INCOMPLETE_INTERVAL;
2059
+ return true;
2060
+ }
2061
+ if (!valid_symbols[REGEX_INVALID_INTERVAL]) {
2062
+ return false;
2063
+ }
2064
+ if (lexer->lookahead == '}') {
2065
+ advance(lexer);
2066
+ } else {
2067
+ advance_past_escaped_character(lexer);
2068
+ scan_invalid_interval_remainder(lexer, state);
2069
+ }
2070
+ lexer->mark_end(lexer);
2071
+ state->regex_interval_state = REGEX_INTERVAL_NONE;
2072
+ *symbol = REGEX_INVALID_INTERVAL;
2073
+ return true;
2074
+ }
2075
+ #endif
2076
+
2077
+ if (
2078
+ state->regex_interval_state !=
2079
+ REGEX_INTERVAL_NONE &&
2080
+ valid_symbols[REGEX_INVALID_INTERVAL] &&
2081
+ scan_invalid_interval_remainder(lexer, state)
2082
+ ) {
2083
+ *symbol = REGEX_INVALID_INTERVAL;
2084
+ return true;
2085
+ }
2086
+
2087
+ const bool inside_bracket = regex_is_inside_bracket(state);
2088
+ if (inside_bracket) {
2089
+ if (
2090
+ valid_symbols[REGEX_CLASS_NAME] ||
2091
+ valid_symbols[REGEX_COLL_ELEM_SINGLE] ||
2092
+ valid_symbols[REGEX_COLL_ELEM_MULTI] ||
2093
+ valid_symbols[REGEX_META_CHAR]
2094
+ ) {
2095
+ const int32_t close_marker =
2096
+ state->regex_bracket_term_state == REGEX_BRACKET_TERM_COLON ? ':'
2097
+ : state->regex_bracket_term_state == REGEX_BRACKET_TERM_DOT ? '.'
2098
+ : '=';
2099
+ return scan_regex_bracket_term_content(
2100
+ lexer,
2101
+ state,
2102
+ close_marker,
2103
+ valid_symbols,
2104
+ symbol
2105
+ );
2106
+ }
2107
+ if (
2108
+ state->regex_bracket_term_state !=
2109
+ REGEX_BRACKET_TERM_NONE &&
2110
+ lexer->lookahead ==
2111
+ ']' &&
2112
+ valid_symbols[REGEX_MALFORMED_BRACKET_TERM]
2113
+ ) {
2114
+ lexer->mark_end(lexer);
2115
+ state->regex_bracket_term_state = REGEX_BRACKET_TERM_NONE;
2116
+ finish_compound_bracket_element(state);
2117
+ *symbol = REGEX_MALFORMED_BRACKET_TERM;
2118
+ return true;
2119
+ }
2120
+ if (valid_symbols[REGEX_COLON_CLOSE] && lexer->lookahead == ':') {
2121
+ return scan_regex_bracket_term_close(
2122
+ lexer,
2123
+ state,
2124
+ ':',
2125
+ REGEX_COLON_CLOSE,
2126
+ valid_symbols,
2127
+ symbol
2128
+ );
2129
+ }
2130
+ if (valid_symbols[REGEX_DOT_CLOSE] && lexer->lookahead == '.') {
2131
+ return scan_regex_bracket_term_close(
2132
+ lexer,
2133
+ state,
2134
+ '.',
2135
+ REGEX_DOT_CLOSE,
2136
+ valid_symbols,
2137
+ symbol
2138
+ );
2139
+ }
2140
+ if (valid_symbols[REGEX_EQUAL_CLOSE] && lexer->lookahead == '=') {
2141
+ return scan_regex_bracket_term_close(
2142
+ lexer,
2143
+ state,
2144
+ '=',
2145
+ REGEX_EQUAL_CLOSE,
2146
+ valid_symbols,
2147
+ symbol
2148
+ );
2149
+ }
2150
+ }
2151
+
2152
+ const enum LiteralScanResult literal_result =
2153
+ scan_regex_literal(lexer, state);
2154
+ if (literal_result == LITERAL_SCAN_TOKEN) {
2155
+ return emit_symbol(
2156
+ valid_symbols,
2157
+ inside_bracket ? REGEX_BRACKET_LITERAL : REGEX_LITERAL,
2158
+ symbol
2159
+ );
2160
+ }
2161
+ if (literal_result == LITERAL_SCAN_LINE_END) {
2162
+ return emit_unterminated(
2163
+ state,
2164
+ valid_symbols,
2165
+ regex_unterminated_symbol(state->mode, lexer->eof(lexer)),
2166
+ symbol
2167
+ );
2168
+ }
2169
+
2170
+ if (state->regex_state == REGEX_OUTSIDE_BRACKET) {
2171
+ if (lexer->lookahead == '^') {
2172
+ consume(lexer);
2173
+ #if !SED_REGEX_EXTENDED
2174
+ if (
2175
+ state->regex_group_depth >
2176
+ 0 &&
2177
+ state->regex_at_branch_start &&
2178
+ !state->regex_after_anchor
2179
+ ) {
2180
+ return emit_symbol(
2181
+ valid_symbols,
2182
+ REGEX_BRE_SUBEXPRESSION_CARET,
2183
+ symbol
2184
+ );
2185
+ }
2186
+ #endif
2187
+ const bool is_beginning_anchor = SED_REGEX_EXTENDED ||
2188
+ (state->regex_at_branch_start && !state->regex_after_anchor);
2189
+ const TSSymbol candidate =
2190
+ is_beginning_anchor ? REGEX_BEGINNING_ANCHOR : REGEX_LITERAL;
2191
+ return emit_symbol(valid_symbols, candidate, symbol);
2192
+ }
2193
+
2194
+ if (lexer->lookahead == '$') {
2195
+ bool inspected_bre_escape = false;
2196
+ consume(lexer);
2197
+ #if !SED_REGEX_EXTENDED
2198
+ if (lexer->lookahead == '\\') {
2199
+ inspected_bre_escape = true;
2200
+ advance(lexer);
2201
+ if (state->regex_group_depth > 0 && lexer->lookahead == ')') {
2202
+ return emit_symbol(
2203
+ valid_symbols,
2204
+ REGEX_BRE_SUBEXPRESSION_DOLLAR,
2205
+ symbol
2206
+ );
2207
+ }
2208
+ }
2209
+ #endif
2210
+ const bool at_branch_end = SED_REGEX_EXTENDED ||
2211
+ (!inspected_bre_escape &&
2212
+ (lexer->eof(lexer) ||
2213
+ lexer->lookahead ==
2214
+ '\n' ||
2215
+ lexer->lookahead == state->delimiter));
2216
+ const TSSymbol candidate =
2217
+ at_branch_end ? REGEX_END_ANCHOR : REGEX_LITERAL;
2218
+ return emit_symbol(valid_symbols, candidate, symbol);
2219
+ }
2220
+
2221
+ if (lexer->lookahead == '.') {
2222
+ consume(lexer);
2223
+ return emit_symbol(valid_symbols, REGEX_PERIOD, symbol);
2224
+ }
2225
+
2226
+ if (lexer->lookahead == '\\') {
2227
+ advance(lexer);
2228
+ lexer->mark_end(lexer);
2229
+ return scan_regex_escape_after_backslash(
2230
+ lexer,
2231
+ state,
2232
+ valid_symbols,
2233
+ symbol
2234
+ );
2235
+ }
2236
+
2237
+ if (
2238
+ lexer->lookahead ==
2239
+ '(' ||
2240
+ lexer->lookahead ==
2241
+ ')' ||
2242
+ lexer->lookahead ==
2243
+ '*' ||
2244
+ lexer->lookahead ==
2245
+ '+' ||
2246
+ lexer->lookahead ==
2247
+ '?' ||
2248
+ lexer->lookahead ==
2249
+ '|' ||
2250
+ lexer->lookahead == '{'
2251
+ ) {
2252
+ return scan_raw_regex_operator(lexer, state, valid_symbols, symbol);
2253
+ }
2254
+
2255
+ if (lexer->lookahead == '[') {
2256
+ consume(lexer);
2257
+ reset_bracket_tracking(state);
2258
+ state->regex_state = REGEX_BRACKET_FIRST;
2259
+ return emit_symbol(valid_symbols, REGEX_BRACKET_OPEN, symbol);
2260
+ }
2261
+
2262
+ return false;
2263
+ }
2264
+
2265
+ if (state->regex_state == REGEX_BRACKET_FIRST && lexer->lookahead == '^') {
2266
+ consume(lexer);
2267
+ state->regex_state = REGEX_BRACKET_AFTER_CARET;
2268
+ return emit_symbol(valid_symbols, REGEX_BRACKET_NEGATION, symbol);
2269
+ }
2270
+
2271
+ if (state->regex_state == REGEX_BRACKET_BODY && lexer->lookahead == ']') {
2272
+ commit_pending_bracket_element(state);
2273
+ if (
2274
+ bracket_expression_is_ambiguous(state) &&
2275
+ valid_symbols[AMBIGUOUS_BRACKET_EXPRESSION_MARKER]
2276
+ ) {
2277
+ lexer->mark_end(lexer);
2278
+ *symbol = AMBIGUOUS_BRACKET_EXPRESSION_MARKER;
2279
+ return true;
2280
+ }
2281
+
2282
+ consume(lexer);
2283
+ state->regex_state = REGEX_OUTSIDE_BRACKET;
2284
+ reset_bracket_tracking(state);
2285
+ return emit_symbol(valid_symbols, REGEX_BRACKET_CLOSE, symbol);
2286
+ }
2287
+
2288
+ if (state->regex_state == REGEX_BRACKET_BODY && lexer->lookahead == '-') {
2289
+ lexer->mark_end(lexer);
2290
+ advance(lexer);
2291
+ if (
2292
+ valid_symbols[NONPORTABLE_RANGE_START_MARKER] &&
2293
+ !lexer->eof(lexer) &&
2294
+ lexer->lookahead !=
2295
+ '\n' &&
2296
+ lexer->lookahead != ']'
2297
+ ) {
2298
+ *symbol = NONPORTABLE_RANGE_START_MARKER;
2299
+ return true;
2300
+ }
2301
+ lexer->mark_end(lexer);
2302
+
2303
+ TSSymbol candidate;
2304
+ if (valid_symbols[REGEX_BRACKET_RANGE_END_HYPHEN]) {
2305
+ candidate = REGEX_BRACKET_RANGE_END_HYPHEN;
2306
+ } else if (
2307
+ lexer->eof(lexer) || lexer->lookahead == '\n' || lexer->lookahead == ']'
2308
+ ) {
2309
+ candidate = REGEX_BRACKET_TRAILING_HYPHEN;
2310
+ } else {
2311
+ candidate = REGEX_BRACKET_HYPHEN;
2312
+ }
2313
+ if (emit_symbol(valid_symbols, candidate, symbol)) {
2314
+ if (candidate == REGEX_BRACKET_RANGE_END_HYPHEN) {
2315
+ state->regex_bracket_pending_element = REGEX_BRACKET_PENDING_NONE;
2316
+ state->regex_bracket_range_pending = false;
2317
+ record_bracket_element(state, REGEX_BRACKET_PENDING_OTHER);
2318
+ } else if (candidate == REGEX_BRACKET_TRAILING_HYPHEN) {
2319
+ commit_pending_bracket_element(state);
2320
+ record_bracket_element(state, REGEX_BRACKET_PENDING_OTHER);
2321
+ } else {
2322
+ state->regex_bracket_pending_element = REGEX_BRACKET_PENDING_NONE;
2323
+ state->regex_bracket_range_pending = true;
2324
+ }
2325
+ return true;
2326
+ }
2327
+ if (emit_symbol(valid_symbols, REGEX_SHARED_RANGE_ENDPOINT, symbol)) {
2328
+ commit_pending_bracket_element(state);
2329
+ state->regex_bracket_range_pending = false;
2330
+ return true;
2331
+ }
2332
+ return false;
2333
+ }
2334
+
2335
+ if (lexer->lookahead == '[') {
2336
+ return scan_regex_bracket_opener(lexer, state, valid_symbols, symbol);
2337
+ }
2338
+
2339
+ return false;
2340
+ }
2341
+
2342
+ static enum LiteralScanResult scan_operand_literal(
2343
+ TSLexer *lexer,
2344
+ const ScannerState *state,
2345
+ bool ampersand_is_special
2346
+ ) {
2347
+ bool consumed = false;
2348
+ lexer->mark_end(lexer);
2349
+
2350
+ for (;;) {
2351
+ if (lexer->eof(lexer) || lexer->lookahead == '\n') {
2352
+ return consumed ? LITERAL_SCAN_TOKEN : LITERAL_SCAN_LINE_END;
2353
+ }
2354
+
2355
+ if (
2356
+ lexer->lookahead ==
2357
+ state->delimiter ||
2358
+ lexer->lookahead ==
2359
+ '\\' ||
2360
+ (ampersand_is_special && lexer->lookahead == '&')
2361
+ ) {
2362
+ return consumed ? LITERAL_SCAN_TOKEN : LITERAL_SCAN_NONE;
2363
+ }
2364
+
2365
+ consume(lexer);
2366
+ consumed = true;
2367
+ }
2368
+ }
2369
+
2370
+ static bool scan_replacement_escape(
2371
+ TSLexer *lexer,
2372
+ const ScannerState *state,
2373
+ const bool *valid_symbols,
2374
+ TSSymbol *symbol
2375
+ ) {
2376
+ advance(lexer);
2377
+ lexer->mark_end(lexer);
2378
+
2379
+ if (lexer->eof(lexer)) {
2380
+ return emit_symbol(valid_symbols, REPLACEMENT_INCOMPLETE_ESCAPE, symbol);
2381
+ }
2382
+
2383
+ if (lexer->lookahead == '\n') {
2384
+ consume(lexer);
2385
+ return emit_symbol(valid_symbols, REPLACEMENT_ESCAPED_NEWLINE, symbol);
2386
+ }
2387
+
2388
+ TSSymbol candidate = REPLACEMENT_ESCAPE_SEQUENCE;
2389
+ if (
2390
+ lexer->lookahead !=
2391
+ state->delimiter &&
2392
+ lexer->lookahead !=
2393
+ '&' &&
2394
+ lexer->lookahead !=
2395
+ '\\' &&
2396
+ !is_digit(lexer->lookahead)
2397
+ ) {
2398
+ consume(lexer);
2399
+ return emit_symbol(valid_symbols, REPLACEMENT_NONPORTABLE_ESCAPE, symbol);
2400
+ }
2401
+ if (lexer->lookahead == state->delimiter) {
2402
+ candidate = state->delimiter == '&'
2403
+ ? REPLACEMENT_AMPERSAND_ESCAPED_DELIMITER
2404
+ : REPLACEMENT_ESCAPED_DELIMITER;
2405
+ } else if (is_digit(lexer->lookahead)) {
2406
+ candidate = REPLACEMENT_BACKREFERENCE;
2407
+ }
2408
+
2409
+ consume(lexer);
2410
+ return emit_symbol(valid_symbols, candidate, symbol);
2411
+ }
2412
+
2413
+ static bool scan_replacement_token(
2414
+ TSLexer *lexer,
2415
+ ScannerState *state,
2416
+ const bool *valid_symbols,
2417
+ TSSymbol *symbol
2418
+ ) {
2419
+ const enum LiteralScanResult literal_result =
2420
+ scan_operand_literal(lexer, state, true);
2421
+ if (literal_result == LITERAL_SCAN_TOKEN) {
2422
+ return emit_symbol(valid_symbols, REPLACEMENT_LITERAL, symbol);
2423
+ }
2424
+ if (literal_result == LITERAL_SCAN_LINE_END) {
2425
+ return emit_unterminated(
2426
+ state,
2427
+ valid_symbols,
2428
+ lexer->eof(lexer) ? REPLACEMENT_UNTERMINATED
2429
+ : REPLACEMENT_LINE_UNTERMINATED,
2430
+ symbol
2431
+ );
2432
+ }
2433
+
2434
+ if (lexer->lookahead == '\\') {
2435
+ return scan_replacement_escape(lexer, state, valid_symbols, symbol);
2436
+ }
2437
+
2438
+ if (lexer->lookahead == '&') {
2439
+ consume(lexer);
2440
+ return emit_symbol(valid_symbols, REPLACEMENT_MATCH_REFERENCE, symbol);
2441
+ }
2442
+
2443
+ return false;
2444
+ }
2445
+
2446
+ static TSSymbol
2447
+ translate_unterminated_symbol(enum ScannerMode mode, bool at_end_of_source) {
2448
+ if (mode == MODE_TRANSLATE_SOURCE) {
2449
+ return at_end_of_source ? TRANSLATE_UNTERMINATED_SOURCE
2450
+ : TRANSLATE_LINE_UNTERMINATED_SOURCE;
2451
+ }
2452
+ return at_end_of_source ? TRANSLATE_UNTERMINATED_DESTINATION
2453
+ : TRANSLATE_LINE_UNTERMINATED_DESTINATION;
2454
+ }
2455
+
2456
+ static bool scan_translate_escape(
2457
+ TSLexer *lexer,
2458
+ const ScannerState *state,
2459
+ const bool *valid_symbols,
2460
+ TSSymbol *symbol
2461
+ ) {
2462
+ advance(lexer);
2463
+ lexer->mark_end(lexer);
2464
+
2465
+ if (lexer->eof(lexer)) {
2466
+ return emit_symbol(valid_symbols, TRANSLATE_INCOMPLETE_ESCAPE, symbol);
2467
+ }
2468
+
2469
+ if (lexer->lookahead == '\n') {
2470
+ return emit_symbol(valid_symbols, TRANSLATE_NONPORTABLE_ESCAPE, symbol);
2471
+ }
2472
+
2473
+ if (
2474
+ lexer->lookahead !=
2475
+ 'n' &&
2476
+ lexer->lookahead !=
2477
+ '\\' &&
2478
+ (lexer->lookahead != state->delimiter || state->delimiter == 'n')
2479
+ ) {
2480
+ consume(lexer);
2481
+ return emit_symbol(valid_symbols, TRANSLATE_NONPORTABLE_ESCAPE, symbol);
2482
+ }
2483
+ const TSSymbol candidate = lexer->lookahead == 'n' || lexer->lookahead == '\\'
2484
+ ? TRANSLATE_ESCAPE
2485
+ : TRANSLATE_ESCAPED_DELIMITER;
2486
+ consume(lexer);
2487
+ return emit_symbol(valid_symbols, candidate, symbol);
2488
+ }
2489
+
2490
+ static bool scan_translate_token(
2491
+ TSLexer *lexer,
2492
+ ScannerState *state,
2493
+ const bool *valid_symbols,
2494
+ TSSymbol *symbol
2495
+ ) {
2496
+ const enum LiteralScanResult literal_result =
2497
+ scan_operand_literal(lexer, state, false);
2498
+ if (literal_result == LITERAL_SCAN_TOKEN) {
2499
+ return emit_symbol(valid_symbols, TRANSLATE_LITERAL, symbol);
2500
+ }
2501
+ if (literal_result == LITERAL_SCAN_LINE_END) {
2502
+ return emit_unterminated(
2503
+ state,
2504
+ valid_symbols,
2505
+ translate_unterminated_symbol(state->mode, lexer->eof(lexer)),
2506
+ symbol
2507
+ );
2508
+ }
2509
+
2510
+ if (lexer->lookahead == '\\') {
2511
+ return scan_translate_escape(lexer, state, valid_symbols, symbol);
2512
+ }
2513
+
2514
+ return false;
2515
+ }
2516
+
2517
+ static bool sed_scanner_scan_impl(
2518
+ ScannerState *state,
2519
+ TSLexer *lexer,
2520
+ const bool *valid_symbols,
2521
+ TSSymbol *symbol
2522
+ ) {
2523
+ if (valid_symbols[ERROR_SENTINEL]) {
2524
+ return false;
2525
+ }
2526
+
2527
+ if (state->mode == MODE_TEXT) {
2528
+ return scan_text_token(lexer, state, valid_symbols, symbol);
2529
+ }
2530
+
2531
+ #if !SED_REGEX_EXTENDED
2532
+ if (
2533
+ is_regex_mode(state->mode) &&
2534
+ (emit_missing_marker(
2535
+ lexer,
2536
+ valid_symbols,
2537
+ BRE_VERTICAL_LINE_ESCAPE_MARKER,
2538
+ symbol
2539
+ ) ||
2540
+ emit_missing_marker(
2541
+ lexer,
2542
+ valid_symbols,
2543
+ BRE_QUESTION_MARK_ESCAPE_MARKER,
2544
+ symbol
2545
+ ) ||
2546
+ emit_missing_marker(
2547
+ lexer,
2548
+ valid_symbols,
2549
+ BRE_PLUS_ESCAPE_MARKER,
2550
+ symbol
2551
+ ) ||
2552
+ emit_missing_marker(
2553
+ lexer,
2554
+ valid_symbols,
2555
+ UNMATCHED_INTERVAL_CLOSE_MARKER,
2556
+ symbol
2557
+ ))
2558
+ ) {
2559
+ return true;
2560
+ }
2561
+ #endif
2562
+
2563
+ if (
2564
+ is_regex_mode(state->mode) &&
2565
+ state->regex_state ==
2566
+ REGEX_OUTSIDE_BRACKET &&
2567
+ state->regex_group_depth >
2568
+ 0 &&
2569
+ !state->regex_after_alternation &&
2570
+ (lexer->eof(lexer) ||
2571
+ lexer->lookahead ==
2572
+ '\n' ||
2573
+ lexer->lookahead == state->delimiter)
2574
+ ) {
2575
+ const TSSymbol candidate = lexer->eof(lexer)
2576
+ ? MISSING_SUBEXPRESSION_MARKER
2577
+ : MISSING_SUBEXPRESSION_PLACEHOLDER_MARKER;
2578
+ if (valid_symbols[candidate]) {
2579
+ lexer->mark_end(lexer);
2580
+ *symbol = candidate;
2581
+ return true;
2582
+ }
2583
+ }
2584
+
2585
+ if (
2586
+ is_regex_mode(state->mode) &&
2587
+ (state->regex_state ==
2588
+ REGEX_BRACKET_FIRST ||
2589
+ state->regex_state == REGEX_BRACKET_AFTER_CARET) &&
2590
+ (lexer->eof(lexer) || lexer->lookahead == '\n')
2591
+ ) {
2592
+ const TSSymbol candidate = lexer->eof(lexer)
2593
+ ? INCOMPLETE_BRACKET_LIST_MARKER
2594
+ : MISSING_BRACKET_LIST_MARKER;
2595
+ if (valid_symbols[candidate]) {
2596
+ lexer->mark_end(lexer);
2597
+ *symbol = candidate;
2598
+ return true;
2599
+ }
2600
+ }
2601
+
2602
+ if (
2603
+ is_regex_mode(state->mode) &&
2604
+ state->regex_bracket_term_state !=
2605
+ REGEX_BRACKET_TERM_NONE &&
2606
+ (lexer->eof(lexer) || lexer->lookahead == '\n')
2607
+ ) {
2608
+ const TSSymbol candidate = lexer->eof(lexer) ? REGEX_INCOMPLETE_BRACKET_TERM
2609
+ : REGEX_MALFORMED_BRACKET_TERM;
2610
+ if (valid_symbols[candidate]) {
2611
+ lexer->mark_end(lexer);
2612
+ state->regex_bracket_term_state = REGEX_BRACKET_TERM_NONE;
2613
+ finish_compound_bracket_element(state);
2614
+ *symbol = candidate;
2615
+ return true;
2616
+ }
2617
+ }
2618
+
2619
+ if (
2620
+ is_regex_mode(state->mode) &&
2621
+ regex_is_inside_bracket(state) &&
2622
+ (lexer->eof(lexer) || lexer->lookahead == '\n')
2623
+ ) {
2624
+ const TSSymbol candidate = lexer->eof(lexer)
2625
+ ? INCOMPLETE_BRACKET_EXPRESSION_MARKER
2626
+ : UNCLOSED_BRACKET_EXPRESSION_MARKER;
2627
+ if (valid_symbols[candidate]) {
2628
+ lexer->mark_end(lexer);
2629
+ state->regex_state = REGEX_OUTSIDE_BRACKET;
2630
+ reset_bracket_tracking(state);
2631
+ *symbol = candidate;
2632
+ return true;
2633
+ }
2634
+ }
2635
+
2636
+ #if SED_REGEX_EXTENDED
2637
+ if (
2638
+ is_regex_mode(state->mode) &&
2639
+ state->regex_state ==
2640
+ REGEX_OUTSIDE_BRACKET &&
2641
+ state->regex_after_alternation &&
2642
+ (lexer->lookahead ==
2643
+ state->delimiter ||
2644
+ lexer->lookahead ==
2645
+ '\n' ||
2646
+ lexer->eof(lexer))
2647
+ ) {
2648
+ const TSSymbol candidate = lexer->eof(lexer) ? INCOMPLETE_ALTERNATIVE_MARKER
2649
+ : EMPTY_ALTERNATIVE_MARKER;
2650
+ if (valid_symbols[candidate]) {
2651
+ lexer->mark_end(lexer);
2652
+ state->regex_after_alternation = false;
2653
+ *symbol = candidate;
2654
+ return true;
2655
+ }
2656
+ }
2657
+ #endif
2658
+
2659
+ if (
2660
+ is_regex_mode(state->mode) &&
2661
+ state->regex_interval_state !=
2662
+ REGEX_INTERVAL_NONE &&
2663
+ (lexer->lookahead ==
2664
+ state->delimiter ||
2665
+ lexer->lookahead ==
2666
+ '\n' ||
2667
+ #if !SED_REGEX_EXTENDED
2668
+ (state->delimiter == '}' && lexer->lookahead == '\\') ||
2669
+ #endif
2670
+ lexer->eof(lexer))
2671
+ ) {
2672
+ const TSSymbol candidate =
2673
+ lexer->eof(lexer) ? REGEX_INCOMPLETE_INTERVAL : REGEX_INVALID_INTERVAL;
2674
+ if (valid_symbols[candidate]) {
2675
+ lexer->mark_end(lexer);
2676
+ state->regex_interval_state = REGEX_INTERVAL_NONE;
2677
+ *symbol = candidate;
2678
+ return true;
2679
+ }
2680
+ }
2681
+
2682
+ if (
2683
+ is_regex_mode(state->mode) &&
2684
+ state->regex_state ==
2685
+ REGEX_OUTSIDE_BRACKET &&
2686
+ (lexer->lookahead == '\n' || lexer->eof(lexer))
2687
+ ) {
2688
+ if (state->regex_group_depth > 0) {
2689
+ const TSSymbol candidate =
2690
+ lexer->eof(lexer) ? REGEX_INCOMPLETE_GROUP : REGEX_UNCLOSED_GROUP;
2691
+ if (valid_symbols[candidate]) {
2692
+ lexer->mark_end(lexer);
2693
+ state->regex_group_depth--;
2694
+ *symbol = candidate;
2695
+ return true;
2696
+ }
2697
+ }
2698
+ }
2699
+
2700
+ const bool delimiter_is_active = state->mode !=
2701
+ MODE_NONE &&
2702
+ state->mode !=
2703
+ MODE_TEXT &&
2704
+ lexer->lookahead ==
2705
+ state->delimiter &&
2706
+ (!is_regex_mode(state->mode) ||
2707
+ state->regex_state == REGEX_OUTSIDE_BRACKET);
2708
+ if (delimiter_is_active) {
2709
+ if (state->regex_group_depth > 0 && valid_symbols[REGEX_UNCLOSED_GROUP]) {
2710
+ state->regex_group_depth--;
2711
+ *symbol = REGEX_UNCLOSED_GROUP;
2712
+ return true;
2713
+ }
2714
+ return scan_active_mode_delimiter(lexer, state, valid_symbols, symbol);
2715
+ }
2716
+
2717
+ switch (state->mode) {
2718
+ case MODE_REGEX_ADDRESS:
2719
+ case MODE_SUBSTITUTE_PATTERN:
2720
+ return scan_regex_token(lexer, state, valid_symbols, symbol);
2721
+ case MODE_SUBSTITUTE_REPLACEMENT:
2722
+ return scan_replacement_token(lexer, state, valid_symbols, symbol);
2723
+ case MODE_TRANSLATE_SOURCE:
2724
+ case MODE_TRANSLATE_DESTINATION:
2725
+ return scan_translate_token(lexer, state, valid_symbols, symbol);
2726
+ case MODE_TEXT:
2727
+ return false;
2728
+ case MODE_NONE:
2729
+ break;
2730
+ }
2731
+
2732
+ if (valid_symbols[LINE_WORD] && scan_to_physical_line_end(lexer, false)) {
2733
+ *symbol = LINE_WORD;
2734
+ return true;
2735
+ }
2736
+
2737
+ if (
2738
+ valid_symbols[SUBSTITUTION_WFILE_ARGUMENT] &&
2739
+ scan_substitution_wfile_argument(lexer)
2740
+ ) {
2741
+ *symbol = SUBSTITUTION_WFILE_ARGUMENT;
2742
+ return true;
2743
+ }
2744
+
2745
+ if (valid_symbols[FILE_ARGUMENT] && scan_file_argument(lexer)) {
2746
+ *symbol = FILE_ARGUMENT;
2747
+ return true;
2748
+ }
2749
+
2750
+ if (
2751
+ valid_symbols[INVALID_SUBSTITUTION_FLAG] &&
2752
+ !is_blank(lexer->lookahead) &&
2753
+ !is_digit(lexer->lookahead) &&
2754
+ lexer->lookahead !=
2755
+ 'g' &&
2756
+ lexer->lookahead !=
2757
+ 'i' &&
2758
+ lexer->lookahead !=
2759
+ 'p' &&
2760
+ lexer->lookahead !=
2761
+ 'w' &&
2762
+ lexer->lookahead !=
2763
+ ';' &&
2764
+ lexer->lookahead !=
2765
+ '}' &&
2766
+ lexer->lookahead !=
2767
+ '\n' &&
2768
+ !lexer->eof(lexer)
2769
+ ) {
2770
+ consume(lexer);
2771
+ *symbol = INVALID_SUBSTITUTION_FLAG;
2772
+ return true;
2773
+ }
2774
+
2775
+ if (valid_symbols[TEXT_COMMAND_START] && lexer->lookahead == '\\') {
2776
+ if (scan_text_command_start(lexer, state)) {
2777
+ *symbol = TEXT_COMMAND_START;
2778
+ return true;
2779
+ }
2780
+ const TSSymbol introducer_marker = lexer->eof(lexer)
2781
+ ? MISSING_TEXT_INTRODUCER_MARKER
2782
+ : NONCONFORMING_MISSING_TEXT_INTRODUCER_MARKER;
2783
+ return emit_symbol(valid_symbols, introducer_marker, symbol);
2784
+ }
2785
+
2786
+ if (valid_symbols[DEFAULT_OUTPUT_SUPPRESSION] && lexer->lookahead == 'n') {
2787
+ consume(lexer);
2788
+ *symbol = DEFAULT_OUTPUT_SUPPRESSION;
2789
+ return true;
2790
+ }
2791
+
2792
+ if (valid_symbols[COMMENT_TEXT] && scan_to_physical_line_end(lexer, false)) {
2793
+ *symbol = COMMENT_TEXT;
2794
+ return true;
2795
+ }
2796
+
2797
+ if (
2798
+ valid_symbols[RESERVED_UNKNOWN_FUNCTION] &&
2799
+ scan_reserved_unknown_function(lexer)
2800
+ ) {
2801
+ *symbol = RESERVED_UNKNOWN_FUNCTION;
2802
+ return true;
2803
+ }
2804
+
2805
+ if (
2806
+ valid_symbols[REGEX_ADDRESS_START] &&
2807
+ lexer->lookahead ==
2808
+ '/' &&
2809
+ scan_simple_delimiter(lexer, state, MODE_REGEX_ADDRESS)
2810
+ ) {
2811
+ *symbol = REGEX_ADDRESS_START;
2812
+ return true;
2813
+ }
2814
+
2815
+ if (valid_symbols[ESCAPED_REGEX_ADDRESS_START]) {
2816
+ if (scan_simple_delimiter(lexer, state, MODE_REGEX_ADDRESS)) {
2817
+ *symbol = ESCAPED_REGEX_ADDRESS_START;
2818
+ return true;
2819
+ }
2820
+ }
2821
+
2822
+ if (valid_symbols[SUBSTITUTE_START]) {
2823
+ if (scan_simple_delimiter(lexer, state, MODE_SUBSTITUTE_PATTERN)) {
2824
+ *symbol = SUBSTITUTE_START;
2825
+ return true;
2826
+ }
2827
+ }
2828
+
2829
+ if (valid_symbols[TRANSLATE_START]) {
2830
+ if (scan_simple_delimiter(lexer, state, MODE_TRANSLATE_SOURCE)) {
2831
+ *symbol = TRANSLATE_START;
2832
+ return true;
2833
+ }
2834
+ }
2835
+
2836
+ if (valid_symbols[RIGHT_BRACE] && scan_right_brace(lexer, state)) {
2837
+ *symbol = RIGHT_BRACE;
2838
+ return true;
2839
+ }
2840
+
2841
+ if (
2842
+ emit_missing_marker(
2843
+ lexer,
2844
+ valid_symbols,
2845
+ OMITTED_FIRST_ADDRESS_MARKER,
2846
+ symbol
2847
+ )
2848
+ ) {
2849
+ return true;
2850
+ }
2851
+
2852
+ if (
2853
+ valid_symbols[OMITTED_ADDRESS_MARKER] &&
2854
+ !can_start_address(lexer) &&
2855
+ !is_blank(lexer->lookahead)
2856
+ ) {
2857
+ return emit_missing_marker(
2858
+ lexer,
2859
+ valid_symbols,
2860
+ OMITTED_ADDRESS_MARKER,
2861
+ symbol
2862
+ );
2863
+ }
2864
+
2865
+ if (
2866
+ valid_symbols[ADDITIONAL_ADDRESS_MARKER] &&
2867
+ (lexer->lookahead == ',' || can_start_address(lexer))
2868
+ ) {
2869
+ return emit_missing_marker(
2870
+ lexer,
2871
+ valid_symbols,
2872
+ ADDITIONAL_ADDRESS_MARKER,
2873
+ symbol
2874
+ );
2875
+ }
2876
+
2877
+ if (
2878
+ valid_symbols[MISSING_ADDRESS_SEPARATOR_MARKER] && can_start_address(lexer)
2879
+ ) {
2880
+ return emit_missing_marker(
2881
+ lexer,
2882
+ valid_symbols,
2883
+ MISSING_ADDRESS_SEPARATOR_MARKER,
2884
+ symbol
2885
+ );
2886
+ }
2887
+
2888
+ if (
2889
+ valid_symbols[BLANKS_AROUND_ADDRESS_SEPARATOR_MARKER] &&
2890
+ lexer->lookahead == ','
2891
+ ) {
2892
+ lexer->mark_end(lexer);
2893
+ advance(lexer);
2894
+ if (is_blank(lexer->lookahead)) {
2895
+ *symbol = BLANKS_AROUND_ADDRESS_SEPARATOR_MARKER;
2896
+ return true;
2897
+ }
2898
+ return false;
2899
+ }
2900
+
2901
+ if (is_blank(lexer->lookahead)) {
2902
+ switch (scan_post_blank_recovery(lexer, valid_symbols, symbol)) {
2903
+ case POST_BLANK_RECOVERY_TOKEN:
2904
+ return true;
2905
+ case POST_BLANK_RECOVERY_FAILED:
2906
+ return false;
2907
+ case POST_BLANK_RECOVERY_SKIPPED:
2908
+ break;
2909
+ }
2910
+ }
2911
+
2912
+ if (
2913
+ emit_missing_marker(lexer, valid_symbols, DUPLICATE_NEGATION_MARKER, symbol)
2914
+ ) {
2915
+ return true;
2916
+ }
2917
+
2918
+ if (
2919
+ emit_missing_marker(lexer, valid_symbols, EXCESS_ADDRESSES_MARKER, symbol)
2920
+ ) {
2921
+ return true;
2922
+ }
2923
+
2924
+ if (
2925
+ !at_command_boundary(lexer) &&
2926
+ !is_blank(lexer->lookahead) &&
2927
+ valid_symbols[OMITTED_FILE_SEPARATOR_MARKER] &&
2928
+ emit_missing_marker(
2929
+ lexer,
2930
+ valid_symbols,
2931
+ OMITTED_FILE_SEPARATOR_MARKER,
2932
+ symbol
2933
+ )
2934
+ ) {
2935
+ return true;
2936
+ }
2937
+
2938
+ if (at_command_boundary(lexer)) {
2939
+ const TSSymbol first_marker = lexer->eof(lexer)
2940
+ ? MISSING_FUNCTION_MARKER
2941
+ : NONCONFORMING_MISSING_FUNCTION_MARKER;
2942
+ for (
2943
+ TSSymbol offset = 0;
2944
+ offset <= MISSING_WFILE_MARKER - MISSING_FUNCTION_MARKER;
2945
+ offset++
2946
+ ) {
2947
+ const TSSymbol marker = first_marker + offset;
2948
+ if (emit_missing_marker(lexer, valid_symbols, marker, symbol)) {
2949
+ return true;
2950
+ }
2951
+ }
2952
+ }
2953
+
2954
+ const TSSymbol missing_text_introducer = lexer->eof(lexer)
2955
+ ? MISSING_TEXT_INTRODUCER_MARKER
2956
+ : NONCONFORMING_MISSING_TEXT_INTRODUCER_MARKER;
2957
+ if (
2958
+ emit_missing_marker(lexer, valid_symbols, missing_text_introducer, symbol)
2959
+ ) {
2960
+ return true;
2961
+ }
2962
+
2963
+ if (valid_symbols[MISSING_CLOSING_BRACE_MARKER] && lexer->eof(lexer)) {
2964
+ return emit_missing_marker(
2965
+ lexer,
2966
+ valid_symbols,
2967
+ MISSING_CLOSING_BRACE_MARKER,
2968
+ symbol
2969
+ );
2970
+ }
2971
+
2972
+ if (
2973
+ !at_command_boundary(lexer) &&
2974
+ !is_blank(lexer->lookahead) &&
2975
+ emit_missing_marker(
2976
+ lexer,
2977
+ valid_symbols,
2978
+ MISSING_SEPARATOR_AFTER_UNMATCHED_BRACE_MARKER,
2979
+ symbol
2980
+ )
2981
+ ) {
2982
+ return true;
2983
+ }
2984
+
2985
+ if (lexer->lookahead == '}') {
2986
+ if (
2987
+ emit_missing_marker(
2988
+ lexer,
2989
+ valid_symbols,
2990
+ MISSING_SEPARATOR_BEFORE_UNMATCHED_BRACE_MARKER,
2991
+ symbol
2992
+ )
2993
+ ) {
2994
+ return true;
2995
+ }
2996
+ if (
2997
+ emit_missing_marker(
2998
+ lexer,
2999
+ valid_symbols,
3000
+ MISSING_COMMAND_SEPARATOR_MARKER,
3001
+ symbol
3002
+ )
3003
+ ) {
3004
+ return true;
3005
+ }
3006
+ } else if (lexer->eof(lexer)) {
3007
+ if (
3008
+ emit_missing_marker(
3009
+ lexer,
3010
+ valid_symbols,
3011
+ INCOMPLETE_COMMAND_SEPARATOR_MARKER,
3012
+ symbol
3013
+ )
3014
+ ) {
3015
+ return true;
3016
+ }
3017
+ }
3018
+
3019
+ const TSSymbol missing_opening_delimiter = lexer->eof(lexer)
3020
+ ? MISSING_OPENING_DELIMITER_MARKER
3021
+ : NONCONFORMING_MISSING_OPENING_DELIMITER_MARKER;
3022
+ if (
3023
+ delimiter_is_missing(lexer) &&
3024
+ emit_missing_marker(lexer, valid_symbols, missing_opening_delimiter, symbol)
3025
+ ) {
3026
+ return true;
3027
+ }
3028
+
3029
+ return false;
3030
+ }
3031
+
3032
+ static void
3033
+ update_regex_position_after_symbol(ScannerState *state, TSSymbol symbol) {
3034
+ #if !SED_REGEX_EXTENDED
3035
+ if (
3036
+ symbol ==
3037
+ BRE_VERTICAL_LINE_ESCAPE_MARKER ||
3038
+ symbol ==
3039
+ BRE_QUESTION_MARK_ESCAPE_MARKER ||
3040
+ symbol ==
3041
+ BRE_PLUS_ESCAPE_MARKER ||
3042
+ symbol == UNMATCHED_INTERVAL_CLOSE_MARKER
3043
+ ) {
3044
+ return;
3045
+ }
3046
+ #endif
3047
+ if (
3048
+ symbol ==
3049
+ REGEX_LEADING_DUPLICATION_MARKER ||
3050
+ symbol == REGEX_ADJACENT_DUPLICATION_MARKER
3051
+ ) {
3052
+ return;
3053
+ }
3054
+
3055
+ const bool is_regex_token =
3056
+ symbol >= REGEX_LITERAL && symbol <= REGEX_MALFORMED_BRACKET_TERM;
3057
+ if (!is_regex_token) {
3058
+ return;
3059
+ }
3060
+
3061
+ if (symbol == REGEX_GROUP_OPEN) {
3062
+ if (state->regex_group_depth < UINT16_MAX) {
3063
+ state->regex_group_depth++;
3064
+ }
3065
+ set_regex_position(state, true, REGEX_DUPLICATION_NONE, false, false);
3066
+ return;
3067
+ }
3068
+
3069
+ if (symbol == REGEX_GROUP_CLOSE) {
3070
+ if (state->regex_group_depth > 0) {
3071
+ state->regex_group_depth--;
3072
+ }
3073
+ set_regex_position(state, false, REGEX_DUPLICATION_NONE, false, false);
3074
+ return;
3075
+ }
3076
+
3077
+ #if SED_REGEX_EXTENDED
3078
+ if (symbol == REGEX_ALTERNATION_OPERATOR) {
3079
+ set_regex_position(state, true, REGEX_DUPLICATION_NONE, true, false);
3080
+ return;
3081
+ }
3082
+ #endif
3083
+
3084
+ if (symbol == REGEX_BEGINNING_ANCHOR || symbol == REGEX_END_ANCHOR) {
3085
+ set_regex_position(state, true, REGEX_DUPLICATION_NONE, false, true);
3086
+ return;
3087
+ }
3088
+
3089
+ bool is_duplication = symbol ==
3090
+ REGEX_ZERO_OR_MORE ||
3091
+ symbol ==
3092
+ REGEX_INTERVAL_CLOSE ||
3093
+ symbol == REGEX_INVALID_INTERVAL;
3094
+ #if SED_REGEX_EXTENDED
3095
+ is_duplication = is_duplication ||
3096
+ symbol ==
3097
+ REGEX_ONE_OR_MORE ||
3098
+ symbol == REGEX_ZERO_OR_ONE;
3099
+ #endif
3100
+ if (is_duplication) {
3101
+ set_regex_position(
3102
+ state,
3103
+ false,
3104
+ REGEX_AFTER_DUPLICATION_SYMBOL,
3105
+ false,
3106
+ false
3107
+ );
3108
+ return;
3109
+ }
3110
+
3111
+ #if SED_REGEX_EXTENDED
3112
+ if (symbol == REGEX_REPETITION_MODIFIER) {
3113
+ set_regex_position(
3114
+ state,
3115
+ false,
3116
+ REGEX_AFTER_REPETITION_MODIFIER,
3117
+ false,
3118
+ false
3119
+ );
3120
+ return;
3121
+ }
3122
+ #endif
3123
+
3124
+ set_regex_position(state, false, REGEX_DUPLICATION_NONE, false, false);
3125
+ }
3126
+
3127
+ static bool
3128
+ sed_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) {
3129
+ ScannerState next = *(ScannerState *)payload;
3130
+ TSSymbol symbol;
3131
+
3132
+ if (!sed_scanner_scan_impl(&next, lexer, valid_symbols, &symbol)) {
3133
+ return false;
3134
+ }
3135
+
3136
+ update_regex_position_after_symbol(&next, symbol);
3137
+ *(ScannerState *)payload = next;
3138
+ lexer->result_symbol = symbol;
3139
+ return true;
3140
+ }
3141
+
3142
+ #endif