@konomanoasa/tree-sitter-gitattributes 0.5.0 → 0.7.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/README.md +3 -3
- package/binding.gyp +38 -0
- package/bindings/node/binding.cc +25 -0
- package/bindings/node/index.d.ts +7 -0
- package/bindings/node/index.js +14 -0
- package/bindings/python/binding.c +1 -1
- package/grammar.js +166 -60
- package/package.json +25 -5
- 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 +156 -56
- package/tree-sitter.json +2 -2
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,19 @@ 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
|
+
static bool invalid_run(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
139
|
+
do advance(s, lexer);
|
|
140
|
+
while (!lexer->eof(lexer) && lexer->lookahead == DECODE_ERROR);
|
|
141
|
+
lexer->mark_end(lexer);
|
|
142
|
+
if (!lexer->eof(lexer)) lexer->advance(lexer, false);
|
|
143
|
+
return emit(lexer, valid, INVALID_ENCODING);
|
|
144
|
+
}
|
|
145
|
+
|
|
104
146
|
static bool consume(
|
|
105
147
|
Scanner *s,
|
|
106
148
|
TSLexer *lexer,
|
|
@@ -108,16 +150,8 @@ static bool consume(
|
|
|
108
150
|
enum Token token,
|
|
109
151
|
uint32_t end
|
|
110
152
|
) {
|
|
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
|
-
}
|
|
153
|
+
if (token == INVALID_ENCODING) return invalid_run(s, lexer, valid);
|
|
154
|
+
while (s->position < end) advance(s, lexer);
|
|
121
155
|
lexer->mark_end(lexer);
|
|
122
156
|
return emit(lexer, valid, token);
|
|
123
157
|
}
|
|
@@ -134,13 +168,8 @@ static bool text_run(
|
|
|
134
168
|
enum Token token,
|
|
135
169
|
uint32_t end
|
|
136
170
|
) {
|
|
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
|
-
)
|
|
171
|
+
if (lexer->lookahead == DECODE_ERROR) return invalid_run(s, lexer, valid);
|
|
172
|
+
while (s->position < end && lexer->lookahead != DECODE_ERROR)
|
|
144
173
|
advance(s, lexer);
|
|
145
174
|
lexer->mark_end(lexer);
|
|
146
175
|
return emit(lexer, valid, token);
|
|
@@ -178,9 +207,12 @@ static int32_t simple_escape(int32_t c) {
|
|
|
178
207
|
static void quoted_escape(Cursor *r) {
|
|
179
208
|
const int32_t c = r->lexer->lookahead;
|
|
180
209
|
r->kind = QUOTED_ESCAPE;
|
|
181
|
-
if (r->raw >= r->limit
|
|
210
|
+
if (r->raw >= r->limit) {
|
|
211
|
+
r->c = INVALID_UNIT;
|
|
212
|
+
r->kind = absent(r->lexer, ENDED_QUOTED_ESCAPE, INCOMPLETE_QUOTED_ESCAPE);
|
|
213
|
+
} else if (c == DECODE_ERROR) {
|
|
182
214
|
r->c = INVALID_UNIT;
|
|
183
|
-
r->kind =
|
|
215
|
+
r->kind = ESCAPE_PREFIX;
|
|
184
216
|
} else if (c >= '0' && c <= '3') {
|
|
185
217
|
int32_t value = 0;
|
|
186
218
|
unsigned digits = 0;
|
|
@@ -194,12 +226,14 @@ static void quoted_escape(Cursor *r) {
|
|
|
194
226
|
if (digits == 3) r->c = value;
|
|
195
227
|
else {
|
|
196
228
|
r->c = INVALID_UNIT;
|
|
197
|
-
r->kind =
|
|
229
|
+
r->kind = r->raw == r->limit
|
|
230
|
+
? absent(r->lexer, ENDED_QUOTED_ESCAPE, INCOMPLETE_QUOTED_ESCAPE)
|
|
231
|
+
: ENDED_QUOTED_ESCAPE;
|
|
198
232
|
}
|
|
199
233
|
} else {
|
|
200
234
|
raw_step(r);
|
|
201
235
|
r->c = simple_escape(c);
|
|
202
|
-
if (r->c == INVALID_UNIT) r->kind =
|
|
236
|
+
if (r->c == INVALID_UNIT) r->kind = INVALID_QUOTED_ESCAPE;
|
|
203
237
|
}
|
|
204
238
|
}
|
|
205
239
|
|
|
@@ -212,7 +246,7 @@ static void step(Cursor *r) {
|
|
|
212
246
|
raw_step(r);
|
|
213
247
|
r->c = c;
|
|
214
248
|
if (c == DECODE_ERROR) {
|
|
215
|
-
r->kind =
|
|
249
|
+
r->kind = INVALID_ENCODING;
|
|
216
250
|
while (r->raw < r->limit && r->lexer->lookahead == DECODE_ERROR)
|
|
217
251
|
raw_step(r);
|
|
218
252
|
} else if (r->s->quoted && r->start < r->s->content_end && c == '\\')
|
|
@@ -369,7 +403,9 @@ static Item item(Cursor *r) {
|
|
|
369
403
|
if (r->kind) a.kind = r->kind;
|
|
370
404
|
step(r);
|
|
371
405
|
if (c == '\\') {
|
|
372
|
-
if (r->c
|
|
406
|
+
if (r->c == CURSOR_END)
|
|
407
|
+
a.kind = absent(r->lexer, ENDED_ESCAPE, INCOMPLETE_ESCAPE);
|
|
408
|
+
else if (r->c < 0) a.kind = ESCAPE_PREFIX;
|
|
373
409
|
else {
|
|
374
410
|
a.kind = ESCAPE;
|
|
375
411
|
a.end = r->end;
|
|
@@ -391,18 +427,35 @@ static bool literal_boundary(const Cursor *r) {
|
|
|
391
427
|
return c == '\\' || c == '*' || c == '?' || c == '/' || c == '[';
|
|
392
428
|
}
|
|
393
429
|
|
|
394
|
-
|
|
430
|
+
static void hold_prefix(Scanner *s, Cursor *r, uint32_t prefix_end) {
|
|
431
|
+
s->next = ESCAPE_PREFIX;
|
|
432
|
+
s->prefix_end = prefix_end;
|
|
433
|
+
s->prefix_kind = r->kind;
|
|
434
|
+
if (r->kind == ESCAPE_PREFIX) {
|
|
435
|
+
s->prefix_end = r->end;
|
|
436
|
+
s->prefix_kind = INVALID_ENCODING;
|
|
437
|
+
step(r);
|
|
438
|
+
}
|
|
439
|
+
s->next_end = r->end;
|
|
440
|
+
}
|
|
441
|
+
|
|
395
442
|
static bool prepare_glob(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
396
443
|
Cursor r = cursor(s, lexer, s->content_end);
|
|
397
444
|
bool separator = r.c == '/';
|
|
398
445
|
const uint32_t start = s->position;
|
|
399
446
|
s->next_end = r.end;
|
|
400
|
-
if (r.c < 0
|
|
447
|
+
if (r.c < 0) {
|
|
448
|
+
if (r.kind == ESCAPE_PREFIX) hold_prefix(s, &r, r.end);
|
|
449
|
+
else s->next = r.kind;
|
|
450
|
+
} else if (r.c == '!' && start == content_start(s))
|
|
451
|
+
s->next = NEGATIVE_PATTERN;
|
|
401
452
|
else if (r.c == '?') s->next = SINGLE_CHARACTER;
|
|
402
453
|
else if (r.c == '/') s->next = PATH_SEPARATOR;
|
|
403
454
|
else if (r.c == '\\') {
|
|
404
455
|
step(&r);
|
|
405
|
-
if (r.c
|
|
456
|
+
if (r.c == CURSOR_END)
|
|
457
|
+
s->next = absent(lexer, ENDED_ESCAPE, INCOMPLETE_ESCAPE);
|
|
458
|
+
else if (r.c < 0) hold_prefix(s, &r, s->next_end);
|
|
406
459
|
else {
|
|
407
460
|
s->next = ESCAPE;
|
|
408
461
|
s->next_end = r.end;
|
|
@@ -415,11 +468,11 @@ static bool prepare_glob(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
415
468
|
s->next_end = r.end;
|
|
416
469
|
step(&r);
|
|
417
470
|
}
|
|
418
|
-
const bool
|
|
471
|
+
const bool multiple = count >= 2 && s->component_start;
|
|
419
472
|
const bool tail = r.c == CURSOR_END && s->after_separator;
|
|
420
473
|
if (r.c == '\\') step(&r);
|
|
421
474
|
const bool slash = r.c == '/';
|
|
422
|
-
s->next =
|
|
475
|
+
s->next = multiple && (slash || tail) ? RECURSIVE_WILDCARD : WILDCARD;
|
|
423
476
|
} else if (r.kind == QUOTED_ESCAPE && r.c != '[') s->next = QUOTED_ESCAPE;
|
|
424
477
|
else if (r.c == '[') {
|
|
425
478
|
s->next = SET_OPEN;
|
|
@@ -438,7 +491,7 @@ static bool prepare_glob(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
438
491
|
s->component_start = false;
|
|
439
492
|
return emit(lexer, valid, LITERAL);
|
|
440
493
|
}
|
|
441
|
-
s->component_start = separator;
|
|
494
|
+
s->component_start = separator || s->next == NEGATIVE_PATTERN;
|
|
442
495
|
if (separator) s->after_separator = true;
|
|
443
496
|
return emit(lexer, valid, GLOB_START);
|
|
444
497
|
}
|
|
@@ -485,6 +538,7 @@ static bool prepare_set(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
485
538
|
if (s->next_end == start) {
|
|
486
539
|
s->next = current.kind;
|
|
487
540
|
s->next_end = current.end;
|
|
541
|
+
if (current.kind == ESCAPE_PREFIX) hold_prefix(s, &r, current.end);
|
|
488
542
|
}
|
|
489
543
|
break;
|
|
490
544
|
}
|
|
@@ -519,7 +573,7 @@ static bool class_piece(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
519
573
|
if (!next_class(&r, false, &s->class)) s->class.start = NONE;
|
|
520
574
|
return emit(lexer, valid, COMPOUND_CLOSE);
|
|
521
575
|
}
|
|
522
|
-
if (lexer->lookahead == DECODE_ERROR) return
|
|
576
|
+
if (lexer->lookahead == DECODE_ERROR) return invalid_run(s, lexer, valid);
|
|
523
577
|
Cursor r = cursor(s, lexer, s->class.closing_start);
|
|
524
578
|
const enum Token token = r.kind ? (enum Token)r.kind : CLASS_NAME;
|
|
525
579
|
uint32_t end = r.end;
|
|
@@ -550,20 +604,26 @@ static bool range_piece(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
550
604
|
);
|
|
551
605
|
}
|
|
552
606
|
|
|
553
|
-
static enum Token name_token(const Cursor *r) {
|
|
554
|
-
if (r->c < 0) return
|
|
607
|
+
static enum Token name_token(const Cursor *r, bool first) {
|
|
608
|
+
if (r->c < 0) return (enum Token)r->kind;
|
|
609
|
+
if (!r->kind && r->c == '\r' && r->lexer->eof(r->lexer))
|
|
610
|
+
return INCOMPLETE_NAME_CHARACTER;
|
|
611
|
+
if (!name_character(r->c, first))
|
|
612
|
+
return r->kind == QUOTED_ESCAPE ? INVALID_NAME_ESCAPE
|
|
613
|
+
: INVALID_NAME_CHARACTER;
|
|
555
614
|
return r->kind == QUOTED_ESCAPE ? QUOTED_ESCAPE : NAME_TEXT;
|
|
556
615
|
}
|
|
557
616
|
|
|
558
617
|
static bool name_piece(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
559
|
-
if (lexer->lookahead == DECODE_ERROR) return
|
|
618
|
+
if (lexer->lookahead == DECODE_ERROR) return invalid_run(s, lexer, valid);
|
|
560
619
|
Cursor r = cursor(s, lexer, s->name_end);
|
|
561
|
-
|
|
620
|
+
if (r.kind == ESCAPE_PREFIX) s->next = INVALID_ENCODING;
|
|
621
|
+
const enum Token token = name_token(&r, s->position == s->name_start);
|
|
562
622
|
uint32_t end = r.end;
|
|
563
623
|
lexer->mark_end(lexer);
|
|
564
|
-
if (token == NAME_TEXT) {
|
|
624
|
+
if (token == NAME_TEXT || token == INVALID_NAME_CHARACTER) {
|
|
565
625
|
step(&r);
|
|
566
|
-
while (name_token(&r) == token) {
|
|
626
|
+
while (name_token(&r, false) == token) {
|
|
567
627
|
end = r.end;
|
|
568
628
|
lexer->mark_end(lexer);
|
|
569
629
|
step(&r);
|
|
@@ -587,6 +647,21 @@ static bool prepare_attribute(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
587
647
|
return emit(lexer, valid, ATTRIBUTE_START);
|
|
588
648
|
}
|
|
589
649
|
|
|
650
|
+
static bool end_line(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
651
|
+
enum Token token = END_OF_FILE;
|
|
652
|
+
if (!lexer->eof(lexer)) {
|
|
653
|
+
if (!valid[LINE_ENDING]) return false;
|
|
654
|
+
if (lexer->lookahead == '\r') advance(s, lexer);
|
|
655
|
+
if (lexer->lookahead != '\n') return false;
|
|
656
|
+
advance(s, lexer);
|
|
657
|
+
token = LINE_ENDING;
|
|
658
|
+
}
|
|
659
|
+
lexer->mark_end(lexer);
|
|
660
|
+
if (!emit(lexer, valid, token)) return false;
|
|
661
|
+
*s = (Scanner){0};
|
|
662
|
+
return true;
|
|
663
|
+
}
|
|
664
|
+
|
|
590
665
|
static bool scan(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
591
666
|
if (valid[ERROR_SENTINEL]) return false;
|
|
592
667
|
if (valid[LINE_START]) return start_line(s, lexer, valid);
|
|
@@ -599,11 +674,19 @@ static bool scan(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
599
674
|
return start_content(s, lexer, valid);
|
|
600
675
|
lexer->mark_end(lexer);
|
|
601
676
|
if (
|
|
602
|
-
valid[SET_CLOSE]
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
677
|
+
(valid[SET_CLOSE] ||
|
|
678
|
+
valid[MISSING_SET_CLOSE] ||
|
|
679
|
+
valid[INCOMPLETE_SET_CLOSE]) &&
|
|
680
|
+
s->position == s->set_end
|
|
681
|
+
) {
|
|
682
|
+
if (s->set_close_end > s->set_end)
|
|
683
|
+
return consume(s, lexer, valid, SET_CLOSE, s->set_close_end);
|
|
684
|
+
return emit(
|
|
685
|
+
lexer,
|
|
686
|
+
valid,
|
|
687
|
+
absent(lexer, MISSING_SET_CLOSE, INCOMPLETE_SET_CLOSE)
|
|
688
|
+
);
|
|
689
|
+
}
|
|
607
690
|
if (valid[ATTRIBUTE_START]) return prepare_attribute(s, lexer, valid);
|
|
608
691
|
if (valid[ATTRIBUTE_END] && s->position == s->token_end)
|
|
609
692
|
return emit(lexer, valid, ATTRIBUTE_END);
|
|
@@ -616,6 +699,15 @@ static bool scan(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
616
699
|
return emit(lexer, valid, VALUE_START);
|
|
617
700
|
if (valid[VALUE_END] && s->position == s->token_end)
|
|
618
701
|
return emit(lexer, valid, VALUE_END);
|
|
702
|
+
if (
|
|
703
|
+
(valid[MISSING_ATTRIBUTE_NAME] || valid[INCOMPLETE_ATTRIBUTE_NAME]) &&
|
|
704
|
+
s->position == s->name_end
|
|
705
|
+
)
|
|
706
|
+
return emit(
|
|
707
|
+
lexer,
|
|
708
|
+
valid,
|
|
709
|
+
absent(lexer, MISSING_ATTRIBUTE_NAME, INCOMPLETE_ATTRIBUTE_NAME)
|
|
710
|
+
);
|
|
619
711
|
if (
|
|
620
712
|
(valid[UNSET_MARKER] || valid[UNSPECIFIED_MARKER]) &&
|
|
621
713
|
s->position < s->name_start
|
|
@@ -632,16 +724,22 @@ static bool scan(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
632
724
|
if (valid[ASSIGNMENT_OPERATOR] && lexer->lookahead == '=')
|
|
633
725
|
return take(s, lexer, valid, ASSIGNMENT_OPERATOR);
|
|
634
726
|
if (
|
|
635
|
-
valid[QUOTE_CLOSE]
|
|
727
|
+
(valid[QUOTE_CLOSE] ||
|
|
728
|
+
valid[MISSING_QUOTE_CLOSE] ||
|
|
729
|
+
valid[INCOMPLETE_QUOTE_CLOSE]) &&
|
|
636
730
|
s->quoted &&
|
|
637
|
-
s->position == s->content_end
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
return
|
|
731
|
+
s->position == s->content_end
|
|
732
|
+
) {
|
|
733
|
+
if (s->content_end < s->line_end) return take(s, lexer, valid, QUOTE_CLOSE);
|
|
734
|
+
return emit(
|
|
735
|
+
lexer,
|
|
736
|
+
valid,
|
|
737
|
+
absent(lexer, MISSING_QUOTE_CLOSE, INCOMPLETE_QUOTE_CLOSE)
|
|
738
|
+
);
|
|
739
|
+
}
|
|
641
740
|
if (valid[PATTERN_END] && s->position >= s->content_end)
|
|
642
741
|
return emit(lexer, valid, PATTERN_END);
|
|
643
|
-
if (s->position >= s->line_end)
|
|
644
|
-
return lexer->eof(lexer) && emit(lexer, valid, END_OF_FILE);
|
|
742
|
+
if (s->position >= s->line_end) return end_line(s, lexer, valid);
|
|
645
743
|
if (s->kind == COMMENT_START) {
|
|
646
744
|
if (s->position == s->leading) return take(s, lexer, valid, COMMENT_MARKER);
|
|
647
745
|
return text_run(s, lexer, valid, COMMENT_TEXT, s->line_end);
|
|
@@ -651,17 +749,15 @@ static bool scan(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
651
749
|
if (valid[MACRO_MARKER])
|
|
652
750
|
return consume(s, lexer, valid, MACRO_MARKER, s->name_start);
|
|
653
751
|
if (valid[SEPARATOR] || valid[LAYOUT]) {
|
|
654
|
-
if (!whitespace(lexer->lookahead))
|
|
752
|
+
if (!whitespace(lexer->lookahead))
|
|
753
|
+
return emit(lexer, valid, MISSING_ATTRIBUTE_SEPARATOR);
|
|
655
754
|
while (s->position < s->line_end && whitespace(lexer->lookahead))
|
|
656
755
|
advance(s, lexer);
|
|
657
756
|
lexer->mark_end(lexer);
|
|
658
757
|
return emit(lexer, valid, s->position < s->line_end ? SEPARATOR : LAYOUT);
|
|
659
758
|
}
|
|
660
|
-
if (valid[GLOB_START]
|
|
661
|
-
|
|
662
|
-
if (
|
|
663
|
-
(valid[SET_ITEM_START] || valid[SET_NEGATION]) && s->position < s->set_end
|
|
664
|
-
)
|
|
759
|
+
if (valid[GLOB_START]) return prepare_glob(s, lexer, valid);
|
|
760
|
+
if (valid[SET_ITEM_START] || valid[SET_NEGATION])
|
|
665
761
|
return prepare_set(s, lexer, valid);
|
|
666
762
|
if (s->class.start < s->position && s->position < s->class.end)
|
|
667
763
|
return class_piece(s, lexer, valid);
|
|
@@ -673,6 +769,10 @@ static bool scan(Scanner *s, TSLexer *lexer, const bool *valid) {
|
|
|
673
769
|
const enum Token token = (enum Token)s->next;
|
|
674
770
|
if (token == CLASS_OPEN)
|
|
675
771
|
return class_delimiter(s, lexer, valid, COMPOUND_OPEN);
|
|
772
|
+
if (token == ESCAPE_PREFIX) {
|
|
773
|
+
s->next = s->prefix_kind;
|
|
774
|
+
return consume(s, lexer, valid, token, s->prefix_end);
|
|
775
|
+
}
|
|
676
776
|
return consume(s, lexer, valid, token, s->next_end);
|
|
677
777
|
}
|
|
678
778
|
|
package/tree-sitter.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
}
|
|
13
13
|
],
|
|
14
14
|
"metadata": {
|
|
15
|
-
"version": "0.
|
|
15
|
+
"version": "0.7.0",
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"description": "Tree-sitter grammar for gitattributes.",
|
|
18
18
|
"links": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"bindings": {
|
|
23
23
|
"c": false,
|
|
24
24
|
"go": false,
|
|
25
|
-
"node":
|
|
25
|
+
"node": true,
|
|
26
26
|
"python": true,
|
|
27
27
|
"rust": true,
|
|
28
28
|
"swift": false
|