@konomanoasa/tree-sitter-gitattributes 0.5.0 → 0.6.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.
- package/Cargo.toml +1 -1
- package/grammar.js +166 -60
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/grammar.json +1343 -224
- package/src/node-types.json +258 -9
- package/src/parser.c +5031 -1247
- package/src/scanner.c +155 -53
- package/tree-sitter.json +1 -1
package/src/scanner.c
CHANGED
|
@@ -9,6 +9,7 @@ enum Token {
|
|
|
9
9
|
RULE_START,
|
|
10
10
|
MACRO_START,
|
|
11
11
|
END_OF_FILE,
|
|
12
|
+
LINE_ENDING,
|
|
12
13
|
LAYOUT,
|
|
13
14
|
SEPARATOR,
|
|
14
15
|
ATTRIBUTE_START,
|
|
@@ -37,6 +38,7 @@ enum Token {
|
|
|
37
38
|
PATH_SEPARATOR,
|
|
38
39
|
ESCAPE,
|
|
39
40
|
QUOTED_ESCAPE,
|
|
41
|
+
ESCAPE_PREFIX,
|
|
40
42
|
SET_OPEN,
|
|
41
43
|
SET_NEGATION,
|
|
42
44
|
SET_TEXT,
|
|
@@ -49,6 +51,23 @@ enum Token {
|
|
|
49
51
|
CLASS_OPEN,
|
|
50
52
|
CLASS_NAME,
|
|
51
53
|
CLASS_CLOSE,
|
|
54
|
+
MISSING_SET_CLOSE,
|
|
55
|
+
INCOMPLETE_SET_CLOSE,
|
|
56
|
+
INVALID_ENCODING,
|
|
57
|
+
NEGATIVE_PATTERN,
|
|
58
|
+
ENDED_ESCAPE,
|
|
59
|
+
INCOMPLETE_ESCAPE,
|
|
60
|
+
INVALID_QUOTED_ESCAPE,
|
|
61
|
+
ENDED_QUOTED_ESCAPE,
|
|
62
|
+
INCOMPLETE_QUOTED_ESCAPE,
|
|
63
|
+
MISSING_QUOTE_CLOSE,
|
|
64
|
+
INCOMPLETE_QUOTE_CLOSE,
|
|
65
|
+
MISSING_ATTRIBUTE_SEPARATOR,
|
|
66
|
+
MISSING_ATTRIBUTE_NAME,
|
|
67
|
+
INCOMPLETE_ATTRIBUTE_NAME,
|
|
68
|
+
INVALID_NAME_CHARACTER,
|
|
69
|
+
INCOMPLETE_NAME_CHARACTER,
|
|
70
|
+
INVALID_NAME_ESCAPE,
|
|
52
71
|
ERROR_SENTINEL
|
|
53
72
|
};
|
|
54
73
|
|
|
@@ -69,10 +88,10 @@ typedef struct {
|
|
|
69
88
|
typedef struct {
|
|
70
89
|
uint32_t position, leading, line_end, content_end;
|
|
71
90
|
uint32_t token_end, name_start, name_end;
|
|
72
|
-
uint32_t next_end, set_end, set_close_end;
|
|
91
|
+
uint32_t next_end, prefix_end, set_end, set_close_end;
|
|
73
92
|
Class class;
|
|
74
93
|
uint32_t lower_end, range_operator_end, upper_end;
|
|
75
|
-
uint8_t kind, next, lower_kind, upper_kind;
|
|
94
|
+
uint8_t kind, next, prefix_kind, lower_kind, upper_kind;
|
|
76
95
|
uint8_t quoted, component_start, after_separator;
|
|
77
96
|
} Scanner;
|
|
78
97
|
|
|
@@ -90,6 +109,16 @@ static bool whitespace(int32_t c) {
|
|
|
90
109
|
return c == ' ' || c == '\t' || c == '\r';
|
|
91
110
|
}
|
|
92
111
|
|
|
112
|
+
static bool alphanumeric(int32_t c) {
|
|
113
|
+
return (c >= 'a' && c <= 'z') ||
|
|
114
|
+
(c >= 'A' && c <= 'Z') ||
|
|
115
|
+
(c >= '0' && c <= '9');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static bool name_character(int32_t c, bool first) {
|
|
119
|
+
return alphanumeric(c) || c == '_' || c == '.' || (!first && c == '-');
|
|
120
|
+
}
|
|
121
|
+
|
|
93
122
|
static void advance(Scanner *s, TSLexer *lexer) {
|
|
94
123
|
lexer->advance(lexer, false);
|
|
95
124
|
s->position++;
|
|
@@ -101,6 +130,20 @@ static bool emit(TSLexer *lexer, const bool *valid, enum Token token) {
|
|
|
101
130
|
return true;
|
|
102
131
|
}
|
|
103
132
|
|
|
133
|
+
static enum Token
|
|
134
|
+
absent(TSLexer *lexer, enum Token missing, enum Token incomplete) {
|
|
135
|
+
return lexer->eof(lexer) ? incomplete : missing;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Include the next decoded character so edits invalidate the run.
|
|
139
|
+
static bool invalid_run(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
140
|
+
do advance(s, lexer);
|
|
141
|
+
while (!lexer->eof(lexer) && lexer->lookahead == DECODE_ERROR);
|
|
142
|
+
lexer->mark_end(lexer);
|
|
143
|
+
if (!lexer->eof(lexer)) lexer->advance(lexer, false);
|
|
144
|
+
return emit(lexer, valid, INVALID_ENCODING);
|
|
145
|
+
}
|
|
146
|
+
|
|
104
147
|
static bool consume(
|
|
105
148
|
Scanner *s,
|
|
106
149
|
TSLexer *lexer,
|
|
@@ -108,16 +151,8 @@ static bool consume(
|
|
|
108
151
|
enum Token token,
|
|
109
152
|
uint32_t end
|
|
110
153
|
) {
|
|
111
|
-
if (
|
|
112
|
-
while (s->position < end)
|
|
113
|
-
if (
|
|
114
|
-
lexer->eof(lexer) ||
|
|
115
|
-
lexer->lookahead == '\n' ||
|
|
116
|
-
lexer->lookahead == DECODE_ERROR
|
|
117
|
-
)
|
|
118
|
-
return false;
|
|
119
|
-
advance(s, lexer);
|
|
120
|
-
}
|
|
154
|
+
if (token == INVALID_ENCODING) return invalid_run(s, lexer, valid);
|
|
155
|
+
while (s->position < end) advance(s, lexer);
|
|
121
156
|
lexer->mark_end(lexer);
|
|
122
157
|
return emit(lexer, valid, token);
|
|
123
158
|
}
|
|
@@ -134,13 +169,8 @@ static bool text_run(
|
|
|
134
169
|
enum Token token,
|
|
135
170
|
uint32_t end
|
|
136
171
|
) {
|
|
137
|
-
if (lexer->lookahead == DECODE_ERROR) return
|
|
138
|
-
while (
|
|
139
|
-
s->position < end &&
|
|
140
|
-
!lexer->eof(lexer) &&
|
|
141
|
-
lexer->lookahead != '\n' &&
|
|
142
|
-
lexer->lookahead != DECODE_ERROR
|
|
143
|
-
)
|
|
172
|
+
if (lexer->lookahead == DECODE_ERROR) return invalid_run(s, lexer, valid);
|
|
173
|
+
while (s->position < end && lexer->lookahead != DECODE_ERROR)
|
|
144
174
|
advance(s, lexer);
|
|
145
175
|
lexer->mark_end(lexer);
|
|
146
176
|
return emit(lexer, valid, token);
|
|
@@ -178,9 +208,12 @@ static int32_t simple_escape(int32_t c) {
|
|
|
178
208
|
static void quoted_escape(Cursor *r) {
|
|
179
209
|
const int32_t c = r->lexer->lookahead;
|
|
180
210
|
r->kind = QUOTED_ESCAPE;
|
|
181
|
-
if (r->raw >= r->limit
|
|
211
|
+
if (r->raw >= r->limit) {
|
|
212
|
+
r->c = INVALID_UNIT;
|
|
213
|
+
r->kind = absent(r->lexer, ENDED_QUOTED_ESCAPE, INCOMPLETE_QUOTED_ESCAPE);
|
|
214
|
+
} else if (c == DECODE_ERROR) {
|
|
182
215
|
r->c = INVALID_UNIT;
|
|
183
|
-
r->kind =
|
|
216
|
+
r->kind = ESCAPE_PREFIX;
|
|
184
217
|
} else if (c >= '0' && c <= '3') {
|
|
185
218
|
int32_t value = 0;
|
|
186
219
|
unsigned digits = 0;
|
|
@@ -194,12 +227,14 @@ static void quoted_escape(Cursor *r) {
|
|
|
194
227
|
if (digits == 3) r->c = value;
|
|
195
228
|
else {
|
|
196
229
|
r->c = INVALID_UNIT;
|
|
197
|
-
r->kind =
|
|
230
|
+
r->kind = r->raw == r->limit
|
|
231
|
+
? absent(r->lexer, ENDED_QUOTED_ESCAPE, INCOMPLETE_QUOTED_ESCAPE)
|
|
232
|
+
: ENDED_QUOTED_ESCAPE;
|
|
198
233
|
}
|
|
199
234
|
} else {
|
|
200
235
|
raw_step(r);
|
|
201
236
|
r->c = simple_escape(c);
|
|
202
|
-
if (r->c == INVALID_UNIT) r->kind =
|
|
237
|
+
if (r->c == INVALID_UNIT) r->kind = INVALID_QUOTED_ESCAPE;
|
|
203
238
|
}
|
|
204
239
|
}
|
|
205
240
|
|
|
@@ -212,7 +247,7 @@ static void step(Cursor *r) {
|
|
|
212
247
|
raw_step(r);
|
|
213
248
|
r->c = c;
|
|
214
249
|
if (c == DECODE_ERROR) {
|
|
215
|
-
r->kind =
|
|
250
|
+
r->kind = INVALID_ENCODING;
|
|
216
251
|
while (r->raw < r->limit && r->lexer->lookahead == DECODE_ERROR)
|
|
217
252
|
raw_step(r);
|
|
218
253
|
} else if (r->s->quoted && r->start < r->s->content_end && c == '\\')
|
|
@@ -369,7 +404,9 @@ static Item item(Cursor *r) {
|
|
|
369
404
|
if (r->kind) a.kind = r->kind;
|
|
370
405
|
step(r);
|
|
371
406
|
if (c == '\\') {
|
|
372
|
-
if (r->c
|
|
407
|
+
if (r->c == CURSOR_END)
|
|
408
|
+
a.kind = absent(r->lexer, ENDED_ESCAPE, INCOMPLETE_ESCAPE);
|
|
409
|
+
else if (r->c < 0) a.kind = ESCAPE_PREFIX;
|
|
373
410
|
else {
|
|
374
411
|
a.kind = ESCAPE;
|
|
375
412
|
a.end = r->end;
|
|
@@ -391,18 +428,36 @@ static bool literal_boundary(const Cursor *r) {
|
|
|
391
428
|
return c == '\\' || c == '*' || c == '?' || c == '/' || c == '[';
|
|
392
429
|
}
|
|
393
430
|
|
|
431
|
+
static void hold_prefix(Scanner *s, Cursor *r, uint32_t prefix_end) {
|
|
432
|
+
s->next = ESCAPE_PREFIX;
|
|
433
|
+
s->prefix_end = prefix_end;
|
|
434
|
+
s->prefix_kind = r->kind;
|
|
435
|
+
if (r->kind == ESCAPE_PREFIX) {
|
|
436
|
+
s->prefix_end = r->end;
|
|
437
|
+
s->prefix_kind = INVALID_ENCODING;
|
|
438
|
+
step(r);
|
|
439
|
+
}
|
|
440
|
+
s->next_end = r->end;
|
|
441
|
+
}
|
|
442
|
+
|
|
394
443
|
// Consume lookahead units fully so edits inside them invalidate the decision.
|
|
395
444
|
static bool prepare_glob(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
396
445
|
Cursor r = cursor(s, lexer, s->content_end);
|
|
397
446
|
bool separator = r.c == '/';
|
|
398
447
|
const uint32_t start = s->position;
|
|
399
448
|
s->next_end = r.end;
|
|
400
|
-
if (r.c < 0
|
|
449
|
+
if (r.c < 0) {
|
|
450
|
+
if (r.kind == ESCAPE_PREFIX) hold_prefix(s, &r, r.end);
|
|
451
|
+
else s->next = r.kind;
|
|
452
|
+
} else if (r.c == '!' && start == content_start(s))
|
|
453
|
+
s->next = NEGATIVE_PATTERN;
|
|
401
454
|
else if (r.c == '?') s->next = SINGLE_CHARACTER;
|
|
402
455
|
else if (r.c == '/') s->next = PATH_SEPARATOR;
|
|
403
456
|
else if (r.c == '\\') {
|
|
404
457
|
step(&r);
|
|
405
|
-
if (r.c
|
|
458
|
+
if (r.c == CURSOR_END)
|
|
459
|
+
s->next = absent(lexer, ENDED_ESCAPE, INCOMPLETE_ESCAPE);
|
|
460
|
+
else if (r.c < 0) hold_prefix(s, &r, s->next_end);
|
|
406
461
|
else {
|
|
407
462
|
s->next = ESCAPE;
|
|
408
463
|
s->next_end = r.end;
|
|
@@ -438,7 +493,7 @@ static bool prepare_glob(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
438
493
|
s->component_start = false;
|
|
439
494
|
return emit(lexer, valid, LITERAL);
|
|
440
495
|
}
|
|
441
|
-
s->component_start = separator;
|
|
496
|
+
s->component_start = separator || s->next == NEGATIVE_PATTERN;
|
|
442
497
|
if (separator) s->after_separator = true;
|
|
443
498
|
return emit(lexer, valid, GLOB_START);
|
|
444
499
|
}
|
|
@@ -485,6 +540,7 @@ static bool prepare_set(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
485
540
|
if (s->next_end == start) {
|
|
486
541
|
s->next = current.kind;
|
|
487
542
|
s->next_end = current.end;
|
|
543
|
+
if (current.kind == ESCAPE_PREFIX) hold_prefix(s, &r, current.end);
|
|
488
544
|
}
|
|
489
545
|
break;
|
|
490
546
|
}
|
|
@@ -519,7 +575,7 @@ static bool class_piece(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
519
575
|
if (!next_class(&r, false, &s->class)) s->class.start = NONE;
|
|
520
576
|
return emit(lexer, valid, COMPOUND_CLOSE);
|
|
521
577
|
}
|
|
522
|
-
if (lexer->lookahead == DECODE_ERROR) return
|
|
578
|
+
if (lexer->lookahead == DECODE_ERROR) return invalid_run(s, lexer, valid);
|
|
523
579
|
Cursor r = cursor(s, lexer, s->class.closing_start);
|
|
524
580
|
const enum Token token = r.kind ? (enum Token)r.kind : CLASS_NAME;
|
|
525
581
|
uint32_t end = r.end;
|
|
@@ -550,20 +606,26 @@ static bool range_piece(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
550
606
|
);
|
|
551
607
|
}
|
|
552
608
|
|
|
553
|
-
static enum Token name_token(const Cursor *r) {
|
|
554
|
-
if (r->c < 0) return
|
|
609
|
+
static enum Token name_token(const Cursor *r, bool first) {
|
|
610
|
+
if (r->c < 0) return (enum Token)r->kind;
|
|
611
|
+
if (!r->kind && r->c == '\r' && r->lexer->eof(r->lexer))
|
|
612
|
+
return INCOMPLETE_NAME_CHARACTER;
|
|
613
|
+
if (!name_character(r->c, first))
|
|
614
|
+
return r->kind == QUOTED_ESCAPE ? INVALID_NAME_ESCAPE
|
|
615
|
+
: INVALID_NAME_CHARACTER;
|
|
555
616
|
return r->kind == QUOTED_ESCAPE ? QUOTED_ESCAPE : NAME_TEXT;
|
|
556
617
|
}
|
|
557
618
|
|
|
558
619
|
static bool name_piece(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
559
|
-
if (lexer->lookahead == DECODE_ERROR) return
|
|
620
|
+
if (lexer->lookahead == DECODE_ERROR) return invalid_run(s, lexer, valid);
|
|
560
621
|
Cursor r = cursor(s, lexer, s->name_end);
|
|
561
|
-
|
|
622
|
+
if (r.kind == ESCAPE_PREFIX) s->next = INVALID_ENCODING;
|
|
623
|
+
const enum Token token = name_token(&r, s->position == s->name_start);
|
|
562
624
|
uint32_t end = r.end;
|
|
563
625
|
lexer->mark_end(lexer);
|
|
564
|
-
if (token == NAME_TEXT) {
|
|
626
|
+
if (token == NAME_TEXT || token == INVALID_NAME_CHARACTER) {
|
|
565
627
|
step(&r);
|
|
566
|
-
while (name_token(&r) == token) {
|
|
628
|
+
while (name_token(&r, false) == token) {
|
|
567
629
|
end = r.end;
|
|
568
630
|
lexer->mark_end(lexer);
|
|
569
631
|
step(&r);
|
|
@@ -587,6 +649,21 @@ static bool prepare_attribute(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
587
649
|
return emit(lexer, valid, ATTRIBUTE_START);
|
|
588
650
|
}
|
|
589
651
|
|
|
652
|
+
static bool end_line(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
653
|
+
enum Token token = END_OF_FILE;
|
|
654
|
+
if (!lexer->eof(lexer)) {
|
|
655
|
+
if (!valid[LINE_ENDING]) return false;
|
|
656
|
+
if (lexer->lookahead == '\r') advance(s, lexer);
|
|
657
|
+
if (lexer->lookahead != '\n') return false;
|
|
658
|
+
advance(s, lexer);
|
|
659
|
+
token = LINE_ENDING;
|
|
660
|
+
}
|
|
661
|
+
lexer->mark_end(lexer);
|
|
662
|
+
if (!emit(lexer, valid, token)) return false;
|
|
663
|
+
*s = (Scanner){0};
|
|
664
|
+
return true;
|
|
665
|
+
}
|
|
666
|
+
|
|
590
667
|
static bool scan(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
591
668
|
if (valid[ERROR_SENTINEL]) return false;
|
|
592
669
|
if (valid[LINE_START]) return start_line(s, lexer, valid);
|
|
@@ -599,11 +676,19 @@ static bool scan(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
599
676
|
return start_content(s, lexer, valid);
|
|
600
677
|
lexer->mark_end(lexer);
|
|
601
678
|
if (
|
|
602
|
-
valid[SET_CLOSE]
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
679
|
+
(valid[SET_CLOSE] ||
|
|
680
|
+
valid[MISSING_SET_CLOSE] ||
|
|
681
|
+
valid[INCOMPLETE_SET_CLOSE]) &&
|
|
682
|
+
s->position == s->set_end
|
|
683
|
+
) {
|
|
684
|
+
if (s->set_close_end > s->set_end)
|
|
685
|
+
return consume(s, lexer, valid, SET_CLOSE, s->set_close_end);
|
|
686
|
+
return emit(
|
|
687
|
+
lexer,
|
|
688
|
+
valid,
|
|
689
|
+
absent(lexer, MISSING_SET_CLOSE, INCOMPLETE_SET_CLOSE)
|
|
690
|
+
);
|
|
691
|
+
}
|
|
607
692
|
if (valid[ATTRIBUTE_START]) return prepare_attribute(s, lexer, valid);
|
|
608
693
|
if (valid[ATTRIBUTE_END] && s->position == s->token_end)
|
|
609
694
|
return emit(lexer, valid, ATTRIBUTE_END);
|
|
@@ -616,6 +701,15 @@ static bool scan(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
616
701
|
return emit(lexer, valid, VALUE_START);
|
|
617
702
|
if (valid[VALUE_END] && s->position == s->token_end)
|
|
618
703
|
return emit(lexer, valid, VALUE_END);
|
|
704
|
+
if (
|
|
705
|
+
(valid[MISSING_ATTRIBUTE_NAME] || valid[INCOMPLETE_ATTRIBUTE_NAME]) &&
|
|
706
|
+
s->position == s->name_end
|
|
707
|
+
)
|
|
708
|
+
return emit(
|
|
709
|
+
lexer,
|
|
710
|
+
valid,
|
|
711
|
+
absent(lexer, MISSING_ATTRIBUTE_NAME, INCOMPLETE_ATTRIBUTE_NAME)
|
|
712
|
+
);
|
|
619
713
|
if (
|
|
620
714
|
(valid[UNSET_MARKER] || valid[UNSPECIFIED_MARKER]) &&
|
|
621
715
|
s->position < s->name_start
|
|
@@ -632,16 +726,22 @@ static bool scan(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
632
726
|
if (valid[ASSIGNMENT_OPERATOR] && lexer->lookahead == '=')
|
|
633
727
|
return take(s, lexer, valid, ASSIGNMENT_OPERATOR);
|
|
634
728
|
if (
|
|
635
|
-
valid[QUOTE_CLOSE]
|
|
729
|
+
(valid[QUOTE_CLOSE] ||
|
|
730
|
+
valid[MISSING_QUOTE_CLOSE] ||
|
|
731
|
+
valid[INCOMPLETE_QUOTE_CLOSE]) &&
|
|
636
732
|
s->quoted &&
|
|
637
|
-
s->position == s->content_end
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
return
|
|
733
|
+
s->position == s->content_end
|
|
734
|
+
) {
|
|
735
|
+
if (s->content_end < s->line_end) return take(s, lexer, valid, QUOTE_CLOSE);
|
|
736
|
+
return emit(
|
|
737
|
+
lexer,
|
|
738
|
+
valid,
|
|
739
|
+
absent(lexer, MISSING_QUOTE_CLOSE, INCOMPLETE_QUOTE_CLOSE)
|
|
740
|
+
);
|
|
741
|
+
}
|
|
641
742
|
if (valid[PATTERN_END] && s->position >= s->content_end)
|
|
642
743
|
return emit(lexer, valid, PATTERN_END);
|
|
643
|
-
if (s->position >= s->line_end)
|
|
644
|
-
return lexer->eof(lexer) && emit(lexer, valid, END_OF_FILE);
|
|
744
|
+
if (s->position >= s->line_end) return end_line(s, lexer, valid);
|
|
645
745
|
if (s->kind == COMMENT_START) {
|
|
646
746
|
if (s->position == s->leading) return take(s, lexer, valid, COMMENT_MARKER);
|
|
647
747
|
return text_run(s, lexer, valid, COMMENT_TEXT, s->line_end);
|
|
@@ -651,17 +751,15 @@ static bool scan(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
651
751
|
if (valid[MACRO_MARKER])
|
|
652
752
|
return consume(s, lexer, valid, MACRO_MARKER, s->name_start);
|
|
653
753
|
if (valid[SEPARATOR] || valid[LAYOUT]) {
|
|
654
|
-
if (!whitespace(lexer->lookahead))
|
|
754
|
+
if (!whitespace(lexer->lookahead))
|
|
755
|
+
return emit(lexer, valid, MISSING_ATTRIBUTE_SEPARATOR);
|
|
655
756
|
while (s->position < s->line_end && whitespace(lexer->lookahead))
|
|
656
757
|
advance(s, lexer);
|
|
657
758
|
lexer->mark_end(lexer);
|
|
658
759
|
return emit(lexer, valid, s->position < s->line_end ? SEPARATOR : LAYOUT);
|
|
659
760
|
}
|
|
660
|
-
if (valid[GLOB_START]
|
|
661
|
-
|
|
662
|
-
if (
|
|
663
|
-
(valid[SET_ITEM_START] || valid[SET_NEGATION]) && s->position < s->set_end
|
|
664
|
-
)
|
|
761
|
+
if (valid[GLOB_START]) return prepare_glob(s, lexer, valid);
|
|
762
|
+
if (valid[SET_ITEM_START] || valid[SET_NEGATION])
|
|
665
763
|
return prepare_set(s, lexer, valid);
|
|
666
764
|
if (s->class.start < s->position && s->position < s->class.end)
|
|
667
765
|
return class_piece(s, lexer, valid);
|
|
@@ -673,6 +771,10 @@ static bool scan(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
673
771
|
const enum Token token = (enum Token)s->next;
|
|
674
772
|
if (token == CLASS_OPEN)
|
|
675
773
|
return class_delimiter(s, lexer, valid, COMPOUND_OPEN);
|
|
774
|
+
if (token == ESCAPE_PREFIX) {
|
|
775
|
+
s->next = s->prefix_kind;
|
|
776
|
+
return consume(s, lexer, valid, token, s->prefix_end);
|
|
777
|
+
}
|
|
676
778
|
return consume(s, lexer, valid, token, s->next_end);
|
|
677
779
|
}
|
|
678
780
|
|