tree-sitter-sed 0.2.0 → 0.3.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/common/grammar.js +264 -312
- package/common/regex.js +12 -23
- package/common/scanner.h +423 -460
- package/package.json +3 -3
- package/sed_ere/src/grammar.json +1264 -2013
- package/sed_ere/src/node-types.json +109 -32
- package/sed_ere/src/parser.c +37125 -36566
- package/src/grammar.json +1261 -2076
- package/src/node-types.json +131 -38
- package/src/parser.c +31231 -30740
- package/tree-sitter.json +1 -1
package/common/scanner.h
CHANGED
|
@@ -42,7 +42,6 @@ enum TokenType {
|
|
|
42
42
|
BRE_QUESTION_MARK_ESCAPE_MARKER,
|
|
43
43
|
BRE_PLUS_ESCAPE_MARKER,
|
|
44
44
|
REGEX_UNMATCHED_INTERVAL_CLOSE,
|
|
45
|
-
UNMATCHED_INTERVAL_CLOSE_MARKER,
|
|
46
45
|
#endif
|
|
47
46
|
#if SED_REGEX_EXTENDED
|
|
48
47
|
REGEX_ALTERNATION_OPERATOR,
|
|
@@ -109,6 +108,7 @@ enum TokenType {
|
|
|
109
108
|
TRANSLATE_UNTERMINATED_SOURCE,
|
|
110
109
|
TRANSLATE_UNTERMINATED_DESTINATION,
|
|
111
110
|
INVALID_SUBSTITUTION_FLAG,
|
|
111
|
+
FLAG_AFTER_WRITE_MARKER,
|
|
112
112
|
TEXT_COMMAND_START,
|
|
113
113
|
TEXT_LITERAL,
|
|
114
114
|
TEXT_BACKSLASH_ESCAPE,
|
|
@@ -122,7 +122,7 @@ enum TokenType {
|
|
|
122
122
|
SUBSTITUTION_WFILE_ARGUMENT,
|
|
123
123
|
LINE_WORD,
|
|
124
124
|
RIGHT_BRACE,
|
|
125
|
-
|
|
125
|
+
RESERVED_UNKNOWN_FUNCTION_TOKEN,
|
|
126
126
|
REGEX_INCOMPLETE_GROUP,
|
|
127
127
|
REGEX_INCOMPLETE_BRACKET_TERM,
|
|
128
128
|
REGEX_INCOMPLETE_INTERVAL,
|
|
@@ -132,15 +132,15 @@ enum TokenType {
|
|
|
132
132
|
REPLACEMENT_LINE_UNTERMINATED,
|
|
133
133
|
TRANSLATE_LINE_UNTERMINATED_SOURCE,
|
|
134
134
|
TRANSLATE_LINE_UNTERMINATED_DESTINATION,
|
|
135
|
+
BLANKS_AROUND_ADDRESS_SEPARATOR,
|
|
135
136
|
OMITTED_ADDRESS_MARKER,
|
|
137
|
+
INCOMPLETE_OMITTED_ADDRESS_MARKER,
|
|
136
138
|
OMITTED_FIRST_ADDRESS_MARKER,
|
|
137
139
|
EMPTY_SUBEXPRESSION_MARKER,
|
|
138
140
|
MISSING_SUBEXPRESSION_MARKER,
|
|
139
141
|
#if SED_REGEX_EXTENDED
|
|
140
142
|
EMPTY_ALTERNATIVE_MARKER,
|
|
141
143
|
#endif
|
|
142
|
-
EXCESS_ADDRESSES_MARKER,
|
|
143
|
-
ADDITIONAL_ADDRESS_MARKER,
|
|
144
144
|
MISSING_FUNCTION_MARKER,
|
|
145
145
|
MISSING_LABEL_MARKER,
|
|
146
146
|
MISSING_RFILE_MARKER,
|
|
@@ -149,9 +149,7 @@ enum TokenType {
|
|
|
149
149
|
MISSING_TEXT_INTRODUCER_MARKER,
|
|
150
150
|
MISSING_TEXT_MARKER,
|
|
151
151
|
MISSING_COMMAND_SEPARATOR_MARKER,
|
|
152
|
-
BLANKS_AROUND_ADDRESS_SEPARATOR_MARKER,
|
|
153
152
|
MISSING_ADDRESS_SEPARATOR_MARKER,
|
|
154
|
-
DUPLICATE_NEGATION_MARKER,
|
|
155
153
|
MISSING_CLOSING_BRACE_MARKER,
|
|
156
154
|
MISSING_OPENING_DELIMITER_MARKER,
|
|
157
155
|
MISSING_SEPARATOR_BEFORE_UNMATCHED_BRACE_MARKER,
|
|
@@ -306,6 +304,10 @@ static uint16_t deserialize_uint16(const char *buffer, unsigned offset) {
|
|
|
306
304
|
((uint16_t)(unsigned char)buffer[offset + 1] << 8));
|
|
307
305
|
}
|
|
308
306
|
|
|
307
|
+
static bool is_regex_mode(enum ScannerMode mode) {
|
|
308
|
+
return mode == MODE_REGEX_ADDRESS || mode == MODE_SUBSTITUTE_PATTERN;
|
|
309
|
+
}
|
|
310
|
+
|
|
309
311
|
static unsigned sed_scanner_serialize(void *payload, char *buffer) {
|
|
310
312
|
const ScannerState *state = payload;
|
|
311
313
|
const uint32_t delimiter = (uint32_t)state->delimiter;
|
|
@@ -333,6 +335,96 @@ static unsigned sed_scanner_serialize(void *payload, char *buffer) {
|
|
|
333
335
|
return SCANNER_SERIALIZED_STATE_SIZE;
|
|
334
336
|
}
|
|
335
337
|
|
|
338
|
+
static bool bracket_tracking_is_reset(const ScannerState *state) {
|
|
339
|
+
return state->regex_bracket_term_state ==
|
|
340
|
+
REGEX_BRACKET_TERM_NONE &&
|
|
341
|
+
state->regex_bracket_pending_element ==
|
|
342
|
+
REGEX_BRACKET_PENDING_NONE &&
|
|
343
|
+
state->regex_bracket_first_element ==
|
|
344
|
+
REGEX_BRACKET_PENDING_NONE &&
|
|
345
|
+
state->regex_bracket_last_element ==
|
|
346
|
+
REGEX_BRACKET_PENDING_NONE &&
|
|
347
|
+
state->regex_bracket_element_count ==
|
|
348
|
+
0 &&
|
|
349
|
+
!state->regex_bracket_range_pending;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
static bool regex_position_is_reset(const ScannerState *state) {
|
|
353
|
+
return !state->regex_at_branch_start &&
|
|
354
|
+
state->regex_duplication_state ==
|
|
355
|
+
REGEX_DUPLICATION_NONE &&
|
|
356
|
+
!state->regex_after_alternation &&
|
|
357
|
+
!state->regex_after_anchor;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
static bool deserialized_delimiter_is_valid(uint32_t delimiter) {
|
|
361
|
+
return delimiter !=
|
|
362
|
+
0 &&
|
|
363
|
+
delimiter <=
|
|
364
|
+
UINT32_C(0x10ffff) &&
|
|
365
|
+
!(delimiter >= UINT32_C(0xd800) && delimiter <= UINT32_C(0xdfff)) &&
|
|
366
|
+
delimiter !=
|
|
367
|
+
(uint32_t)'\\' &&
|
|
368
|
+
delimiter != (uint32_t)'\n';
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
static bool deserialized_state_is_valid(const ScannerState *candidate) {
|
|
372
|
+
if (candidate->mode == MODE_NONE) {
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if (candidate->mode == MODE_TEXT) {
|
|
377
|
+
return candidate->delimiter ==
|
|
378
|
+
0 &&
|
|
379
|
+
candidate->regex_state ==
|
|
380
|
+
REGEX_OUTSIDE_BRACKET &&
|
|
381
|
+
regex_position_is_reset(candidate) &&
|
|
382
|
+
candidate->regex_group_depth ==
|
|
383
|
+
0 &&
|
|
384
|
+
candidate->regex_interval_state ==
|
|
385
|
+
REGEX_INTERVAL_NONE &&
|
|
386
|
+
bracket_tracking_is_reset(candidate);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (!deserialized_delimiter_is_valid((uint32_t)candidate->delimiter)) {
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (!is_regex_mode(candidate->mode)) {
|
|
394
|
+
return candidate->regex_state ==
|
|
395
|
+
REGEX_OUTSIDE_BRACKET &&
|
|
396
|
+
regex_position_is_reset(candidate) &&
|
|
397
|
+
candidate->text_state ==
|
|
398
|
+
TEXT_EMPTY &&
|
|
399
|
+
candidate->regex_interval_state ==
|
|
400
|
+
REGEX_INTERVAL_NONE &&
|
|
401
|
+
bracket_tracking_is_reset(candidate) &&
|
|
402
|
+
candidate->regex_group_depth == 0;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (candidate->text_state != TEXT_EMPTY) {
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (candidate->regex_state == REGEX_OUTSIDE_BRACKET) {
|
|
410
|
+
return bracket_tracking_is_reset(candidate);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (!regex_position_is_reset(candidate)) {
|
|
414
|
+
return false;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (
|
|
418
|
+
candidate->regex_state ==
|
|
419
|
+
REGEX_BRACKET_FIRST ||
|
|
420
|
+
candidate->regex_state == REGEX_BRACKET_AFTER_CARET
|
|
421
|
+
) {
|
|
422
|
+
return bracket_tracking_is_reset(candidate);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return true;
|
|
426
|
+
}
|
|
427
|
+
|
|
336
428
|
static void
|
|
337
429
|
sed_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
|
|
338
430
|
ScannerState *state = payload;
|
|
@@ -346,256 +438,101 @@ sed_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
|
|
|
346
438
|
return;
|
|
347
439
|
}
|
|
348
440
|
|
|
349
|
-
const enum ScannerMode mode = (enum ScannerMode)(unsigned char)buffer[1];
|
|
350
|
-
const enum RegexState regex_state = (enum RegexState)(unsigned char)buffer[2];
|
|
351
441
|
const unsigned char mode_flags = (unsigned char)buffer[3];
|
|
352
|
-
const uint32_t delimiter = (uint32_t)(unsigned char)buffer[4] |
|
|
353
|
-
((uint32_t)(unsigned char)buffer[5] << 8) |
|
|
354
|
-
((uint32_t)(unsigned char)buffer[6] << 16) |
|
|
355
|
-
((uint32_t)(unsigned char)buffer[7] << 24);
|
|
356
|
-
const uint16_t regex_group_depth = deserialize_uint16(buffer, 8);
|
|
357
|
-
const enum RegexIntervalState regex_interval_state =
|
|
358
|
-
(enum RegexIntervalState)(unsigned char)buffer[10];
|
|
359
|
-
const enum RegexBracketTermState regex_bracket_term_state =
|
|
360
|
-
(enum RegexBracketTermState)(unsigned char)buffer[11];
|
|
361
|
-
const enum RegexBracketPendingElement regex_bracket_pending_element =
|
|
362
|
-
(enum RegexBracketPendingElement)(unsigned char)buffer[12];
|
|
363
|
-
const enum RegexBracketPendingElement regex_bracket_first_element =
|
|
364
|
-
(enum RegexBracketPendingElement)(unsigned char)buffer[13];
|
|
365
|
-
const enum RegexBracketPendingElement regex_bracket_last_element =
|
|
366
|
-
(enum RegexBracketPendingElement)(unsigned char)buffer[14];
|
|
367
|
-
const uint8_t regex_bracket_element_count =
|
|
368
|
-
(uint8_t)(unsigned char)buffer[15];
|
|
369
442
|
const unsigned char regex_bracket_flags = (unsigned char)buffer[16];
|
|
370
|
-
const
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
443
|
+
const ScannerState candidate = {
|
|
444
|
+
.delimiter = (int32_t)((uint32_t)(unsigned char)buffer[4] |
|
|
445
|
+
((uint32_t)(unsigned char)buffer[5] << 8) |
|
|
446
|
+
((uint32_t)(unsigned char)buffer[6] << 16) |
|
|
447
|
+
((uint32_t)(unsigned char)buffer[7] << 24)),
|
|
448
|
+
.mode = (enum ScannerMode)(unsigned char)buffer[1],
|
|
449
|
+
.regex_state = (enum RegexState)(unsigned char)buffer[2],
|
|
450
|
+
.regex_at_branch_start = (mode_flags & 1U) != 0,
|
|
451
|
+
.regex_duplication_state =
|
|
452
|
+
(enum RegexDuplicationState)((regex_bracket_flags >> 1) & 3U),
|
|
453
|
+
.regex_after_alternation = (mode_flags & 2U) != 0,
|
|
454
|
+
.regex_after_anchor = (mode_flags & 4U) != 0,
|
|
455
|
+
.text_state = (enum TextState)((mode_flags >> 3) & 3U),
|
|
456
|
+
.regex_interval_state = (enum RegexIntervalState)(unsigned char)buffer[10],
|
|
457
|
+
.regex_bracket_term_state =
|
|
458
|
+
(enum RegexBracketTermState)(unsigned char)buffer[11],
|
|
459
|
+
.regex_bracket_pending_element =
|
|
460
|
+
(enum RegexBracketPendingElement)(unsigned char)buffer[12],
|
|
461
|
+
.regex_bracket_first_element =
|
|
462
|
+
(enum RegexBracketPendingElement)(unsigned char)buffer[13],
|
|
463
|
+
.regex_bracket_last_element =
|
|
464
|
+
(enum RegexBracketPendingElement)(unsigned char)buffer[14],
|
|
465
|
+
.regex_bracket_element_count = (uint8_t)(unsigned char)buffer[15],
|
|
466
|
+
.regex_bracket_range_pending = (regex_bracket_flags & 1U) != 0,
|
|
467
|
+
.regex_group_depth = deserialize_uint16(buffer, 8),
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
if (candidate.mode > MODE_TEXT) {
|
|
375
471
|
return;
|
|
376
472
|
}
|
|
377
473
|
|
|
378
|
-
if (regex_state > REGEX_BRACKET_BODY) {
|
|
474
|
+
if (candidate.regex_state > REGEX_BRACKET_BODY) {
|
|
379
475
|
return;
|
|
380
476
|
}
|
|
381
477
|
|
|
382
478
|
if ((mode_flags & (unsigned char)~31U) != 0) {
|
|
383
479
|
return;
|
|
384
480
|
}
|
|
385
|
-
|
|
386
|
-
const bool regex_after_alternation = (mode_flags & 2U) != 0;
|
|
387
|
-
const bool regex_after_anchor = (mode_flags & 4U) != 0;
|
|
388
|
-
const enum TextState text_state = (enum TextState)((mode_flags >> 3) & 3U);
|
|
389
|
-
if (text_state > TEXT_AFTER_ESCAPED_NEWLINE) {
|
|
481
|
+
if (candidate.text_state > TEXT_AFTER_ESCAPED_NEWLINE) {
|
|
390
482
|
return;
|
|
391
483
|
}
|
|
392
484
|
#if !SED_REGEX_EXTENDED
|
|
393
|
-
if (regex_after_alternation) {
|
|
485
|
+
if (candidate.regex_after_alternation) {
|
|
394
486
|
return;
|
|
395
487
|
}
|
|
396
488
|
#endif
|
|
397
489
|
|
|
398
|
-
if (regex_interval_state > REGEX_INTERVAL_AFTER_MAXIMUM) {
|
|
490
|
+
if (candidate.regex_interval_state > REGEX_INTERVAL_AFTER_MAXIMUM) {
|
|
399
491
|
return;
|
|
400
492
|
}
|
|
401
|
-
if (regex_bracket_term_state > REGEX_BRACKET_TERM_EQUAL) {
|
|
493
|
+
if (candidate.regex_bracket_term_state > REGEX_BRACKET_TERM_EQUAL) {
|
|
402
494
|
return;
|
|
403
495
|
}
|
|
404
496
|
if (
|
|
405
|
-
regex_bracket_pending_element >
|
|
497
|
+
candidate.regex_bracket_pending_element >
|
|
406
498
|
REGEX_BRACKET_PENDING_COLON ||
|
|
407
|
-
regex_bracket_first_element >
|
|
499
|
+
candidate.regex_bracket_first_element >
|
|
408
500
|
REGEX_BRACKET_PENDING_COLON ||
|
|
409
|
-
regex_bracket_last_element >
|
|
501
|
+
candidate.regex_bracket_last_element >
|
|
410
502
|
REGEX_BRACKET_PENDING_COLON ||
|
|
411
|
-
regex_bracket_element_count >
|
|
503
|
+
candidate.regex_bracket_element_count >
|
|
412
504
|
3U ||
|
|
413
505
|
(regex_bracket_flags & (unsigned char)~7U) !=
|
|
414
506
|
0 ||
|
|
415
507
|
#if SED_REGEX_EXTENDED
|
|
416
|
-
regex_duplication_state > REGEX_AFTER_REPETITION_MODIFIER
|
|
508
|
+
candidate.regex_duplication_state > REGEX_AFTER_REPETITION_MODIFIER
|
|
417
509
|
#else
|
|
418
|
-
regex_duplication_state > REGEX_AFTER_DUPLICATION_SYMBOL
|
|
510
|
+
candidate.regex_duplication_state > REGEX_AFTER_DUPLICATION_SYMBOL
|
|
419
511
|
#endif
|
|
420
512
|
) {
|
|
421
513
|
return;
|
|
422
514
|
}
|
|
423
515
|
if (
|
|
424
|
-
(regex_bracket_element_count ==
|
|
516
|
+
(candidate.regex_bracket_element_count ==
|
|
425
517
|
0 &&
|
|
426
|
-
(regex_bracket_first_element !=
|
|
518
|
+
(candidate.regex_bracket_first_element !=
|
|
427
519
|
REGEX_BRACKET_PENDING_NONE ||
|
|
428
|
-
regex_bracket_last_element != REGEX_BRACKET_PENDING_NONE)) ||
|
|
429
|
-
(regex_bracket_element_count >
|
|
520
|
+
candidate.regex_bracket_last_element != REGEX_BRACKET_PENDING_NONE)) ||
|
|
521
|
+
(candidate.regex_bracket_element_count >
|
|
430
522
|
0 &&
|
|
431
|
-
(regex_bracket_first_element ==
|
|
523
|
+
(candidate.regex_bracket_first_element ==
|
|
432
524
|
REGEX_BRACKET_PENDING_NONE ||
|
|
433
|
-
regex_bracket_last_element == REGEX_BRACKET_PENDING_NONE)) ||
|
|
434
|
-
(regex_bracket_pending_element !=
|
|
435
|
-
REGEX_BRACKET_PENDING_NONE &&
|
|
436
|
-
regex_bracket_range_pending)
|
|
437
|
-
) {
|
|
438
|
-
return;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
if (mode == MODE_NONE) {
|
|
442
|
-
return;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
if (mode == MODE_TEXT) {
|
|
446
|
-
if (
|
|
447
|
-
delimiter ==
|
|
448
|
-
0 &&
|
|
449
|
-
regex_state ==
|
|
450
|
-
REGEX_OUTSIDE_BRACKET &&
|
|
451
|
-
!regex_at_branch_start &&
|
|
452
|
-
regex_duplication_state ==
|
|
453
|
-
REGEX_DUPLICATION_NONE &&
|
|
454
|
-
regex_group_depth ==
|
|
455
|
-
0 &&
|
|
456
|
-
!regex_after_anchor &&
|
|
457
|
-
regex_interval_state ==
|
|
458
|
-
REGEX_INTERVAL_NONE &&
|
|
459
|
-
!regex_after_alternation &&
|
|
460
|
-
regex_bracket_term_state ==
|
|
461
|
-
REGEX_BRACKET_TERM_NONE &&
|
|
462
|
-
regex_bracket_pending_element ==
|
|
525
|
+
candidate.regex_bracket_last_element == REGEX_BRACKET_PENDING_NONE)) ||
|
|
526
|
+
(candidate.regex_bracket_pending_element !=
|
|
463
527
|
REGEX_BRACKET_PENDING_NONE &&
|
|
464
|
-
|
|
465
|
-
REGEX_BRACKET_PENDING_NONE &&
|
|
466
|
-
regex_bracket_last_element ==
|
|
467
|
-
REGEX_BRACKET_PENDING_NONE &&
|
|
468
|
-
regex_bracket_element_count ==
|
|
469
|
-
0 &&
|
|
470
|
-
!regex_bracket_range_pending
|
|
471
|
-
) {
|
|
472
|
-
state->mode = mode;
|
|
473
|
-
state->text_state = text_state;
|
|
474
|
-
}
|
|
475
|
-
return;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
if (
|
|
479
|
-
delimiter ==
|
|
480
|
-
0 ||
|
|
481
|
-
delimiter >
|
|
482
|
-
UINT32_C(0x10ffff) ||
|
|
483
|
-
(delimiter >= UINT32_C(0xd800) && delimiter <= UINT32_C(0xdfff)) ||
|
|
484
|
-
delimiter ==
|
|
485
|
-
(uint32_t)'\\' ||
|
|
486
|
-
delimiter == (uint32_t)'\n'
|
|
487
|
-
) {
|
|
488
|
-
return;
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
if (
|
|
492
|
-
mode !=
|
|
493
|
-
MODE_REGEX_ADDRESS &&
|
|
494
|
-
mode !=
|
|
495
|
-
MODE_SUBSTITUTE_PATTERN &&
|
|
496
|
-
(regex_state !=
|
|
497
|
-
REGEX_OUTSIDE_BRACKET ||
|
|
498
|
-
regex_at_branch_start ||
|
|
499
|
-
regex_duplication_state !=
|
|
500
|
-
REGEX_DUPLICATION_NONE ||
|
|
501
|
-
regex_after_alternation ||
|
|
502
|
-
regex_after_anchor ||
|
|
503
|
-
text_state !=
|
|
504
|
-
TEXT_EMPTY ||
|
|
505
|
-
regex_interval_state !=
|
|
506
|
-
REGEX_INTERVAL_NONE ||
|
|
507
|
-
regex_bracket_term_state !=
|
|
508
|
-
REGEX_BRACKET_TERM_NONE ||
|
|
509
|
-
regex_bracket_pending_element !=
|
|
510
|
-
REGEX_BRACKET_PENDING_NONE ||
|
|
511
|
-
regex_bracket_first_element !=
|
|
512
|
-
REGEX_BRACKET_PENDING_NONE ||
|
|
513
|
-
regex_bracket_last_element !=
|
|
514
|
-
REGEX_BRACKET_PENDING_NONE ||
|
|
515
|
-
regex_bracket_element_count !=
|
|
516
|
-
0 ||
|
|
517
|
-
regex_bracket_range_pending)
|
|
528
|
+
candidate.regex_bracket_range_pending)
|
|
518
529
|
) {
|
|
519
530
|
return;
|
|
520
531
|
}
|
|
521
532
|
|
|
522
|
-
if (
|
|
523
|
-
|
|
524
|
-
REGEX_OUTSIDE_BRACKET &&
|
|
525
|
-
(regex_at_branch_start ||
|
|
526
|
-
regex_duplication_state !=
|
|
527
|
-
REGEX_DUPLICATION_NONE ||
|
|
528
|
-
regex_after_alternation ||
|
|
529
|
-
regex_after_anchor)
|
|
530
|
-
) {
|
|
531
|
-
return;
|
|
533
|
+
if (deserialized_state_is_valid(&candidate)) {
|
|
534
|
+
*state = candidate;
|
|
532
535
|
}
|
|
533
|
-
|
|
534
|
-
if (
|
|
535
|
-
regex_state ==
|
|
536
|
-
REGEX_OUTSIDE_BRACKET &&
|
|
537
|
-
(regex_bracket_term_state !=
|
|
538
|
-
REGEX_BRACKET_TERM_NONE ||
|
|
539
|
-
regex_bracket_pending_element !=
|
|
540
|
-
REGEX_BRACKET_PENDING_NONE ||
|
|
541
|
-
regex_bracket_first_element !=
|
|
542
|
-
REGEX_BRACKET_PENDING_NONE ||
|
|
543
|
-
regex_bracket_last_element !=
|
|
544
|
-
REGEX_BRACKET_PENDING_NONE ||
|
|
545
|
-
regex_bracket_element_count !=
|
|
546
|
-
0 ||
|
|
547
|
-
regex_bracket_range_pending)
|
|
548
|
-
) {
|
|
549
|
-
return;
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
if (
|
|
553
|
-
(regex_state ==
|
|
554
|
-
REGEX_BRACKET_FIRST ||
|
|
555
|
-
regex_state == REGEX_BRACKET_AFTER_CARET) &&
|
|
556
|
-
(regex_bracket_term_state !=
|
|
557
|
-
REGEX_BRACKET_TERM_NONE ||
|
|
558
|
-
regex_bracket_pending_element !=
|
|
559
|
-
REGEX_BRACKET_PENDING_NONE ||
|
|
560
|
-
regex_bracket_element_count !=
|
|
561
|
-
0 ||
|
|
562
|
-
regex_bracket_range_pending)
|
|
563
|
-
) {
|
|
564
|
-
return;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
if (
|
|
568
|
-
(mode == MODE_REGEX_ADDRESS || mode == MODE_SUBSTITUTE_PATTERN) &&
|
|
569
|
-
text_state != TEXT_EMPTY
|
|
570
|
-
) {
|
|
571
|
-
return;
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
if (
|
|
575
|
-
mode !=
|
|
576
|
-
MODE_REGEX_ADDRESS &&
|
|
577
|
-
mode !=
|
|
578
|
-
MODE_SUBSTITUTE_PATTERN &&
|
|
579
|
-
regex_group_depth != 0
|
|
580
|
-
) {
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
state->mode = mode;
|
|
585
|
-
state->delimiter = (int32_t)delimiter;
|
|
586
|
-
state->regex_state = regex_state;
|
|
587
|
-
state->regex_at_branch_start = regex_at_branch_start;
|
|
588
|
-
state->regex_duplication_state = regex_duplication_state;
|
|
589
|
-
state->regex_after_alternation = regex_after_alternation;
|
|
590
|
-
state->regex_after_anchor = regex_after_anchor;
|
|
591
|
-
state->regex_interval_state = regex_interval_state;
|
|
592
|
-
state->regex_bracket_term_state = regex_bracket_term_state;
|
|
593
|
-
state->regex_bracket_pending_element = regex_bracket_pending_element;
|
|
594
|
-
state->regex_bracket_first_element = regex_bracket_first_element;
|
|
595
|
-
state->regex_bracket_last_element = regex_bracket_last_element;
|
|
596
|
-
state->regex_bracket_element_count = regex_bracket_element_count;
|
|
597
|
-
state->regex_bracket_range_pending = regex_bracket_range_pending;
|
|
598
|
-
state->regex_group_depth = regex_group_depth;
|
|
599
536
|
}
|
|
600
537
|
|
|
601
538
|
static void advance(TSLexer *lexer) {
|
|
@@ -789,6 +726,42 @@ static bool scan_substitution_wfile_argument(TSLexer *lexer) {
|
|
|
789
726
|
return true;
|
|
790
727
|
}
|
|
791
728
|
|
|
729
|
+
enum FlagAfterWriteScan {
|
|
730
|
+
FLAG_AFTER_WRITE_NONE,
|
|
731
|
+
FLAG_AFTER_WRITE_MATCH,
|
|
732
|
+
FLAG_AFTER_WRITE_FALLBACK,
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
static bool is_substitution_flag_character(int32_t character) {
|
|
736
|
+
if (is_digit(character)) {
|
|
737
|
+
return true;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
switch (character) {
|
|
741
|
+
case 'g':
|
|
742
|
+
case 'i':
|
|
743
|
+
case 'p':
|
|
744
|
+
case 'w':
|
|
745
|
+
return true;
|
|
746
|
+
default:
|
|
747
|
+
return false;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
static enum FlagAfterWriteScan scan_flag_after_write_marker(TSLexer *lexer) {
|
|
752
|
+
if (!is_substitution_flag_character(lexer->lookahead)) {
|
|
753
|
+
return FLAG_AFTER_WRITE_NONE;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
lexer->mark_end(lexer);
|
|
757
|
+
do {
|
|
758
|
+
advance(lexer);
|
|
759
|
+
} while (is_substitution_flag_character(lexer->lookahead));
|
|
760
|
+
|
|
761
|
+
return is_blank(lexer->lookahead) ? FLAG_AFTER_WRITE_MATCH
|
|
762
|
+
: FLAG_AFTER_WRITE_FALLBACK;
|
|
763
|
+
}
|
|
764
|
+
|
|
792
765
|
static bool scan_right_brace(TSLexer *lexer, ScannerState *state) {
|
|
793
766
|
if (state->mode != MODE_NONE) {
|
|
794
767
|
return false;
|
|
@@ -883,8 +856,8 @@ static enum PostBlankRecoveryScan scan_post_blank_recovery(
|
|
|
883
856
|
) {
|
|
884
857
|
if (
|
|
885
858
|
!valid_symbols[OMITTED_ADDRESS_MARKER] &&
|
|
886
|
-
!valid_symbols[
|
|
887
|
-
!valid_symbols[
|
|
859
|
+
!valid_symbols[INCOMPLETE_OMITTED_ADDRESS_MARKER] &&
|
|
860
|
+
!valid_symbols[BLANKS_AROUND_ADDRESS_SEPARATOR] &&
|
|
888
861
|
!valid_symbols[MISSING_ADDRESS_SEPARATOR_MARKER] &&
|
|
889
862
|
!valid_symbols[MISSING_SEPARATOR_BEFORE_UNMATCHED_BRACE_MARKER] &&
|
|
890
863
|
!valid_symbols[MISSING_COMMAND_SEPARATOR_MARKER] &&
|
|
@@ -896,22 +869,23 @@ static enum PostBlankRecoveryScan scan_post_blank_recovery(
|
|
|
896
869
|
lexer->mark_end(lexer);
|
|
897
870
|
advance_past_blanks(lexer);
|
|
898
871
|
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
}
|
|
872
|
+
const bool after_separator = valid_symbols[OMITTED_ADDRESS_MARKER] ||
|
|
873
|
+
valid_symbols[INCOMPLETE_OMITTED_ADDRESS_MARKER];
|
|
874
|
+
|
|
903
875
|
if (
|
|
904
|
-
valid_symbols[
|
|
905
|
-
(lexer->lookahead == ','
|
|
876
|
+
valid_symbols[BLANKS_AROUND_ADDRESS_SEPARATOR] &&
|
|
877
|
+
(after_separator ? can_start_address(lexer) : lexer->lookahead == ',')
|
|
906
878
|
) {
|
|
907
|
-
|
|
879
|
+
lexer->mark_end(lexer);
|
|
880
|
+
*symbol = BLANKS_AROUND_ADDRESS_SEPARATOR;
|
|
908
881
|
return POST_BLANK_RECOVERY_TOKEN;
|
|
909
882
|
}
|
|
910
|
-
if (
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
883
|
+
if (after_separator && !can_start_address(lexer)) {
|
|
884
|
+
*symbol = lexer->eof(lexer) ? INCOMPLETE_OMITTED_ADDRESS_MARKER
|
|
885
|
+
: OMITTED_ADDRESS_MARKER;
|
|
886
|
+
if (!valid_symbols[*symbol]) {
|
|
887
|
+
return POST_BLANK_RECOVERY_FAILED;
|
|
888
|
+
}
|
|
915
889
|
return POST_BLANK_RECOVERY_TOKEN;
|
|
916
890
|
}
|
|
917
891
|
if (
|
|
@@ -1021,10 +995,6 @@ static bool scan_text_token(
|
|
|
1021
995
|
return true;
|
|
1022
996
|
}
|
|
1023
997
|
|
|
1024
|
-
static bool is_regex_mode(enum ScannerMode mode) {
|
|
1025
|
-
return mode == MODE_REGEX_ADDRESS || mode == MODE_SUBSTITUTE_PATTERN;
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
998
|
static bool regex_is_inside_bracket(const ScannerState *state) {
|
|
1029
999
|
return state->regex_state != REGEX_OUTSIDE_BRACKET;
|
|
1030
1000
|
}
|
|
@@ -1509,6 +1479,18 @@ static bool scan_regex_interval(
|
|
|
1509
1479
|
return emit_symbol(valid_symbols, REGEX_INTERVAL_OPEN, symbol);
|
|
1510
1480
|
}
|
|
1511
1481
|
|
|
1482
|
+
static bool emit_interval_issue(
|
|
1483
|
+
TSLexer *lexer,
|
|
1484
|
+
ScannerState *state,
|
|
1485
|
+
TSSymbol candidate,
|
|
1486
|
+
TSSymbol *symbol
|
|
1487
|
+
) {
|
|
1488
|
+
lexer->mark_end(lexer);
|
|
1489
|
+
state->regex_interval_state = REGEX_INTERVAL_NONE;
|
|
1490
|
+
*symbol = candidate;
|
|
1491
|
+
return true;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1512
1494
|
static bool
|
|
1513
1495
|
scan_invalid_interval_remainder(TSLexer *lexer, ScannerState *state);
|
|
1514
1496
|
|
|
@@ -1604,9 +1586,7 @@ static enum DuplicationContextScan scan_regex_duplication_context_marker(
|
|
|
1604
1586
|
#endif
|
|
1605
1587
|
|
|
1606
1588
|
if (lexer->eof(lexer) && valid_symbols[REGEX_INCOMPLETE_INTERVAL]) {
|
|
1607
|
-
|
|
1608
|
-
state->regex_interval_state = REGEX_INTERVAL_NONE;
|
|
1609
|
-
*symbol = REGEX_INCOMPLETE_INTERVAL;
|
|
1589
|
+
emit_interval_issue(lexer, state, REGEX_INCOMPLETE_INTERVAL, symbol);
|
|
1610
1590
|
return DUPLICATION_CONTEXT_TOKEN;
|
|
1611
1591
|
}
|
|
1612
1592
|
|
|
@@ -1615,9 +1595,7 @@ static enum DuplicationContextScan scan_regex_duplication_context_marker(
|
|
|
1615
1595
|
return DUPLICATION_CONTEXT_TOKEN;
|
|
1616
1596
|
}
|
|
1617
1597
|
scan_invalid_interval_remainder(lexer, state);
|
|
1618
|
-
|
|
1619
|
-
state->regex_interval_state = REGEX_INTERVAL_NONE;
|
|
1620
|
-
*symbol = REGEX_INVALID_INTERVAL;
|
|
1598
|
+
emit_interval_issue(lexer, state, REGEX_INVALID_INTERVAL, symbol);
|
|
1621
1599
|
return DUPLICATION_CONTEXT_TOKEN;
|
|
1622
1600
|
}
|
|
1623
1601
|
|
|
@@ -2053,10 +2031,12 @@ static bool scan_regex_token(
|
|
|
2053
2031
|
return true;
|
|
2054
2032
|
}
|
|
2055
2033
|
if (lexer->eof(lexer) && valid_symbols[REGEX_INCOMPLETE_INTERVAL]) {
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2034
|
+
return emit_interval_issue(
|
|
2035
|
+
lexer,
|
|
2036
|
+
state,
|
|
2037
|
+
REGEX_INCOMPLETE_INTERVAL,
|
|
2038
|
+
symbol
|
|
2039
|
+
);
|
|
2060
2040
|
}
|
|
2061
2041
|
if (!valid_symbols[REGEX_INVALID_INTERVAL]) {
|
|
2062
2042
|
return false;
|
|
@@ -2067,10 +2047,7 @@ static bool scan_regex_token(
|
|
|
2067
2047
|
advance_past_escaped_character(lexer);
|
|
2068
2048
|
scan_invalid_interval_remainder(lexer, state);
|
|
2069
2049
|
}
|
|
2070
|
-
|
|
2071
|
-
state->regex_interval_state = REGEX_INTERVAL_NONE;
|
|
2072
|
-
*symbol = REGEX_INVALID_INTERVAL;
|
|
2073
|
-
return true;
|
|
2050
|
+
return emit_interval_issue(lexer, state, REGEX_INVALID_INTERVAL, symbol);
|
|
2074
2051
|
}
|
|
2075
2052
|
#endif
|
|
2076
2053
|
|
|
@@ -2514,226 +2491,191 @@ static bool scan_translate_token(
|
|
|
2514
2491
|
return false;
|
|
2515
2492
|
}
|
|
2516
2493
|
|
|
2517
|
-
static bool
|
|
2518
|
-
ScannerState *state,
|
|
2494
|
+
static bool scan_regex_recovery_marker(
|
|
2519
2495
|
TSLexer *lexer,
|
|
2496
|
+
ScannerState *state,
|
|
2520
2497
|
const bool *valid_symbols,
|
|
2521
2498
|
TSSymbol *symbol
|
|
2522
2499
|
) {
|
|
2523
|
-
if (valid_symbols[ERROR_SENTINEL]) {
|
|
2524
|
-
return false;
|
|
2525
|
-
}
|
|
2526
|
-
|
|
2527
|
-
if (state->mode == MODE_TEXT) {
|
|
2528
|
-
return scan_text_token(lexer, state, valid_symbols, symbol);
|
|
2529
|
-
}
|
|
2530
|
-
|
|
2531
2500
|
#if !SED_REGEX_EXTENDED
|
|
2532
2501
|
if (
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
emit_missing_marker(
|
|
2547
|
-
lexer,
|
|
2548
|
-
valid_symbols,
|
|
2549
|
-
BRE_PLUS_ESCAPE_MARKER,
|
|
2550
|
-
symbol
|
|
2551
|
-
) ||
|
|
2552
|
-
emit_missing_marker(
|
|
2553
|
-
lexer,
|
|
2554
|
-
valid_symbols,
|
|
2555
|
-
UNMATCHED_INTERVAL_CLOSE_MARKER,
|
|
2556
|
-
symbol
|
|
2557
|
-
))
|
|
2502
|
+
emit_missing_marker(
|
|
2503
|
+
lexer,
|
|
2504
|
+
valid_symbols,
|
|
2505
|
+
BRE_VERTICAL_LINE_ESCAPE_MARKER,
|
|
2506
|
+
symbol
|
|
2507
|
+
) ||
|
|
2508
|
+
emit_missing_marker(
|
|
2509
|
+
lexer,
|
|
2510
|
+
valid_symbols,
|
|
2511
|
+
BRE_QUESTION_MARK_ESCAPE_MARKER,
|
|
2512
|
+
symbol
|
|
2513
|
+
) ||
|
|
2514
|
+
emit_missing_marker(lexer, valid_symbols, BRE_PLUS_ESCAPE_MARKER, symbol)
|
|
2558
2515
|
) {
|
|
2559
2516
|
return true;
|
|
2560
2517
|
}
|
|
2561
2518
|
#endif
|
|
2562
2519
|
|
|
2520
|
+
const bool at_line_boundary = lexer->eof(lexer) || lexer->lookahead == '\n';
|
|
2521
|
+
const bool at_regex_end =
|
|
2522
|
+
at_line_boundary || lexer->lookahead == state->delimiter;
|
|
2523
|
+
|
|
2563
2524
|
if (
|
|
2564
|
-
is_regex_mode(state->mode) &&
|
|
2565
2525
|
state->regex_state ==
|
|
2566
2526
|
REGEX_OUTSIDE_BRACKET &&
|
|
2567
2527
|
state->regex_group_depth >
|
|
2568
2528
|
0 &&
|
|
2569
2529
|
!state->regex_after_alternation &&
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2530
|
+
at_regex_end &&
|
|
2531
|
+
emit_missing_marker(
|
|
2532
|
+
lexer,
|
|
2533
|
+
valid_symbols,
|
|
2534
|
+
lexer->eof(lexer) ? MISSING_SUBEXPRESSION_MARKER
|
|
2535
|
+
: MISSING_SUBEXPRESSION_PLACEHOLDER_MARKER,
|
|
2536
|
+
symbol
|
|
2537
|
+
)
|
|
2574
2538
|
) {
|
|
2575
|
-
|
|
2576
|
-
? MISSING_SUBEXPRESSION_MARKER
|
|
2577
|
-
: MISSING_SUBEXPRESSION_PLACEHOLDER_MARKER;
|
|
2578
|
-
if (valid_symbols[candidate]) {
|
|
2579
|
-
lexer->mark_end(lexer);
|
|
2580
|
-
*symbol = candidate;
|
|
2581
|
-
return true;
|
|
2582
|
-
}
|
|
2539
|
+
return true;
|
|
2583
2540
|
}
|
|
2584
2541
|
|
|
2585
2542
|
if (
|
|
2586
|
-
is_regex_mode(state->mode) &&
|
|
2587
2543
|
(state->regex_state ==
|
|
2588
2544
|
REGEX_BRACKET_FIRST ||
|
|
2589
2545
|
state->regex_state == REGEX_BRACKET_AFTER_CARET) &&
|
|
2590
|
-
|
|
2546
|
+
at_line_boundary &&
|
|
2547
|
+
emit_missing_marker(
|
|
2548
|
+
lexer,
|
|
2549
|
+
valid_symbols,
|
|
2550
|
+
lexer->eof(lexer) ? INCOMPLETE_BRACKET_LIST_MARKER
|
|
2551
|
+
: MISSING_BRACKET_LIST_MARKER,
|
|
2552
|
+
symbol
|
|
2553
|
+
)
|
|
2591
2554
|
) {
|
|
2592
|
-
|
|
2593
|
-
? INCOMPLETE_BRACKET_LIST_MARKER
|
|
2594
|
-
: MISSING_BRACKET_LIST_MARKER;
|
|
2595
|
-
if (valid_symbols[candidate]) {
|
|
2596
|
-
lexer->mark_end(lexer);
|
|
2597
|
-
*symbol = candidate;
|
|
2598
|
-
return true;
|
|
2599
|
-
}
|
|
2555
|
+
return true;
|
|
2600
2556
|
}
|
|
2601
2557
|
|
|
2602
2558
|
if (
|
|
2603
|
-
is_regex_mode(state->mode) &&
|
|
2604
2559
|
state->regex_bracket_term_state !=
|
|
2605
2560
|
REGEX_BRACKET_TERM_NONE &&
|
|
2606
|
-
|
|
2561
|
+
at_line_boundary &&
|
|
2562
|
+
emit_missing_marker(
|
|
2563
|
+
lexer,
|
|
2564
|
+
valid_symbols,
|
|
2565
|
+
lexer->eof(lexer) ? REGEX_INCOMPLETE_BRACKET_TERM
|
|
2566
|
+
: REGEX_MALFORMED_BRACKET_TERM,
|
|
2567
|
+
symbol
|
|
2568
|
+
)
|
|
2607
2569
|
) {
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
lexer->mark_end(lexer);
|
|
2612
|
-
state->regex_bracket_term_state = REGEX_BRACKET_TERM_NONE;
|
|
2613
|
-
finish_compound_bracket_element(state);
|
|
2614
|
-
*symbol = candidate;
|
|
2615
|
-
return true;
|
|
2616
|
-
}
|
|
2570
|
+
state->regex_bracket_term_state = REGEX_BRACKET_TERM_NONE;
|
|
2571
|
+
finish_compound_bracket_element(state);
|
|
2572
|
+
return true;
|
|
2617
2573
|
}
|
|
2618
2574
|
|
|
2619
2575
|
if (
|
|
2620
|
-
is_regex_mode(state->mode) &&
|
|
2621
2576
|
regex_is_inside_bracket(state) &&
|
|
2622
|
-
|
|
2577
|
+
at_line_boundary &&
|
|
2578
|
+
emit_missing_marker(
|
|
2579
|
+
lexer,
|
|
2580
|
+
valid_symbols,
|
|
2581
|
+
lexer->eof(lexer) ? INCOMPLETE_BRACKET_EXPRESSION_MARKER
|
|
2582
|
+
: UNCLOSED_BRACKET_EXPRESSION_MARKER,
|
|
2583
|
+
symbol
|
|
2584
|
+
)
|
|
2623
2585
|
) {
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
if (valid_symbols[candidate]) {
|
|
2628
|
-
lexer->mark_end(lexer);
|
|
2629
|
-
state->regex_state = REGEX_OUTSIDE_BRACKET;
|
|
2630
|
-
reset_bracket_tracking(state);
|
|
2631
|
-
*symbol = candidate;
|
|
2632
|
-
return true;
|
|
2633
|
-
}
|
|
2586
|
+
state->regex_state = REGEX_OUTSIDE_BRACKET;
|
|
2587
|
+
reset_bracket_tracking(state);
|
|
2588
|
+
return true;
|
|
2634
2589
|
}
|
|
2635
2590
|
|
|
2636
2591
|
#if SED_REGEX_EXTENDED
|
|
2637
2592
|
if (
|
|
2638
|
-
is_regex_mode(state->mode) &&
|
|
2639
2593
|
state->regex_state ==
|
|
2640
2594
|
REGEX_OUTSIDE_BRACKET &&
|
|
2641
2595
|
state->regex_after_alternation &&
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
lexer
|
|
2645
|
-
|
|
2646
|
-
lexer->eof(lexer)
|
|
2596
|
+
at_regex_end &&
|
|
2597
|
+
emit_missing_marker(
|
|
2598
|
+
lexer,
|
|
2599
|
+
valid_symbols,
|
|
2600
|
+
lexer->eof(lexer) ? INCOMPLETE_ALTERNATIVE_MARKER
|
|
2601
|
+
: EMPTY_ALTERNATIVE_MARKER,
|
|
2602
|
+
symbol
|
|
2603
|
+
)
|
|
2647
2604
|
) {
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
if (valid_symbols[candidate]) {
|
|
2651
|
-
lexer->mark_end(lexer);
|
|
2652
|
-
state->regex_after_alternation = false;
|
|
2653
|
-
*symbol = candidate;
|
|
2654
|
-
return true;
|
|
2655
|
-
}
|
|
2605
|
+
state->regex_after_alternation = false;
|
|
2606
|
+
return true;
|
|
2656
2607
|
}
|
|
2657
2608
|
#endif
|
|
2658
2609
|
|
|
2659
2610
|
if (
|
|
2660
|
-
is_regex_mode(state->mode) &&
|
|
2661
2611
|
state->regex_interval_state !=
|
|
2662
2612
|
REGEX_INTERVAL_NONE &&
|
|
2663
|
-
(
|
|
2664
|
-
state->delimiter ||
|
|
2665
|
-
lexer->lookahead ==
|
|
2666
|
-
'\n' ||
|
|
2613
|
+
(at_regex_end
|
|
2667
2614
|
#if !SED_REGEX_EXTENDED
|
|
2668
|
-
|
|
2615
|
+
|| (state->delimiter == '}' && lexer->lookahead == '\\')
|
|
2669
2616
|
#endif
|
|
2670
|
-
|
|
2617
|
+
) &&
|
|
2618
|
+
emit_missing_marker(
|
|
2619
|
+
lexer,
|
|
2620
|
+
valid_symbols,
|
|
2621
|
+
lexer->eof(lexer) ? REGEX_INCOMPLETE_INTERVAL : REGEX_INVALID_INTERVAL,
|
|
2622
|
+
symbol
|
|
2623
|
+
)
|
|
2671
2624
|
) {
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
if (valid_symbols[candidate]) {
|
|
2675
|
-
lexer->mark_end(lexer);
|
|
2676
|
-
state->regex_interval_state = REGEX_INTERVAL_NONE;
|
|
2677
|
-
*symbol = candidate;
|
|
2678
|
-
return true;
|
|
2679
|
-
}
|
|
2625
|
+
state->regex_interval_state = REGEX_INTERVAL_NONE;
|
|
2626
|
+
return true;
|
|
2680
2627
|
}
|
|
2681
2628
|
|
|
2682
2629
|
if (
|
|
2683
|
-
is_regex_mode(state->mode) &&
|
|
2684
2630
|
state->regex_state ==
|
|
2685
2631
|
REGEX_OUTSIDE_BRACKET &&
|
|
2686
|
-
|
|
2632
|
+
state->regex_group_depth >
|
|
2633
|
+
0 &&
|
|
2634
|
+
at_line_boundary &&
|
|
2635
|
+
emit_missing_marker(
|
|
2636
|
+
lexer,
|
|
2637
|
+
valid_symbols,
|
|
2638
|
+
lexer->eof(lexer) ? REGEX_INCOMPLETE_GROUP : REGEX_UNCLOSED_GROUP,
|
|
2639
|
+
symbol
|
|
2640
|
+
)
|
|
2687
2641
|
) {
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
lexer->eof(lexer) ? REGEX_INCOMPLETE_GROUP : REGEX_UNCLOSED_GROUP;
|
|
2691
|
-
if (valid_symbols[candidate]) {
|
|
2692
|
-
lexer->mark_end(lexer);
|
|
2693
|
-
state->regex_group_depth--;
|
|
2694
|
-
*symbol = candidate;
|
|
2695
|
-
return true;
|
|
2696
|
-
}
|
|
2697
|
-
}
|
|
2698
|
-
}
|
|
2699
|
-
|
|
2700
|
-
const bool delimiter_is_active = state->mode !=
|
|
2701
|
-
MODE_NONE &&
|
|
2702
|
-
state->mode !=
|
|
2703
|
-
MODE_TEXT &&
|
|
2704
|
-
lexer->lookahead ==
|
|
2705
|
-
state->delimiter &&
|
|
2706
|
-
(!is_regex_mode(state->mode) ||
|
|
2707
|
-
state->regex_state == REGEX_OUTSIDE_BRACKET);
|
|
2708
|
-
if (delimiter_is_active) {
|
|
2709
|
-
if (state->regex_group_depth > 0 && valid_symbols[REGEX_UNCLOSED_GROUP]) {
|
|
2710
|
-
state->regex_group_depth--;
|
|
2711
|
-
*symbol = REGEX_UNCLOSED_GROUP;
|
|
2712
|
-
return true;
|
|
2713
|
-
}
|
|
2714
|
-
return scan_active_mode_delimiter(lexer, state, valid_symbols, symbol);
|
|
2642
|
+
state->regex_group_depth--;
|
|
2643
|
+
return true;
|
|
2715
2644
|
}
|
|
2716
2645
|
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
case MODE_SUBSTITUTE_PATTERN:
|
|
2720
|
-
return scan_regex_token(lexer, state, valid_symbols, symbol);
|
|
2721
|
-
case MODE_SUBSTITUTE_REPLACEMENT:
|
|
2722
|
-
return scan_replacement_token(lexer, state, valid_symbols, symbol);
|
|
2723
|
-
case MODE_TRANSLATE_SOURCE:
|
|
2724
|
-
case MODE_TRANSLATE_DESTINATION:
|
|
2725
|
-
return scan_translate_token(lexer, state, valid_symbols, symbol);
|
|
2726
|
-
case MODE_TEXT:
|
|
2727
|
-
return false;
|
|
2728
|
-
case MODE_NONE:
|
|
2729
|
-
break;
|
|
2730
|
-
}
|
|
2646
|
+
return false;
|
|
2647
|
+
}
|
|
2731
2648
|
|
|
2649
|
+
static bool scan_command_token(
|
|
2650
|
+
TSLexer *lexer,
|
|
2651
|
+
ScannerState *state,
|
|
2652
|
+
const bool *valid_symbols,
|
|
2653
|
+
TSSymbol *symbol
|
|
2654
|
+
) {
|
|
2732
2655
|
if (valid_symbols[LINE_WORD] && scan_to_physical_line_end(lexer, false)) {
|
|
2733
2656
|
*symbol = LINE_WORD;
|
|
2734
2657
|
return true;
|
|
2735
2658
|
}
|
|
2736
2659
|
|
|
2660
|
+
if (valid_symbols[FLAG_AFTER_WRITE_MARKER]) {
|
|
2661
|
+
const enum FlagAfterWriteScan scan = scan_flag_after_write_marker(lexer);
|
|
2662
|
+
if (scan == FLAG_AFTER_WRITE_MATCH) {
|
|
2663
|
+
*symbol = FLAG_AFTER_WRITE_MARKER;
|
|
2664
|
+
return true;
|
|
2665
|
+
}
|
|
2666
|
+
if (
|
|
2667
|
+
scan ==
|
|
2668
|
+
FLAG_AFTER_WRITE_FALLBACK &&
|
|
2669
|
+
valid_symbols[OMITTED_FILE_SEPARATOR_MARKER]
|
|
2670
|
+
) {
|
|
2671
|
+
*symbol = OMITTED_FILE_SEPARATOR_MARKER;
|
|
2672
|
+
return true;
|
|
2673
|
+
}
|
|
2674
|
+
if (scan == FLAG_AFTER_WRITE_FALLBACK) {
|
|
2675
|
+
return false;
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2737
2679
|
if (
|
|
2738
2680
|
valid_symbols[SUBSTITUTION_WFILE_ARGUMENT] &&
|
|
2739
2681
|
scan_substitution_wfile_argument(lexer)
|
|
@@ -2750,15 +2692,7 @@ static bool sed_scanner_scan_impl(
|
|
|
2750
2692
|
if (
|
|
2751
2693
|
valid_symbols[INVALID_SUBSTITUTION_FLAG] &&
|
|
2752
2694
|
!is_blank(lexer->lookahead) &&
|
|
2753
|
-
!
|
|
2754
|
-
lexer->lookahead !=
|
|
2755
|
-
'g' &&
|
|
2756
|
-
lexer->lookahead !=
|
|
2757
|
-
'i' &&
|
|
2758
|
-
lexer->lookahead !=
|
|
2759
|
-
'p' &&
|
|
2760
|
-
lexer->lookahead !=
|
|
2761
|
-
'w' &&
|
|
2695
|
+
!is_substitution_flag_character(lexer->lookahead) &&
|
|
2762
2696
|
lexer->lookahead !=
|
|
2763
2697
|
';' &&
|
|
2764
2698
|
lexer->lookahead !=
|
|
@@ -2794,11 +2728,23 @@ static bool sed_scanner_scan_impl(
|
|
|
2794
2728
|
return true;
|
|
2795
2729
|
}
|
|
2796
2730
|
|
|
2731
|
+
// Preserve an address interpretation before reserved-function recovery.
|
|
2732
|
+
if (
|
|
2733
|
+
valid_symbols[MISSING_ADDRESS_SEPARATOR_MARKER] && can_start_address(lexer)
|
|
2734
|
+
) {
|
|
2735
|
+
return emit_missing_marker(
|
|
2736
|
+
lexer,
|
|
2737
|
+
valid_symbols,
|
|
2738
|
+
MISSING_ADDRESS_SEPARATOR_MARKER,
|
|
2739
|
+
symbol
|
|
2740
|
+
);
|
|
2741
|
+
}
|
|
2742
|
+
|
|
2797
2743
|
if (
|
|
2798
|
-
valid_symbols[
|
|
2744
|
+
valid_symbols[RESERVED_UNKNOWN_FUNCTION_TOKEN] &&
|
|
2799
2745
|
scan_reserved_unknown_function(lexer)
|
|
2800
2746
|
) {
|
|
2801
|
-
*symbol =
|
|
2747
|
+
*symbol = RESERVED_UNKNOWN_FUNCTION_TOKEN;
|
|
2802
2748
|
return true;
|
|
2803
2749
|
}
|
|
2804
2750
|
|
|
@@ -2839,6 +2785,9 @@ static bool sed_scanner_scan_impl(
|
|
|
2839
2785
|
}
|
|
2840
2786
|
|
|
2841
2787
|
if (
|
|
2788
|
+
valid_symbols[OMITTED_FIRST_ADDRESS_MARKER] &&
|
|
2789
|
+
lexer->lookahead ==
|
|
2790
|
+
',' &&
|
|
2842
2791
|
emit_missing_marker(
|
|
2843
2792
|
lexer,
|
|
2844
2793
|
valid_symbols,
|
|
@@ -2850,54 +2799,20 @@ static bool sed_scanner_scan_impl(
|
|
|
2850
2799
|
}
|
|
2851
2800
|
|
|
2852
2801
|
if (
|
|
2853
|
-
valid_symbols[OMITTED_ADDRESS_MARKER]
|
|
2802
|
+
(valid_symbols[OMITTED_ADDRESS_MARKER] ||
|
|
2803
|
+
valid_symbols[INCOMPLETE_OMITTED_ADDRESS_MARKER]) &&
|
|
2854
2804
|
!can_start_address(lexer) &&
|
|
2855
2805
|
!is_blank(lexer->lookahead)
|
|
2856
2806
|
) {
|
|
2857
2807
|
return emit_missing_marker(
|
|
2858
2808
|
lexer,
|
|
2859
2809
|
valid_symbols,
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
);
|
|
2863
|
-
}
|
|
2864
|
-
|
|
2865
|
-
if (
|
|
2866
|
-
valid_symbols[ADDITIONAL_ADDRESS_MARKER] &&
|
|
2867
|
-
(lexer->lookahead == ',' || can_start_address(lexer))
|
|
2868
|
-
) {
|
|
2869
|
-
return emit_missing_marker(
|
|
2870
|
-
lexer,
|
|
2871
|
-
valid_symbols,
|
|
2872
|
-
ADDITIONAL_ADDRESS_MARKER,
|
|
2810
|
+
lexer->eof(lexer) ? INCOMPLETE_OMITTED_ADDRESS_MARKER
|
|
2811
|
+
: OMITTED_ADDRESS_MARKER,
|
|
2873
2812
|
symbol
|
|
2874
2813
|
);
|
|
2875
2814
|
}
|
|
2876
2815
|
|
|
2877
|
-
if (
|
|
2878
|
-
valid_symbols[MISSING_ADDRESS_SEPARATOR_MARKER] && can_start_address(lexer)
|
|
2879
|
-
) {
|
|
2880
|
-
return emit_missing_marker(
|
|
2881
|
-
lexer,
|
|
2882
|
-
valid_symbols,
|
|
2883
|
-
MISSING_ADDRESS_SEPARATOR_MARKER,
|
|
2884
|
-
symbol
|
|
2885
|
-
);
|
|
2886
|
-
}
|
|
2887
|
-
|
|
2888
|
-
if (
|
|
2889
|
-
valid_symbols[BLANKS_AROUND_ADDRESS_SEPARATOR_MARKER] &&
|
|
2890
|
-
lexer->lookahead == ','
|
|
2891
|
-
) {
|
|
2892
|
-
lexer->mark_end(lexer);
|
|
2893
|
-
advance(lexer);
|
|
2894
|
-
if (is_blank(lexer->lookahead)) {
|
|
2895
|
-
*symbol = BLANKS_AROUND_ADDRESS_SEPARATOR_MARKER;
|
|
2896
|
-
return true;
|
|
2897
|
-
}
|
|
2898
|
-
return false;
|
|
2899
|
-
}
|
|
2900
|
-
|
|
2901
2816
|
if (is_blank(lexer->lookahead)) {
|
|
2902
2817
|
switch (scan_post_blank_recovery(lexer, valid_symbols, symbol)) {
|
|
2903
2818
|
case POST_BLANK_RECOVERY_TOKEN:
|
|
@@ -2909,18 +2824,6 @@ static bool sed_scanner_scan_impl(
|
|
|
2909
2824
|
}
|
|
2910
2825
|
}
|
|
2911
2826
|
|
|
2912
|
-
if (
|
|
2913
|
-
emit_missing_marker(lexer, valid_symbols, DUPLICATE_NEGATION_MARKER, symbol)
|
|
2914
|
-
) {
|
|
2915
|
-
return true;
|
|
2916
|
-
}
|
|
2917
|
-
|
|
2918
|
-
if (
|
|
2919
|
-
emit_missing_marker(lexer, valid_symbols, EXCESS_ADDRESSES_MARKER, symbol)
|
|
2920
|
-
) {
|
|
2921
|
-
return true;
|
|
2922
|
-
}
|
|
2923
|
-
|
|
2924
2827
|
if (
|
|
2925
2828
|
!at_command_boundary(lexer) &&
|
|
2926
2829
|
!is_blank(lexer->lookahead) &&
|
|
@@ -3029,6 +2932,60 @@ static bool sed_scanner_scan_impl(
|
|
|
3029
2932
|
return false;
|
|
3030
2933
|
}
|
|
3031
2934
|
|
|
2935
|
+
static bool sed_scanner_scan_impl(
|
|
2936
|
+
ScannerState *state,
|
|
2937
|
+
TSLexer *lexer,
|
|
2938
|
+
const bool *valid_symbols,
|
|
2939
|
+
TSSymbol *symbol
|
|
2940
|
+
) {
|
|
2941
|
+
if (valid_symbols[ERROR_SENTINEL]) {
|
|
2942
|
+
return false;
|
|
2943
|
+
}
|
|
2944
|
+
|
|
2945
|
+
if (state->mode == MODE_TEXT) {
|
|
2946
|
+
return scan_text_token(lexer, state, valid_symbols, symbol);
|
|
2947
|
+
}
|
|
2948
|
+
|
|
2949
|
+
if (
|
|
2950
|
+
is_regex_mode(state->mode) &&
|
|
2951
|
+
scan_regex_recovery_marker(lexer, state, valid_symbols, symbol)
|
|
2952
|
+
) {
|
|
2953
|
+
return true;
|
|
2954
|
+
}
|
|
2955
|
+
|
|
2956
|
+
const bool delimiter_is_active = state->mode !=
|
|
2957
|
+
MODE_NONE &&
|
|
2958
|
+
lexer->lookahead ==
|
|
2959
|
+
state->delimiter &&
|
|
2960
|
+
(!is_regex_mode(state->mode) ||
|
|
2961
|
+
state->regex_state == REGEX_OUTSIDE_BRACKET);
|
|
2962
|
+
if (delimiter_is_active) {
|
|
2963
|
+
if (state->regex_group_depth > 0 && valid_symbols[REGEX_UNCLOSED_GROUP]) {
|
|
2964
|
+
state->regex_group_depth--;
|
|
2965
|
+
*symbol = REGEX_UNCLOSED_GROUP;
|
|
2966
|
+
return true;
|
|
2967
|
+
}
|
|
2968
|
+
return scan_active_mode_delimiter(lexer, state, valid_symbols, symbol);
|
|
2969
|
+
}
|
|
2970
|
+
|
|
2971
|
+
switch (state->mode) {
|
|
2972
|
+
case MODE_REGEX_ADDRESS:
|
|
2973
|
+
case MODE_SUBSTITUTE_PATTERN:
|
|
2974
|
+
return scan_regex_token(lexer, state, valid_symbols, symbol);
|
|
2975
|
+
case MODE_SUBSTITUTE_REPLACEMENT:
|
|
2976
|
+
return scan_replacement_token(lexer, state, valid_symbols, symbol);
|
|
2977
|
+
case MODE_TRANSLATE_SOURCE:
|
|
2978
|
+
case MODE_TRANSLATE_DESTINATION:
|
|
2979
|
+
return scan_translate_token(lexer, state, valid_symbols, symbol);
|
|
2980
|
+
case MODE_TEXT:
|
|
2981
|
+
return false;
|
|
2982
|
+
case MODE_NONE:
|
|
2983
|
+
break;
|
|
2984
|
+
}
|
|
2985
|
+
|
|
2986
|
+
return scan_command_token(lexer, state, valid_symbols, symbol);
|
|
2987
|
+
}
|
|
2988
|
+
|
|
3032
2989
|
static void
|
|
3033
2990
|
update_regex_position_after_symbol(ScannerState *state, TSSymbol symbol) {
|
|
3034
2991
|
#if !SED_REGEX_EXTENDED
|
|
@@ -3037,9 +2994,7 @@ update_regex_position_after_symbol(ScannerState *state, TSSymbol symbol) {
|
|
|
3037
2994
|
BRE_VERTICAL_LINE_ESCAPE_MARKER ||
|
|
3038
2995
|
symbol ==
|
|
3039
2996
|
BRE_QUESTION_MARK_ESCAPE_MARKER ||
|
|
3040
|
-
symbol ==
|
|
3041
|
-
BRE_PLUS_ESCAPE_MARKER ||
|
|
3042
|
-
symbol == UNMATCHED_INTERVAL_CLOSE_MARKER
|
|
2997
|
+
symbol == BRE_PLUS_ESCAPE_MARKER
|
|
3043
2998
|
) {
|
|
3044
2999
|
return;
|
|
3045
3000
|
}
|
|
@@ -3081,7 +3036,15 @@ update_regex_position_after_symbol(ScannerState *state, TSSymbol symbol) {
|
|
|
3081
3036
|
}
|
|
3082
3037
|
#endif
|
|
3083
3038
|
|
|
3084
|
-
|
|
3039
|
+
bool is_anchor =
|
|
3040
|
+
symbol == REGEX_BEGINNING_ANCHOR || symbol == REGEX_END_ANCHOR;
|
|
3041
|
+
#if !SED_REGEX_EXTENDED
|
|
3042
|
+
is_anchor = is_anchor ||
|
|
3043
|
+
symbol ==
|
|
3044
|
+
REGEX_BRE_SUBEXPRESSION_CARET ||
|
|
3045
|
+
symbol == REGEX_BRE_SUBEXPRESSION_DOLLAR;
|
|
3046
|
+
#endif
|
|
3047
|
+
if (is_anchor) {
|
|
3085
3048
|
set_regex_position(state, true, REGEX_DUPLICATION_NONE, false, true);
|
|
3086
3049
|
return;
|
|
3087
3050
|
}
|