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