prism 0.17.0 → 0.18.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +37 -1
- data/Makefile +5 -5
- data/README.md +2 -2
- data/config.yml +26 -13
- data/docs/build_system.md +6 -6
- data/docs/building.md +1 -1
- data/docs/configuration.md +1 -0
- data/docs/encoding.md +68 -32
- data/docs/heredocs.md +1 -1
- data/docs/javascript.md +29 -1
- data/docs/releasing.md +4 -1
- data/docs/ruby_api.md +14 -0
- data/ext/prism/api_node.c +74 -45
- data/ext/prism/extconf.rb +91 -127
- data/ext/prism/extension.c +4 -1
- data/ext/prism/extension.h +1 -1
- data/include/prism/ast.h +148 -133
- data/include/prism/diagnostic.h +27 -1
- data/include/prism/enc/pm_encoding.h +42 -1
- data/include/prism/parser.h +6 -0
- data/include/prism/version.h +2 -2
- data/lib/prism/compiler.rb +3 -3
- data/lib/prism/debug.rb +4 -0
- data/lib/prism/desugar_compiler.rb +1 -0
- data/lib/prism/dispatcher.rb +14 -14
- data/lib/prism/dot_visitor.rb +4334 -0
- data/lib/prism/dsl.rb +11 -11
- data/lib/prism/ffi.rb +3 -3
- data/lib/prism/mutation_compiler.rb +6 -6
- data/lib/prism/node.rb +182 -113
- data/lib/prism/node_ext.rb +61 -3
- data/lib/prism/parse_result.rb +46 -12
- data/lib/prism/serialize.rb +124 -130
- data/lib/prism/visitor.rb +3 -3
- data/lib/prism.rb +1 -0
- data/prism.gemspec +5 -1
- data/rbi/prism.rbi +5565 -5540
- data/rbi/prism_static.rbi +138 -142
- data/sig/prism.rbs +47 -32
- data/src/diagnostic.c +61 -3
- data/src/enc/pm_big5.c +63 -0
- data/src/enc/pm_cp51932.c +57 -0
- data/src/enc/pm_euc_jp.c +10 -0
- data/src/enc/pm_gbk.c +5 -2
- data/src/enc/pm_tables.c +1478 -148
- data/src/node.c +33 -21
- data/src/prettyprint.c +1027 -925
- data/src/prism.c +925 -374
- data/src/regexp.c +12 -12
- data/src/serialize.c +36 -9
- metadata +6 -2
data/src/prism.c
CHANGED
@@ -16,7 +16,7 @@ pm_version(void) {
|
|
16
16
|
|
17
17
|
#ifndef PM_DEBUG_LOGGING
|
18
18
|
/**
|
19
|
-
* Debugging logging will provide you
|
19
|
+
* Debugging logging will provide you with additional debugging functions as
|
20
20
|
* well as automatically replace some functions with their debugging
|
21
21
|
* counterparts.
|
22
22
|
*/
|
@@ -275,6 +275,16 @@ lex_mode_push_list(pm_parser_t *parser, bool interpolation, uint8_t delimiter) {
|
|
275
275
|
return lex_mode_push(parser, lex_mode);
|
276
276
|
}
|
277
277
|
|
278
|
+
/**
|
279
|
+
* Push on a new list lex mode that is only used for compatibility. This is
|
280
|
+
* called when we're at the end of the file. We want the parser to be able to
|
281
|
+
* perform its normal error tolerance.
|
282
|
+
*/
|
283
|
+
static inline bool
|
284
|
+
lex_mode_push_list_eof(pm_parser_t *parser) {
|
285
|
+
return lex_mode_push_list(parser, false, '\0');
|
286
|
+
}
|
287
|
+
|
278
288
|
/**
|
279
289
|
* Push on a new regexp lex mode.
|
280
290
|
*/
|
@@ -346,6 +356,16 @@ lex_mode_push_string(pm_parser_t *parser, bool interpolation, bool label_allowed
|
|
346
356
|
return lex_mode_push(parser, lex_mode);
|
347
357
|
}
|
348
358
|
|
359
|
+
/**
|
360
|
+
* Push on a new string lex mode that is only used for compatibility. This is
|
361
|
+
* called when we're at the end of the file. We want the parser to be able to
|
362
|
+
* perform its normal error tolerance.
|
363
|
+
*/
|
364
|
+
static inline bool
|
365
|
+
lex_mode_push_string_eof(pm_parser_t *parser) {
|
366
|
+
return lex_mode_push_string(parser, false, false, '\0', '\0');
|
367
|
+
}
|
368
|
+
|
349
369
|
/**
|
350
370
|
* Pop the current lex state off the stack. If we're within the pre-allocated
|
351
371
|
* space of the lex state stack, then we'll just decrement the index. Otherwise
|
@@ -395,7 +415,7 @@ lex_state_ignored_p(pm_parser_t *parser) {
|
|
395
415
|
|
396
416
|
static inline bool
|
397
417
|
lex_state_beg_p(pm_parser_t *parser) {
|
398
|
-
return lex_state_p(parser, PM_LEX_STATE_BEG_ANY) || (parser->lex_state == (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED));
|
418
|
+
return lex_state_p(parser, PM_LEX_STATE_BEG_ANY) || ((parser->lex_state & (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED)) == (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED));
|
399
419
|
}
|
400
420
|
|
401
421
|
static inline bool
|
@@ -459,6 +479,11 @@ pm_parser_err(pm_parser_t *parser, const uint8_t *start, const uint8_t *end, pm_
|
|
459
479
|
pm_diagnostic_list_append(&parser->error_list, start, end, diag_id);
|
460
480
|
}
|
461
481
|
|
482
|
+
/**
|
483
|
+
* Append an error to the list of errors on the parser using a format string.
|
484
|
+
*/
|
485
|
+
#define PM_PARSER_ERR_FORMAT(parser, start, end, diag_id, ...) pm_diagnostic_list_append_format(&parser->error_list, start, end, diag_id, __VA_ARGS__)
|
486
|
+
|
462
487
|
/**
|
463
488
|
* Append an error to the list of errors on the parser using the location of the
|
464
489
|
* current token.
|
@@ -469,12 +494,10 @@ pm_parser_err_current(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
|
|
469
494
|
}
|
470
495
|
|
471
496
|
/**
|
472
|
-
* Append an error to the list of errors on the parser using the given location
|
497
|
+
* Append an error to the list of errors on the parser using the given location
|
498
|
+
* using a format string.
|
473
499
|
*/
|
474
|
-
|
475
|
-
pm_parser_err_location(pm_parser_t *parser, const pm_location_t *location, pm_diagnostic_id_t diag_id) {
|
476
|
-
pm_parser_err(parser, location->start, location->end, diag_id);
|
477
|
-
}
|
500
|
+
#define PM_PARSER_ERR_LOCATION_FORMAT(parser, location, diag_id, ...) pm_diagnostic_list_append_format(&parser->error_list, (location)->start, (location)->end, diag_id, __VA_ARGS__)
|
478
501
|
|
479
502
|
/**
|
480
503
|
* Append an error to the list of errors on the parser using the location of the
|
@@ -485,6 +508,12 @@ pm_parser_err_node(pm_parser_t *parser, const pm_node_t *node, pm_diagnostic_id_
|
|
485
508
|
pm_parser_err(parser, node->location.start, node->location.end, diag_id);
|
486
509
|
}
|
487
510
|
|
511
|
+
/**
|
512
|
+
* Append an error to the list of errors on the parser using the location of the
|
513
|
+
* given node and a format string.
|
514
|
+
*/
|
515
|
+
#define PM_PARSER_ERR_NODE_FORMAT(parser, node, diag_id, ...) pm_diagnostic_list_append_format(&parser->error_list, node->location.start, node->location.end, diag_id, __VA_ARGS__)
|
516
|
+
|
488
517
|
/**
|
489
518
|
* Append an error to the list of errors on the parser using the location of the
|
490
519
|
* previous token.
|
@@ -503,6 +532,12 @@ pm_parser_err_token(pm_parser_t *parser, const pm_token_t *token, pm_diagnostic_
|
|
503
532
|
pm_parser_err(parser, token->start, token->end, diag_id);
|
504
533
|
}
|
505
534
|
|
535
|
+
/**
|
536
|
+
* Append an error to the list of errors on the parser using the location of the
|
537
|
+
* given token and a format string.
|
538
|
+
*/
|
539
|
+
#define PM_PARSER_ERR_TOKEN_FORMAT(parser, token, diag_id, ...) pm_diagnostic_list_append_format(&parser->error_list, token->start, token->end, diag_id, __VA_ARGS__)
|
540
|
+
|
506
541
|
/**
|
507
542
|
* Append a warning to the list of warnings on the parser.
|
508
543
|
*/
|
@@ -567,6 +602,102 @@ pm_parser_optional_constant_id_token(pm_parser_t *parser, const pm_token_t *toke
|
|
567
602
|
return token->type == PM_TOKEN_NOT_PROVIDED ? 0 : pm_parser_constant_id_token(parser, token);
|
568
603
|
}
|
569
604
|
|
605
|
+
/**
|
606
|
+
* Check whether or not the given node is value expression.
|
607
|
+
* If the node is value node, it returns NULL.
|
608
|
+
* If not, it returns the pointer to the node to be inspected as "void expression".
|
609
|
+
*/
|
610
|
+
static pm_node_t*
|
611
|
+
pm_check_value_expression(pm_node_t *node) {
|
612
|
+
pm_node_t* void_node = NULL;
|
613
|
+
|
614
|
+
while (node != NULL) {
|
615
|
+
switch (PM_NODE_TYPE(node)) {
|
616
|
+
case PM_RETURN_NODE:
|
617
|
+
case PM_BREAK_NODE:
|
618
|
+
case PM_NEXT_NODE:
|
619
|
+
case PM_REDO_NODE:
|
620
|
+
case PM_RETRY_NODE:
|
621
|
+
case PM_MATCH_REQUIRED_NODE:
|
622
|
+
return void_node != NULL ? void_node : node;
|
623
|
+
case PM_MATCH_PREDICATE_NODE:
|
624
|
+
return NULL;
|
625
|
+
case PM_BEGIN_NODE: {
|
626
|
+
pm_begin_node_t *cast = (pm_begin_node_t *) node;
|
627
|
+
node = (pm_node_t *) cast->statements;
|
628
|
+
break;
|
629
|
+
}
|
630
|
+
case PM_PARENTHESES_NODE: {
|
631
|
+
pm_parentheses_node_t *cast = (pm_parentheses_node_t *) node;
|
632
|
+
node = (pm_node_t *) cast->body;
|
633
|
+
break;
|
634
|
+
}
|
635
|
+
case PM_STATEMENTS_NODE: {
|
636
|
+
pm_statements_node_t *cast = (pm_statements_node_t *) node;
|
637
|
+
node = cast->body.nodes[cast->body.size - 1];
|
638
|
+
break;
|
639
|
+
}
|
640
|
+
case PM_IF_NODE: {
|
641
|
+
pm_if_node_t *cast = (pm_if_node_t *) node;
|
642
|
+
if (cast->statements == NULL || cast->consequent == NULL) {
|
643
|
+
return NULL;
|
644
|
+
}
|
645
|
+
pm_node_t *vn = pm_check_value_expression((pm_node_t *) cast->statements);
|
646
|
+
if (vn == NULL) {
|
647
|
+
return NULL;
|
648
|
+
}
|
649
|
+
if (void_node == NULL) {
|
650
|
+
void_node = vn;
|
651
|
+
}
|
652
|
+
node = cast->consequent;
|
653
|
+
break;
|
654
|
+
}
|
655
|
+
case PM_UNLESS_NODE: {
|
656
|
+
pm_unless_node_t *cast = (pm_unless_node_t *) node;
|
657
|
+
if (cast->statements == NULL || cast->consequent == NULL) {
|
658
|
+
return NULL;
|
659
|
+
}
|
660
|
+
pm_node_t *vn = pm_check_value_expression((pm_node_t *) cast->statements);
|
661
|
+
if (vn == NULL) {
|
662
|
+
return NULL;
|
663
|
+
}
|
664
|
+
if (void_node == NULL) {
|
665
|
+
void_node = vn;
|
666
|
+
}
|
667
|
+
node = (pm_node_t *) cast->consequent;
|
668
|
+
break;
|
669
|
+
}
|
670
|
+
case PM_ELSE_NODE: {
|
671
|
+
pm_else_node_t *cast = (pm_else_node_t *) node;
|
672
|
+
node = (pm_node_t *) cast->statements;
|
673
|
+
break;
|
674
|
+
}
|
675
|
+
case PM_AND_NODE: {
|
676
|
+
pm_and_node_t *cast = (pm_and_node_t *) node;
|
677
|
+
node = cast->left;
|
678
|
+
break;
|
679
|
+
}
|
680
|
+
case PM_OR_NODE: {
|
681
|
+
pm_or_node_t *cast = (pm_or_node_t *) node;
|
682
|
+
node = cast->left;
|
683
|
+
break;
|
684
|
+
}
|
685
|
+
default:
|
686
|
+
return NULL;
|
687
|
+
}
|
688
|
+
}
|
689
|
+
|
690
|
+
return NULL;
|
691
|
+
}
|
692
|
+
|
693
|
+
static inline void
|
694
|
+
pm_assert_value_expression(pm_parser_t *parser, pm_node_t *node) {
|
695
|
+
pm_node_t *void_node = pm_check_value_expression(node);
|
696
|
+
if (void_node != NULL) {
|
697
|
+
pm_parser_err_node(parser, void_node, PM_ERR_VOID_EXPRESSION);
|
698
|
+
}
|
699
|
+
}
|
700
|
+
|
570
701
|
/**
|
571
702
|
* The predicate of conditional nodes can change what would otherwise be regular
|
572
703
|
* nodes into specialized nodes. For example:
|
@@ -680,6 +811,27 @@ typedef struct {
|
|
680
811
|
pm_node_t *block;
|
681
812
|
} pm_arguments_t;
|
682
813
|
|
814
|
+
/**
|
815
|
+
* Retrieve the end location of a `pm_arguments_t` object.
|
816
|
+
*/
|
817
|
+
static inline const uint8_t *
|
818
|
+
pm_arguments_end(pm_arguments_t *arguments) {
|
819
|
+
if (arguments->block != NULL) {
|
820
|
+
const uint8_t *end = arguments->block->location.end;
|
821
|
+
if (arguments->closing_loc.start != NULL && arguments->closing_loc.end > end) {
|
822
|
+
end = arguments->closing_loc.end;
|
823
|
+
}
|
824
|
+
return end;
|
825
|
+
}
|
826
|
+
if (arguments->closing_loc.start != NULL) {
|
827
|
+
return arguments->closing_loc.end;
|
828
|
+
}
|
829
|
+
if (arguments->arguments != NULL) {
|
830
|
+
return arguments->arguments->base.location.end;
|
831
|
+
}
|
832
|
+
return arguments->closing_loc.end;
|
833
|
+
}
|
834
|
+
|
683
835
|
/**
|
684
836
|
* Check that we're not about to attempt to attach a brace block to a call that
|
685
837
|
* has arguments without parentheses.
|
@@ -894,6 +1046,8 @@ pm_alternation_pattern_node_create(pm_parser_t *parser, pm_node_t *left, pm_node
|
|
894
1046
|
*/
|
895
1047
|
static pm_and_node_t *
|
896
1048
|
pm_and_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operator, pm_node_t *right) {
|
1049
|
+
pm_assert_value_expression(parser, left);
|
1050
|
+
|
897
1051
|
pm_and_node_t *node = PM_ALLOC_NODE(parser, pm_and_node_t);
|
898
1052
|
|
899
1053
|
*node = (pm_and_node_t) {
|
@@ -1488,14 +1642,12 @@ pm_call_node_create(pm_parser_t *parser) {
|
|
1488
1642
|
*/
|
1489
1643
|
static pm_call_node_t *
|
1490
1644
|
pm_call_node_aref_create(pm_parser_t *parser, pm_node_t *receiver, pm_arguments_t *arguments) {
|
1645
|
+
pm_assert_value_expression(parser, receiver);
|
1646
|
+
|
1491
1647
|
pm_call_node_t *node = pm_call_node_create(parser);
|
1492
1648
|
|
1493
1649
|
node->base.location.start = receiver->location.start;
|
1494
|
-
|
1495
|
-
node->base.location.end = arguments->block->location.end;
|
1496
|
-
} else {
|
1497
|
-
node->base.location.end = arguments->closing_loc.end;
|
1498
|
-
}
|
1650
|
+
node->base.location.end = pm_arguments_end(arguments);
|
1499
1651
|
|
1500
1652
|
node->receiver = receiver;
|
1501
1653
|
node->message_loc.start = arguments->opening_loc.start;
|
@@ -1515,6 +1667,9 @@ pm_call_node_aref_create(pm_parser_t *parser, pm_node_t *receiver, pm_arguments_
|
|
1515
1667
|
*/
|
1516
1668
|
static pm_call_node_t *
|
1517
1669
|
pm_call_node_binary_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t *operator, pm_node_t *argument) {
|
1670
|
+
pm_assert_value_expression(parser, receiver);
|
1671
|
+
pm_assert_value_expression(parser, argument);
|
1672
|
+
|
1518
1673
|
pm_call_node_t *node = pm_call_node_create(parser);
|
1519
1674
|
|
1520
1675
|
node->base.location.start = MIN(receiver->location.start, argument->location.start);
|
@@ -1536,18 +1691,16 @@ pm_call_node_binary_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t
|
|
1536
1691
|
*/
|
1537
1692
|
static pm_call_node_t *
|
1538
1693
|
pm_call_node_call_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t *operator, pm_token_t *message, pm_arguments_t *arguments) {
|
1694
|
+
pm_assert_value_expression(parser, receiver);
|
1695
|
+
|
1539
1696
|
pm_call_node_t *node = pm_call_node_create(parser);
|
1540
1697
|
|
1541
1698
|
node->base.location.start = receiver->location.start;
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
node->base.location.end = arguments->closing_loc.end;
|
1546
|
-
} else if (arguments->arguments != NULL) {
|
1547
|
-
node->base.location.end = arguments->arguments->base.location.end;
|
1548
|
-
} else {
|
1549
|
-
node->base.location.end = message->end;
|
1699
|
+
const uint8_t *end = pm_arguments_end(arguments);
|
1700
|
+
if (end == NULL) {
|
1701
|
+
end = message->end;
|
1550
1702
|
}
|
1703
|
+
node->base.location.end = end;
|
1551
1704
|
|
1552
1705
|
node->receiver = receiver;
|
1553
1706
|
node->call_operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(operator);
|
@@ -1574,15 +1727,7 @@ pm_call_node_fcall_create(pm_parser_t *parser, pm_token_t *message, pm_arguments
|
|
1574
1727
|
pm_call_node_t *node = pm_call_node_create(parser);
|
1575
1728
|
|
1576
1729
|
node->base.location.start = message->start;
|
1577
|
-
|
1578
|
-
node->base.location.end = arguments->block->location.end;
|
1579
|
-
} else if (arguments->closing_loc.start != NULL) {
|
1580
|
-
node->base.location.end = arguments->closing_loc.end;
|
1581
|
-
} else if (arguments->arguments != NULL) {
|
1582
|
-
node->base.location.end = arguments->arguments->base.location.end;
|
1583
|
-
} else {
|
1584
|
-
node->base.location.end = arguments->closing_loc.end;
|
1585
|
-
}
|
1730
|
+
node->base.location.end = pm_arguments_end(arguments);
|
1586
1731
|
|
1587
1732
|
node->message_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(message);
|
1588
1733
|
node->opening_loc = arguments->opening_loc;
|
@@ -1599,6 +1744,8 @@ pm_call_node_fcall_create(pm_parser_t *parser, pm_token_t *message, pm_arguments
|
|
1599
1744
|
*/
|
1600
1745
|
static pm_call_node_t *
|
1601
1746
|
pm_call_node_not_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t *message, pm_arguments_t *arguments) {
|
1747
|
+
pm_assert_value_expression(parser, receiver);
|
1748
|
+
|
1602
1749
|
pm_call_node_t *node = pm_call_node_create(parser);
|
1603
1750
|
|
1604
1751
|
node->base.location.start = message->start;
|
@@ -1623,14 +1770,12 @@ pm_call_node_not_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t *me
|
|
1623
1770
|
*/
|
1624
1771
|
static pm_call_node_t *
|
1625
1772
|
pm_call_node_shorthand_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t *operator, pm_arguments_t *arguments) {
|
1773
|
+
pm_assert_value_expression(parser, receiver);
|
1774
|
+
|
1626
1775
|
pm_call_node_t *node = pm_call_node_create(parser);
|
1627
1776
|
|
1628
1777
|
node->base.location.start = receiver->location.start;
|
1629
|
-
|
1630
|
-
node->base.location.end = arguments->block->location.end;
|
1631
|
-
} else {
|
1632
|
-
node->base.location.end = arguments->closing_loc.end;
|
1633
|
-
}
|
1778
|
+
node->base.location.end = pm_arguments_end(arguments);
|
1634
1779
|
|
1635
1780
|
node->receiver = receiver;
|
1636
1781
|
node->call_operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(operator);
|
@@ -1652,6 +1797,8 @@ pm_call_node_shorthand_create(pm_parser_t *parser, pm_node_t *receiver, pm_token
|
|
1652
1797
|
*/
|
1653
1798
|
static pm_call_node_t *
|
1654
1799
|
pm_call_node_unary_create(pm_parser_t *parser, pm_token_t *operator, pm_node_t *receiver, const char *name) {
|
1800
|
+
pm_assert_value_expression(parser, receiver);
|
1801
|
+
|
1655
1802
|
pm_call_node_t *node = pm_call_node_create(parser);
|
1656
1803
|
|
1657
1804
|
node->base.location.start = operator->start;
|
@@ -1981,7 +2128,7 @@ pm_capture_pattern_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t
|
|
1981
2128
|
* Allocate and initialize a new CaseNode node.
|
1982
2129
|
*/
|
1983
2130
|
static pm_case_node_t *
|
1984
|
-
pm_case_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, pm_node_t *predicate,
|
2131
|
+
pm_case_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, pm_node_t *predicate, const pm_token_t *end_keyword) {
|
1985
2132
|
pm_case_node_t *node = PM_ALLOC_NODE(parser, pm_case_node_t);
|
1986
2133
|
|
1987
2134
|
*node = (pm_case_node_t) {
|
@@ -1993,7 +2140,7 @@ pm_case_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, pm_node
|
|
1993
2140
|
},
|
1994
2141
|
},
|
1995
2142
|
.predicate = predicate,
|
1996
|
-
.consequent =
|
2143
|
+
.consequent = NULL,
|
1997
2144
|
.case_keyword_loc = PM_LOCATION_TOKEN_VALUE(case_keyword),
|
1998
2145
|
.end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword),
|
1999
2146
|
.conditions = { 0 }
|
@@ -2007,7 +2154,7 @@ pm_case_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, pm_node
|
|
2007
2154
|
*/
|
2008
2155
|
static void
|
2009
2156
|
pm_case_node_condition_append(pm_case_node_t *node, pm_node_t *condition) {
|
2010
|
-
assert(PM_NODE_TYPE_P(condition, PM_WHEN_NODE)
|
2157
|
+
assert(PM_NODE_TYPE_P(condition, PM_WHEN_NODE));
|
2011
2158
|
|
2012
2159
|
pm_node_list_append(&node->conditions, condition);
|
2013
2160
|
node->base.location.end = condition->location.end;
|
@@ -2031,6 +2178,60 @@ pm_case_node_end_keyword_loc_set(pm_case_node_t *node, const pm_token_t *end_key
|
|
2031
2178
|
node->end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword);
|
2032
2179
|
}
|
2033
2180
|
|
2181
|
+
/**
|
2182
|
+
* Allocate and initialize a new CaseMatchNode node.
|
2183
|
+
*/
|
2184
|
+
static pm_case_match_node_t *
|
2185
|
+
pm_case_match_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, pm_node_t *predicate, const pm_token_t *end_keyword) {
|
2186
|
+
pm_case_match_node_t *node = PM_ALLOC_NODE(parser, pm_case_match_node_t);
|
2187
|
+
|
2188
|
+
*node = (pm_case_match_node_t) {
|
2189
|
+
{
|
2190
|
+
.type = PM_CASE_MATCH_NODE,
|
2191
|
+
.location = {
|
2192
|
+
.start = case_keyword->start,
|
2193
|
+
.end = end_keyword->end
|
2194
|
+
},
|
2195
|
+
},
|
2196
|
+
.predicate = predicate,
|
2197
|
+
.consequent = NULL,
|
2198
|
+
.case_keyword_loc = PM_LOCATION_TOKEN_VALUE(case_keyword),
|
2199
|
+
.end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword),
|
2200
|
+
.conditions = { 0 }
|
2201
|
+
};
|
2202
|
+
|
2203
|
+
return node;
|
2204
|
+
}
|
2205
|
+
|
2206
|
+
/**
|
2207
|
+
* Append a new condition to a CaseMatchNode node.
|
2208
|
+
*/
|
2209
|
+
static void
|
2210
|
+
pm_case_match_node_condition_append(pm_case_match_node_t *node, pm_node_t *condition) {
|
2211
|
+
assert(PM_NODE_TYPE_P(condition, PM_IN_NODE));
|
2212
|
+
|
2213
|
+
pm_node_list_append(&node->conditions, condition);
|
2214
|
+
node->base.location.end = condition->location.end;
|
2215
|
+
}
|
2216
|
+
|
2217
|
+
/**
|
2218
|
+
* Set the consequent of a CaseMatchNode node.
|
2219
|
+
*/
|
2220
|
+
static void
|
2221
|
+
pm_case_match_node_consequent_set(pm_case_match_node_t *node, pm_else_node_t *consequent) {
|
2222
|
+
node->consequent = consequent;
|
2223
|
+
node->base.location.end = consequent->base.location.end;
|
2224
|
+
}
|
2225
|
+
|
2226
|
+
/**
|
2227
|
+
* Set the end location for a CaseMatchNode node.
|
2228
|
+
*/
|
2229
|
+
static void
|
2230
|
+
pm_case_match_node_end_keyword_loc_set(pm_case_match_node_t *node, const pm_token_t *end_keyword) {
|
2231
|
+
node->base.location.end = end_keyword->end;
|
2232
|
+
node->end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword);
|
2233
|
+
}
|
2234
|
+
|
2034
2235
|
/**
|
2035
2236
|
* Allocate a new ClassNode node.
|
2036
2237
|
*/
|
@@ -3075,6 +3276,7 @@ static pm_if_node_t *
|
|
3075
3276
|
pm_if_node_create(pm_parser_t *parser,
|
3076
3277
|
const pm_token_t *if_keyword,
|
3077
3278
|
pm_node_t *predicate,
|
3279
|
+
const pm_token_t *then_keyword,
|
3078
3280
|
pm_statements_node_t *statements,
|
3079
3281
|
pm_node_t *consequent,
|
3080
3282
|
const pm_token_t *end_keyword
|
@@ -3104,6 +3306,7 @@ pm_if_node_create(pm_parser_t *parser,
|
|
3104
3306
|
},
|
3105
3307
|
.if_keyword_loc = PM_LOCATION_TOKEN_VALUE(if_keyword),
|
3106
3308
|
.predicate = predicate,
|
3309
|
+
.then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(then_keyword),
|
3107
3310
|
.statements = statements,
|
3108
3311
|
.consequent = consequent,
|
3109
3312
|
.end_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(end_keyword)
|
@@ -3134,6 +3337,7 @@ pm_if_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_t
|
|
3134
3337
|
},
|
3135
3338
|
.if_keyword_loc = PM_LOCATION_TOKEN_VALUE(if_keyword),
|
3136
3339
|
.predicate = predicate,
|
3340
|
+
.then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
|
3137
3341
|
.statements = statements,
|
3138
3342
|
.consequent = NULL,
|
3139
3343
|
.end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
|
@@ -3146,7 +3350,8 @@ pm_if_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_t
|
|
3146
3350
|
* Allocate and initialize an if node from a ternary expression.
|
3147
3351
|
*/
|
3148
3352
|
static pm_if_node_t *
|
3149
|
-
pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, pm_node_t *true_expression, const pm_token_t *colon, pm_node_t *false_expression) {
|
3353
|
+
pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, const pm_token_t *qmark, pm_node_t *true_expression, const pm_token_t *colon, pm_node_t *false_expression) {
|
3354
|
+
pm_assert_value_expression(parser, predicate);
|
3150
3355
|
pm_conditional_predicate(predicate);
|
3151
3356
|
|
3152
3357
|
pm_statements_node_t *if_statements = pm_statements_node_create(parser);
|
@@ -3171,6 +3376,7 @@ pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, pm_node_t *
|
|
3171
3376
|
},
|
3172
3377
|
.if_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
|
3173
3378
|
.predicate = predicate,
|
3379
|
+
.then_keyword_loc = PM_LOCATION_TOKEN_VALUE(qmark),
|
3174
3380
|
.statements = if_statements,
|
3175
3381
|
.consequent = (pm_node_t *)else_node,
|
3176
3382
|
.end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
|
@@ -3871,39 +4077,68 @@ pm_local_variable_write_node_create(pm_parser_t *parser, pm_constant_id_t name,
|
|
3871
4077
|
return node;
|
3872
4078
|
}
|
3873
4079
|
|
4080
|
+
/**
|
4081
|
+
* Returns true if the given bounds comprise a numbered parameter (i.e., they
|
4082
|
+
* are of the form /^_\d$/).
|
4083
|
+
*/
|
3874
4084
|
static inline bool
|
3875
|
-
|
4085
|
+
pm_token_is_numbered_parameter(const uint8_t *start, const uint8_t *end) {
|
3876
4086
|
return (end - start == 2) && (start[0] == '_') && (start[1] != '0') && (pm_char_is_decimal_digit(start[1]));
|
3877
4087
|
}
|
3878
4088
|
|
3879
4089
|
/**
|
3880
|
-
*
|
4090
|
+
* Ensure the given bounds do not comprise a numbered parameter. If they do, add
|
4091
|
+
* an appropriate error message to the parser.
|
4092
|
+
*/
|
4093
|
+
static inline void
|
4094
|
+
pm_refute_numbered_parameter(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) {
|
4095
|
+
if (pm_token_is_numbered_parameter(start, end)) {
|
4096
|
+
PM_PARSER_ERR_FORMAT(parser, start, end, PM_ERR_PARAMETER_NUMBERED_RESERVED, start);
|
4097
|
+
}
|
4098
|
+
}
|
4099
|
+
|
4100
|
+
/**
|
4101
|
+
* Allocate and initialize a new LocalVariableTargetNode node with the given
|
4102
|
+
* name and depth.
|
3881
4103
|
*/
|
3882
4104
|
static pm_local_variable_target_node_t *
|
3883
|
-
|
4105
|
+
pm_local_variable_target_node_create_values(pm_parser_t *parser, const pm_location_t *location, pm_constant_id_t name, uint32_t depth) {
|
3884
4106
|
pm_local_variable_target_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_target_node_t);
|
3885
4107
|
|
3886
|
-
if (token_is_numbered_parameter(name->start, name->end)) {
|
3887
|
-
pm_parser_err_token(parser, name, PM_ERR_PARAMETER_NUMBERED_RESERVED);
|
3888
|
-
}
|
3889
|
-
|
3890
4108
|
*node = (pm_local_variable_target_node_t) {
|
3891
4109
|
{
|
3892
4110
|
.type = PM_LOCAL_VARIABLE_TARGET_NODE,
|
3893
|
-
.location =
|
4111
|
+
.location = *location
|
3894
4112
|
},
|
3895
|
-
.name =
|
3896
|
-
.depth =
|
4113
|
+
.name = name,
|
4114
|
+
.depth = depth
|
3897
4115
|
};
|
3898
4116
|
|
3899
4117
|
return node;
|
3900
4118
|
}
|
3901
4119
|
|
4120
|
+
/**
|
4121
|
+
* Allocate and initialize a new LocalVariableTargetNode node.
|
4122
|
+
*/
|
4123
|
+
static pm_local_variable_target_node_t *
|
4124
|
+
pm_local_variable_target_node_create(pm_parser_t *parser, const pm_token_t *name) {
|
4125
|
+
pm_refute_numbered_parameter(parser, name->start, name->end);
|
4126
|
+
|
4127
|
+
return pm_local_variable_target_node_create_values(
|
4128
|
+
parser,
|
4129
|
+
&(pm_location_t) { .start = name->start, .end = name->end },
|
4130
|
+
pm_parser_constant_id_token(parser, name),
|
4131
|
+
0
|
4132
|
+
);
|
4133
|
+
}
|
4134
|
+
|
3902
4135
|
/**
|
3903
4136
|
* Allocate and initialize a new MatchPredicateNode node.
|
3904
4137
|
*/
|
3905
4138
|
static pm_match_predicate_node_t *
|
3906
4139
|
pm_match_predicate_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t *pattern, const pm_token_t *operator) {
|
4140
|
+
pm_assert_value_expression(parser, value);
|
4141
|
+
|
3907
4142
|
pm_match_predicate_node_t *node = PM_ALLOC_NODE(parser, pm_match_predicate_node_t);
|
3908
4143
|
|
3909
4144
|
*node = (pm_match_predicate_node_t) {
|
@@ -3927,6 +4162,8 @@ pm_match_predicate_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t
|
|
3927
4162
|
*/
|
3928
4163
|
static pm_match_required_node_t *
|
3929
4164
|
pm_match_required_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t *pattern, const pm_token_t *operator) {
|
4165
|
+
pm_assert_value_expression(parser, value);
|
4166
|
+
|
3930
4167
|
pm_match_required_node_t *node = PM_ALLOC_NODE(parser, pm_match_required_node_t);
|
3931
4168
|
|
3932
4169
|
*node = (pm_match_required_node_t) {
|
@@ -3957,10 +4194,10 @@ pm_match_write_node_create(pm_parser_t *parser, pm_call_node_t *call) {
|
|
3957
4194
|
.type = PM_MATCH_WRITE_NODE,
|
3958
4195
|
.location = call->base.location
|
3959
4196
|
},
|
3960
|
-
.call = call
|
4197
|
+
.call = call,
|
4198
|
+
.targets = { 0 }
|
3961
4199
|
};
|
3962
4200
|
|
3963
|
-
pm_constant_id_list_init(&node->locals);
|
3964
4201
|
return node;
|
3965
4202
|
}
|
3966
4203
|
|
@@ -4200,6 +4437,8 @@ pm_optional_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, c
|
|
4200
4437
|
*/
|
4201
4438
|
static pm_or_node_t *
|
4202
4439
|
pm_or_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operator, pm_node_t *right) {
|
4440
|
+
pm_assert_value_expression(parser, left);
|
4441
|
+
|
4203
4442
|
pm_or_node_t *node = PM_ALLOC_NODE(parser, pm_or_node_t);
|
4204
4443
|
|
4205
4444
|
*node = (pm_or_node_t) {
|
@@ -4470,6 +4709,9 @@ pm_pre_execution_node_create(pm_parser_t *parser, const pm_token_t *keyword, con
|
|
4470
4709
|
*/
|
4471
4710
|
static pm_range_node_t *
|
4472
4711
|
pm_range_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operator, pm_node_t *right) {
|
4712
|
+
pm_assert_value_expression(parser, left);
|
4713
|
+
pm_assert_value_expression(parser, right);
|
4714
|
+
|
4473
4715
|
pm_range_node_t *node = PM_ALLOC_NODE(parser, pm_range_node_t);
|
4474
4716
|
pm_node_flags_t flags = 0;
|
4475
4717
|
|
@@ -4885,28 +5127,6 @@ pm_statements_node_body_append(pm_statements_node_t *node, pm_node_t *statement)
|
|
4885
5127
|
statement->flags |= PM_NODE_FLAG_NEWLINE;
|
4886
5128
|
}
|
4887
5129
|
|
4888
|
-
/**
|
4889
|
-
* Allocate a new StringConcatNode node.
|
4890
|
-
*/
|
4891
|
-
static pm_string_concat_node_t *
|
4892
|
-
pm_string_concat_node_create(pm_parser_t *parser, pm_node_t *left, pm_node_t *right) {
|
4893
|
-
pm_string_concat_node_t *node = PM_ALLOC_NODE(parser, pm_string_concat_node_t);
|
4894
|
-
|
4895
|
-
*node = (pm_string_concat_node_t) {
|
4896
|
-
{
|
4897
|
-
.type = PM_STRING_CONCAT_NODE,
|
4898
|
-
.location = {
|
4899
|
-
.start = left->location.start,
|
4900
|
-
.end = right->location.end
|
4901
|
-
}
|
4902
|
-
},
|
4903
|
-
.left = left,
|
4904
|
-
.right = right
|
4905
|
-
};
|
4906
|
-
|
4907
|
-
return node;
|
4908
|
-
}
|
4909
|
-
|
4910
5130
|
/**
|
4911
5131
|
* Allocate a new StringNode node with the current string on the parser.
|
4912
5132
|
*/
|
@@ -4964,16 +5184,9 @@ pm_super_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argument
|
|
4964
5184
|
assert(keyword->type == PM_TOKEN_KEYWORD_SUPER);
|
4965
5185
|
pm_super_node_t *node = PM_ALLOC_NODE(parser, pm_super_node_t);
|
4966
5186
|
|
4967
|
-
const uint8_t *end;
|
4968
|
-
if (
|
4969
|
-
end = arguments->block->location.end;
|
4970
|
-
} else if (arguments->closing_loc.start != NULL) {
|
4971
|
-
end = arguments->closing_loc.end;
|
4972
|
-
} else if (arguments->arguments != NULL) {
|
4973
|
-
end = arguments->arguments->base.location.end;
|
4974
|
-
} else {
|
5187
|
+
const uint8_t *end = pm_arguments_end(arguments);
|
5188
|
+
if (end == NULL) {
|
4975
5189
|
assert(false && "unreachable");
|
4976
|
-
end = NULL;
|
4977
5190
|
}
|
4978
5191
|
|
4979
5192
|
*node = (pm_super_node_t) {
|
@@ -5207,7 +5420,7 @@ pm_undef_node_append(pm_undef_node_t *node, pm_node_t *name) {
|
|
5207
5420
|
* Allocate a new UnlessNode node.
|
5208
5421
|
*/
|
5209
5422
|
static pm_unless_node_t *
|
5210
|
-
pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, pm_statements_node_t *statements) {
|
5423
|
+
pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, const pm_token_t *then_keyword, pm_statements_node_t *statements) {
|
5211
5424
|
pm_conditional_predicate(predicate);
|
5212
5425
|
pm_unless_node_t *node = PM_ALLOC_NODE(parser, pm_unless_node_t);
|
5213
5426
|
|
@@ -5229,6 +5442,7 @@ pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t
|
|
5229
5442
|
},
|
5230
5443
|
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
|
5231
5444
|
.predicate = predicate,
|
5445
|
+
.then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(then_keyword),
|
5232
5446
|
.statements = statements,
|
5233
5447
|
.consequent = NULL,
|
5234
5448
|
.end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
|
@@ -5259,6 +5473,7 @@ pm_unless_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const
|
|
5259
5473
|
},
|
5260
5474
|
.keyword_loc = PM_LOCATION_TOKEN_VALUE(unless_keyword),
|
5261
5475
|
.predicate = predicate,
|
5476
|
+
.then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
|
5262
5477
|
.statements = statements,
|
5263
5478
|
.consequent = NULL,
|
5264
5479
|
.end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
|
@@ -5535,17 +5750,16 @@ pm_parser_scope_push_transparent(pm_parser_t *parser) {
|
|
5535
5750
|
}
|
5536
5751
|
|
5537
5752
|
/**
|
5538
|
-
* Check if the
|
5753
|
+
* Check if any of the currently visible scopes contain a local variable
|
5754
|
+
* described by the given constant id.
|
5539
5755
|
*/
|
5540
5756
|
static int
|
5541
|
-
|
5542
|
-
pm_constant_id_t constant_id = pm_parser_constant_id_token(parser, token);
|
5757
|
+
pm_parser_local_depth_constant_id(pm_parser_t *parser, pm_constant_id_t constant_id) {
|
5543
5758
|
pm_scope_t *scope = parser->current_scope;
|
5544
5759
|
int depth = 0;
|
5545
5760
|
|
5546
5761
|
while (scope != NULL) {
|
5547
|
-
if (!scope->transparent &&
|
5548
|
-
pm_constant_id_list_includes(&scope->locals, constant_id)) return depth;
|
5762
|
+
if (!scope->transparent && pm_constant_id_list_includes(&scope->locals, constant_id)) return depth;
|
5549
5763
|
if (scope->closed) break;
|
5550
5764
|
|
5551
5765
|
scope = scope->previous;
|
@@ -5555,6 +5769,16 @@ pm_parser_local_depth(pm_parser_t *parser, pm_token_t *token) {
|
|
5555
5769
|
return -1;
|
5556
5770
|
}
|
5557
5771
|
|
5772
|
+
/**
|
5773
|
+
* Check if any of the currently visible scopes contain a local variable
|
5774
|
+
* described by the given token. This function implicitly inserts a constant
|
5775
|
+
* into the constant pool.
|
5776
|
+
*/
|
5777
|
+
static inline int
|
5778
|
+
pm_parser_local_depth(pm_parser_t *parser, pm_token_t *token) {
|
5779
|
+
return pm_parser_local_depth_constant_id(parser, pm_parser_constant_id_token(parser, token));
|
5780
|
+
}
|
5781
|
+
|
5558
5782
|
/**
|
5559
5783
|
* Add a constant id to the local table of the current scope.
|
5560
5784
|
*/
|
@@ -5569,15 +5793,6 @@ pm_parser_local_add(pm_parser_t *parser, pm_constant_id_t constant_id) {
|
|
5569
5793
|
}
|
5570
5794
|
}
|
5571
5795
|
|
5572
|
-
/**
|
5573
|
-
* Add a local variable from a constant string to the current scope.
|
5574
|
-
*/
|
5575
|
-
static inline void
|
5576
|
-
pm_parser_local_add_constant(pm_parser_t *parser, const char *start, size_t length) {
|
5577
|
-
pm_constant_id_t constant_id = pm_parser_constant_id_constant(parser, start, length);
|
5578
|
-
if (constant_id != 0) pm_parser_local_add(parser, constant_id);
|
5579
|
-
}
|
5580
|
-
|
5581
5796
|
/**
|
5582
5797
|
* Add a local variable from a location to the current scope.
|
5583
5798
|
*/
|
@@ -5614,12 +5829,10 @@ static void
|
|
5614
5829
|
pm_parser_parameter_name_check(pm_parser_t *parser, const pm_token_t *name) {
|
5615
5830
|
// We want to check whether the parameter name is a numbered parameter or
|
5616
5831
|
// not.
|
5617
|
-
|
5618
|
-
pm_parser_err_token(parser, name, PM_ERR_PARAMETER_NUMBERED_RESERVED);
|
5619
|
-
}
|
5832
|
+
pm_refute_numbered_parameter(parser, name->start, name->end);
|
5620
5833
|
|
5621
5834
|
// We want to ignore any parameter name that starts with an underscore.
|
5622
|
-
if ((*name->start == '_')) return;
|
5835
|
+
if ((name->start < name->end) && (*name->start == '_')) return;
|
5623
5836
|
|
5624
5837
|
// Otherwise we'll fetch the constant id for the parameter name and check
|
5625
5838
|
// whether it's already in the current scope.
|
@@ -5655,7 +5868,16 @@ pm_parser_scope_pop(pm_parser_t *parser) {
|
|
5655
5868
|
static inline size_t
|
5656
5869
|
char_is_identifier_start(pm_parser_t *parser, const uint8_t *b) {
|
5657
5870
|
if (parser->encoding_changed) {
|
5658
|
-
|
5871
|
+
size_t width;
|
5872
|
+
if ((width = parser->encoding.alpha_char(b, parser->end - b)) != 0) {
|
5873
|
+
return width;
|
5874
|
+
} else if (*b == '_') {
|
5875
|
+
return 1;
|
5876
|
+
} else if (*b >= 0x80) {
|
5877
|
+
return parser->encoding.char_width(b, parser->end - b);
|
5878
|
+
} else {
|
5879
|
+
return 0;
|
5880
|
+
}
|
5659
5881
|
} else if (*b < 0x80) {
|
5660
5882
|
return (pm_encoding_unicode_table[*b] & PRISM_ENCODING_ALPHABETIC_BIT ? 1 : 0) || (*b == '_');
|
5661
5883
|
} else {
|
@@ -5671,7 +5893,16 @@ char_is_identifier_start(pm_parser_t *parser, const uint8_t *b) {
|
|
5671
5893
|
static inline size_t
|
5672
5894
|
char_is_identifier(pm_parser_t *parser, const uint8_t *b) {
|
5673
5895
|
if (parser->encoding_changed) {
|
5674
|
-
|
5896
|
+
size_t width;
|
5897
|
+
if ((width = parser->encoding.alnum_char(b, parser->end - b)) != 0) {
|
5898
|
+
return width;
|
5899
|
+
} else if (*b == '_') {
|
5900
|
+
return 1;
|
5901
|
+
} else if (*b >= 0x80) {
|
5902
|
+
return parser->encoding.char_width(b, parser->end - b);
|
5903
|
+
} else {
|
5904
|
+
return 0;
|
5905
|
+
}
|
5675
5906
|
} else if (*b < 0x80) {
|
5676
5907
|
return (pm_encoding_unicode_table[*b] & PRISM_ENCODING_ALPHANUMERIC_BIT ? 1 : 0) || (*b == '_');
|
5677
5908
|
} else {
|
@@ -5866,10 +6097,18 @@ parser_lex_magic_comment_encoding_value(pm_parser_t *parser, const uint8_t *star
|
|
5866
6097
|
}
|
5867
6098
|
|
5868
6099
|
// Next, we're going to check for UTF-8. This is the most common encoding.
|
5869
|
-
//
|
5870
|
-
//
|
5871
|
-
// treat any encoding starting utf-8 as utf-8.
|
6100
|
+
// utf-8 can contain extra information at the end about the platform it is
|
6101
|
+
// encoded on, such as utf-8-mac or utf-8-unix. We'll ignore those suffixes.
|
5872
6102
|
if ((start + 5 <= end) && (pm_strncasecmp(start, (const uint8_t *) "utf-8", 5) == 0)) {
|
6103
|
+
// We need to explicitly handle utf-8-hfs, as that one needs to switch
|
6104
|
+
// over to being utf8-mac.
|
6105
|
+
if (width == 9 && (pm_strncasecmp(start + 5, (const uint8_t *) "-hfs", 4) == 0)) {
|
6106
|
+
parser->encoding = pm_encoding_utf8_mac;
|
6107
|
+
parser->encoding_changed = true;
|
6108
|
+
if (parser->encoding_changed_callback != NULL) parser->encoding_changed_callback(parser);
|
6109
|
+
return true;
|
6110
|
+
}
|
6111
|
+
|
5873
6112
|
// We don't need to do anything here because the default encoding is
|
5874
6113
|
// already UTF-8. We'll just return.
|
5875
6114
|
return true;
|
@@ -5877,51 +6116,160 @@ parser_lex_magic_comment_encoding_value(pm_parser_t *parser, const uint8_t *star
|
|
5877
6116
|
|
5878
6117
|
// Next, we're going to loop through each of the encodings that we handle
|
5879
6118
|
// explicitly. If we found one that we understand, we'll use that value.
|
5880
|
-
#define
|
6119
|
+
#define ENCODING1(value, prebuilt) \
|
5881
6120
|
if (width == sizeof(value) - 1 && start + width <= end && pm_strncasecmp(start, (const uint8_t *) value, width) == 0) { \
|
5882
6121
|
parser->encoding = prebuilt; \
|
5883
|
-
parser->encoding_changed
|
6122
|
+
parser->encoding_changed = true; \
|
5884
6123
|
if (parser->encoding_changed_callback != NULL) parser->encoding_changed_callback(parser); \
|
5885
6124
|
return true; \
|
5886
6125
|
}
|
5887
6126
|
|
5888
|
-
//
|
5889
|
-
|
5890
|
-
|
5891
|
-
|
5892
|
-
|
5893
|
-
|
5894
|
-
|
5895
|
-
|
5896
|
-
|
5897
|
-
|
5898
|
-
|
5899
|
-
|
5900
|
-
|
5901
|
-
|
5902
|
-
|
5903
|
-
|
5904
|
-
|
5905
|
-
|
5906
|
-
|
5907
|
-
|
5908
|
-
|
5909
|
-
|
5910
|
-
|
5911
|
-
|
5912
|
-
|
5913
|
-
|
5914
|
-
|
5915
|
-
|
5916
|
-
|
5917
|
-
|
5918
|
-
|
5919
|
-
|
5920
|
-
|
5921
|
-
|
5922
|
-
|
5923
|
-
|
5924
|
-
|
6127
|
+
// A convenience macros for comparing two aliases for the same encoding.
|
6128
|
+
#define ENCODING2(value1, value2, prebuilt) ENCODING1(value1, prebuilt) ENCODING1(value2, prebuilt)
|
6129
|
+
|
6130
|
+
if (width >= 3) {
|
6131
|
+
switch (*start) {
|
6132
|
+
case 'A': case 'a':
|
6133
|
+
ENCODING1("ASCII", pm_encoding_ascii);
|
6134
|
+
ENCODING1("ASCII-8BIT", pm_encoding_ascii_8bit);
|
6135
|
+
ENCODING1("ANSI_X3.4-1968", pm_encoding_ascii);
|
6136
|
+
break;
|
6137
|
+
case 'B': case 'b':
|
6138
|
+
ENCODING1("BINARY", pm_encoding_ascii_8bit);
|
6139
|
+
ENCODING1("Big5", pm_encoding_big5);
|
6140
|
+
ENCODING1("Big5-HKSCS", pm_encoding_big5_hkscs);
|
6141
|
+
ENCODING1("Big5-UAO", pm_encoding_big5_uao);
|
6142
|
+
break;
|
6143
|
+
case 'C': case 'c':
|
6144
|
+
ENCODING1("CP437", pm_encoding_ibm437);
|
6145
|
+
ENCODING1("CP720", pm_encoding_ibm720);
|
6146
|
+
ENCODING1("CP737", pm_encoding_ibm737);
|
6147
|
+
ENCODING1("CP775", pm_encoding_ibm775);
|
6148
|
+
ENCODING1("CP850", pm_encoding_cp850);
|
6149
|
+
ENCODING1("CP852", pm_encoding_cp852);
|
6150
|
+
ENCODING1("CP855", pm_encoding_cp855);
|
6151
|
+
ENCODING1("CP857", pm_encoding_ibm857);
|
6152
|
+
ENCODING1("CP860", pm_encoding_ibm860);
|
6153
|
+
ENCODING1("CP861", pm_encoding_ibm861);
|
6154
|
+
ENCODING1("CP862", pm_encoding_ibm862);
|
6155
|
+
ENCODING1("CP864", pm_encoding_ibm864);
|
6156
|
+
ENCODING1("CP865", pm_encoding_ibm865);
|
6157
|
+
ENCODING1("CP866", pm_encoding_ibm866);
|
6158
|
+
ENCODING1("CP869", pm_encoding_ibm869);
|
6159
|
+
ENCODING1("CP874", pm_encoding_windows_874);
|
6160
|
+
ENCODING1("CP878", pm_encoding_koi8_r);
|
6161
|
+
ENCODING1("CP863", pm_encoding_ibm863);
|
6162
|
+
ENCODING2("CP932", "csWindows31J", pm_encoding_windows_31j);
|
6163
|
+
ENCODING1("CP936", pm_encoding_gbk);
|
6164
|
+
ENCODING1("CP1250", pm_encoding_windows_1250);
|
6165
|
+
ENCODING1("CP1251", pm_encoding_windows_1251);
|
6166
|
+
ENCODING1("CP1252", pm_encoding_windows_1252);
|
6167
|
+
ENCODING1("CP1253", pm_encoding_windows_1253);
|
6168
|
+
ENCODING1("CP1254", pm_encoding_windows_1254);
|
6169
|
+
ENCODING1("CP1255", pm_encoding_windows_1255);
|
6170
|
+
ENCODING1("CP1256", pm_encoding_windows_1256);
|
6171
|
+
ENCODING1("CP1257", pm_encoding_windows_1257);
|
6172
|
+
ENCODING1("CP1258", pm_encoding_windows_1258);
|
6173
|
+
ENCODING1("CP51932", pm_encoding_cp51932);
|
6174
|
+
ENCODING1("CP65001", pm_encoding_utf_8);
|
6175
|
+
break;
|
6176
|
+
case 'E': case 'e':
|
6177
|
+
ENCODING2("EUC-JP", "eucJP", pm_encoding_euc_jp);
|
6178
|
+
ENCODING1("external", pm_encoding_utf_8);
|
6179
|
+
break;
|
6180
|
+
case 'F': case 'f':
|
6181
|
+
ENCODING1("filesystem", pm_encoding_utf_8);
|
6182
|
+
break;
|
6183
|
+
case 'G': case 'g':
|
6184
|
+
ENCODING1("GB1988", pm_encoding_gb1988);
|
6185
|
+
ENCODING1("GBK", pm_encoding_gbk);
|
6186
|
+
break;
|
6187
|
+
case 'I': case 'i':
|
6188
|
+
ENCODING1("IBM437", pm_encoding_ibm437);
|
6189
|
+
ENCODING1("IBM720", pm_encoding_ibm720);
|
6190
|
+
ENCODING1("IBM737", pm_encoding_ibm737);
|
6191
|
+
ENCODING1("IBM775", pm_encoding_ibm775);
|
6192
|
+
ENCODING1("IBM850", pm_encoding_cp850);
|
6193
|
+
ENCODING1("IBM852", pm_encoding_ibm852);
|
6194
|
+
ENCODING1("IBM855", pm_encoding_ibm855);
|
6195
|
+
ENCODING1("IBM857", pm_encoding_ibm857);
|
6196
|
+
ENCODING1("IBM860", pm_encoding_ibm860);
|
6197
|
+
ENCODING1("IBM861", pm_encoding_ibm861);
|
6198
|
+
ENCODING1("IBM862", pm_encoding_ibm862);
|
6199
|
+
ENCODING1("IBM863", pm_encoding_ibm863);
|
6200
|
+
ENCODING1("IBM864", pm_encoding_ibm864);
|
6201
|
+
ENCODING1("IBM865", pm_encoding_ibm865);
|
6202
|
+
ENCODING1("IBM866", pm_encoding_ibm866);
|
6203
|
+
ENCODING1("IBM869", pm_encoding_ibm869);
|
6204
|
+
ENCODING2("ISO-8859-1", "ISO8859-1", pm_encoding_iso_8859_1);
|
6205
|
+
ENCODING2("ISO-8859-2", "ISO8859-2", pm_encoding_iso_8859_2);
|
6206
|
+
ENCODING2("ISO-8859-3", "ISO8859-3", pm_encoding_iso_8859_3);
|
6207
|
+
ENCODING2("ISO-8859-4", "ISO8859-4", pm_encoding_iso_8859_4);
|
6208
|
+
ENCODING2("ISO-8859-5", "ISO8859-5", pm_encoding_iso_8859_5);
|
6209
|
+
ENCODING2("ISO-8859-6", "ISO8859-6", pm_encoding_iso_8859_6);
|
6210
|
+
ENCODING2("ISO-8859-7", "ISO8859-7", pm_encoding_iso_8859_7);
|
6211
|
+
ENCODING2("ISO-8859-8", "ISO8859-8", pm_encoding_iso_8859_8);
|
6212
|
+
ENCODING2("ISO-8859-9", "ISO8859-9", pm_encoding_iso_8859_9);
|
6213
|
+
ENCODING2("ISO-8859-10", "ISO8859-10", pm_encoding_iso_8859_10);
|
6214
|
+
ENCODING2("ISO-8859-11", "ISO8859-11", pm_encoding_iso_8859_11);
|
6215
|
+
ENCODING2("ISO-8859-13", "ISO8859-13", pm_encoding_iso_8859_13);
|
6216
|
+
ENCODING2("ISO-8859-14", "ISO8859-14", pm_encoding_iso_8859_14);
|
6217
|
+
ENCODING2("ISO-8859-15", "ISO8859-15", pm_encoding_iso_8859_15);
|
6218
|
+
ENCODING2("ISO-8859-16", "ISO8859-16", pm_encoding_iso_8859_16);
|
6219
|
+
break;
|
6220
|
+
case 'K': case 'k':
|
6221
|
+
ENCODING1("KOI8-R", pm_encoding_koi8_r);
|
6222
|
+
break;
|
6223
|
+
case 'L': case 'l':
|
6224
|
+
ENCODING1("locale", pm_encoding_utf_8);
|
6225
|
+
break;
|
6226
|
+
case 'M': case 'm':
|
6227
|
+
ENCODING1("macCentEuro", pm_encoding_mac_cent_euro);
|
6228
|
+
ENCODING1("macCroatian", pm_encoding_mac_croatian);
|
6229
|
+
ENCODING1("macCyrillic", pm_encoding_mac_cyrillic);
|
6230
|
+
ENCODING1("macGreek", pm_encoding_mac_greek);
|
6231
|
+
ENCODING1("macIceland", pm_encoding_mac_iceland);
|
6232
|
+
ENCODING1("macRoman", pm_encoding_mac_roman);
|
6233
|
+
ENCODING1("macRomania", pm_encoding_mac_romania);
|
6234
|
+
ENCODING1("macThai", pm_encoding_mac_thai);
|
6235
|
+
ENCODING1("macTurkish", pm_encoding_mac_turkish);
|
6236
|
+
ENCODING1("macUkraine", pm_encoding_mac_ukraine);
|
6237
|
+
break;
|
6238
|
+
case 'P': case 'p':
|
6239
|
+
ENCODING1("PCK", pm_encoding_windows_31j);
|
6240
|
+
break;
|
6241
|
+
case 'S': case 's':
|
6242
|
+
ENCODING1("Shift_JIS", pm_encoding_shift_jis);
|
6243
|
+
ENCODING1("SJIS", pm_encoding_windows_31j);
|
6244
|
+
break;
|
6245
|
+
case 'T': case 't':
|
6246
|
+
ENCODING1("TIS-620", pm_encoding_tis_620);
|
6247
|
+
break;
|
6248
|
+
case 'U': case 'u':
|
6249
|
+
ENCODING1("US-ASCII", pm_encoding_ascii);
|
6250
|
+
ENCODING2("UTF8-MAC", "UTF-8-HFS", pm_encoding_utf8_mac);
|
6251
|
+
break;
|
6252
|
+
case 'W': case 'w':
|
6253
|
+
ENCODING1("Windows-31J", pm_encoding_windows_31j);
|
6254
|
+
ENCODING1("Windows-874", pm_encoding_windows_874);
|
6255
|
+
ENCODING1("Windows-1250", pm_encoding_windows_1250);
|
6256
|
+
ENCODING1("Windows-1251", pm_encoding_windows_1251);
|
6257
|
+
ENCODING1("Windows-1252", pm_encoding_windows_1252);
|
6258
|
+
ENCODING1("Windows-1253", pm_encoding_windows_1253);
|
6259
|
+
ENCODING1("Windows-1254", pm_encoding_windows_1254);
|
6260
|
+
ENCODING1("Windows-1255", pm_encoding_windows_1255);
|
6261
|
+
ENCODING1("Windows-1256", pm_encoding_windows_1256);
|
6262
|
+
ENCODING1("Windows-1257", pm_encoding_windows_1257);
|
6263
|
+
ENCODING1("Windows-1258", pm_encoding_windows_1258);
|
6264
|
+
break;
|
6265
|
+
case '6':
|
6266
|
+
ENCODING1("646", pm_encoding_ascii);
|
6267
|
+
break;
|
6268
|
+
}
|
6269
|
+
}
|
6270
|
+
|
6271
|
+
#undef ENCODING2
|
6272
|
+
#undef ENCODING1
|
5925
6273
|
|
5926
6274
|
return false;
|
5927
6275
|
}
|
@@ -6026,6 +6374,8 @@ parser_lex_magic_comment_emacs_marker(pm_parser_t *parser, const uint8_t *cursor
|
|
6026
6374
|
*/
|
6027
6375
|
static inline bool
|
6028
6376
|
parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) {
|
6377
|
+
bool result = true;
|
6378
|
+
|
6029
6379
|
const uint8_t *start = parser->current.start + 1;
|
6030
6380
|
const uint8_t *end = parser->current.end;
|
6031
6381
|
if (end - start <= 7) return false;
|
@@ -6123,7 +6473,7 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) {
|
|
6123
6473
|
(key_length == 8 && pm_strncasecmp(key_source, (const uint8_t *) "encoding", 8) == 0) ||
|
6124
6474
|
(key_length == 6 && pm_strncasecmp(key_source, (const uint8_t *) "coding", 6) == 0)
|
6125
6475
|
) {
|
6126
|
-
parser_lex_magic_comment_encoding_value(parser, value_start, value_end);
|
6476
|
+
result = parser_lex_magic_comment_encoding_value(parser, value_start, value_end);
|
6127
6477
|
}
|
6128
6478
|
}
|
6129
6479
|
|
@@ -6150,7 +6500,7 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) {
|
|
6150
6500
|
}
|
6151
6501
|
}
|
6152
6502
|
|
6153
|
-
return
|
6503
|
+
return result;
|
6154
6504
|
}
|
6155
6505
|
|
6156
6506
|
/******************************************************************************/
|
@@ -6324,7 +6674,7 @@ pm_strspn_hexadecimal_number_validate(pm_parser_t *parser, const uint8_t *string
|
|
6324
6674
|
}
|
6325
6675
|
|
6326
6676
|
static pm_token_type_t
|
6327
|
-
lex_optional_float_suffix(pm_parser_t *parser) {
|
6677
|
+
lex_optional_float_suffix(pm_parser_t *parser, bool* seen_e) {
|
6328
6678
|
pm_token_type_t type = PM_TOKEN_INTEGER;
|
6329
6679
|
|
6330
6680
|
// Here we're going to attempt to parse the optional decimal portion of a
|
@@ -6345,8 +6695,9 @@ lex_optional_float_suffix(pm_parser_t *parser) {
|
|
6345
6695
|
// float. If it's not there, it's okay and we'll just continue on.
|
6346
6696
|
if (match(parser, 'e') || match(parser, 'E')) {
|
6347
6697
|
(void) (match(parser, '+') || match(parser, '-'));
|
6698
|
+
*seen_e = true;
|
6348
6699
|
|
6349
|
-
if (pm_char_is_decimal_digit(
|
6700
|
+
if (pm_char_is_decimal_digit(peek(parser))) {
|
6350
6701
|
parser->current.end++;
|
6351
6702
|
parser->current.end += pm_strspn_decimal_number_validate(parser, parser->current.end);
|
6352
6703
|
type = PM_TOKEN_FLOAT;
|
@@ -6360,8 +6711,9 @@ lex_optional_float_suffix(pm_parser_t *parser) {
|
|
6360
6711
|
}
|
6361
6712
|
|
6362
6713
|
static pm_token_type_t
|
6363
|
-
lex_numeric_prefix(pm_parser_t *parser) {
|
6714
|
+
lex_numeric_prefix(pm_parser_t *parser, bool* seen_e) {
|
6364
6715
|
pm_token_type_t type = PM_TOKEN_INTEGER;
|
6716
|
+
*seen_e = false;
|
6365
6717
|
|
6366
6718
|
if (peek_offset(parser, -1) == '0') {
|
6367
6719
|
switch (*parser->current.end) {
|
@@ -6432,14 +6784,14 @@ lex_numeric_prefix(pm_parser_t *parser) {
|
|
6432
6784
|
|
6433
6785
|
// 0.xxx is a float
|
6434
6786
|
case '.': {
|
6435
|
-
type = lex_optional_float_suffix(parser);
|
6787
|
+
type = lex_optional_float_suffix(parser, seen_e);
|
6436
6788
|
break;
|
6437
6789
|
}
|
6438
6790
|
|
6439
6791
|
// 0exxx is a float
|
6440
6792
|
case 'e':
|
6441
6793
|
case 'E': {
|
6442
|
-
type = lex_optional_float_suffix(parser);
|
6794
|
+
type = lex_optional_float_suffix(parser, seen_e);
|
6443
6795
|
break;
|
6444
6796
|
}
|
6445
6797
|
}
|
@@ -6449,7 +6801,7 @@ lex_numeric_prefix(pm_parser_t *parser) {
|
|
6449
6801
|
parser->current.end += pm_strspn_decimal_number_validate(parser, parser->current.end);
|
6450
6802
|
|
6451
6803
|
// Afterward, we'll lex as far as we can into an optional float suffix.
|
6452
|
-
type = lex_optional_float_suffix(parser);
|
6804
|
+
type = lex_optional_float_suffix(parser, seen_e);
|
6453
6805
|
}
|
6454
6806
|
|
6455
6807
|
return type;
|
@@ -6461,7 +6813,8 @@ lex_numeric(pm_parser_t *parser) {
|
|
6461
6813
|
parser->integer_base = PM_INTEGER_BASE_FLAGS_DECIMAL;
|
6462
6814
|
|
6463
6815
|
if (parser->current.end < parser->end) {
|
6464
|
-
|
6816
|
+
bool seen_e = false;
|
6817
|
+
type = lex_numeric_prefix(parser, &seen_e);
|
6465
6818
|
|
6466
6819
|
const uint8_t *end = parser->current.end;
|
6467
6820
|
pm_token_type_t suffix_type = type;
|
@@ -6477,7 +6830,7 @@ lex_numeric(pm_parser_t *parser) {
|
|
6477
6830
|
suffix_type = PM_TOKEN_INTEGER_IMAGINARY;
|
6478
6831
|
}
|
6479
6832
|
} else {
|
6480
|
-
if (match(parser, 'r')) {
|
6833
|
+
if (!seen_e && match(parser, 'r')) {
|
6481
6834
|
suffix_type = PM_TOKEN_FLOAT_RATIONAL;
|
6482
6835
|
|
6483
6836
|
if (match(parser, 'i')) {
|
@@ -6584,17 +6937,21 @@ lex_global_variable(pm_parser_t *parser) {
|
|
6584
6937
|
|
6585
6938
|
/**
|
6586
6939
|
* This function checks if the current token matches a keyword. If it does, it
|
6587
|
-
* returns
|
6940
|
+
* returns the token type. Otherwise, it returns PM_TOKEN_EOF. The arguments are as follows:
|
6588
6941
|
*
|
6942
|
+
* * `parser` - the parser object
|
6943
|
+
* * `current_start` - pointer to the start of the current token
|
6589
6944
|
* * `value` - the literal string that we're checking for
|
6590
|
-
* * `
|
6945
|
+
* * `vlen` - the length of the token
|
6591
6946
|
* * `state` - the state that we should transition to if the token matches
|
6947
|
+
* * `type` - the expected token type
|
6948
|
+
* * `modifier_type` - the expected modifier token type
|
6592
6949
|
*/
|
6593
6950
|
static inline pm_token_type_t
|
6594
|
-
lex_keyword(pm_parser_t *parser, const char *value, size_t vlen, pm_lex_state_t state, pm_token_type_t type, pm_token_type_t modifier_type) {
|
6595
|
-
|
6951
|
+
lex_keyword(pm_parser_t *parser, const uint8_t *current_start, const char *value, size_t vlen, pm_lex_state_t state, pm_token_type_t type, pm_token_type_t modifier_type) {
|
6952
|
+
if (memcmp(current_start, value, vlen) == 0) {
|
6953
|
+
pm_lex_state_t last_state = parser->lex_state;
|
6596
6954
|
|
6597
|
-
if (parser->current.start + vlen <= parser->end && memcmp(parser->current.start, value, vlen) == 0) {
|
6598
6955
|
if (parser->lex_state & PM_LEX_STATE_FNAME) {
|
6599
6956
|
lex_state_set(parser, PM_LEX_STATE_ENDFN);
|
6600
6957
|
} else {
|
@@ -6650,7 +7007,7 @@ lex_identifier(pm_parser_t *parser, bool previous_command_start) {
|
|
6650
7007
|
}
|
6651
7008
|
|
6652
7009
|
if (parser->lex_state != PM_LEX_STATE_DOT) {
|
6653
|
-
if (width == 8 && (lex_keyword(parser, "defined?", width, PM_LEX_STATE_ARG, PM_TOKEN_KEYWORD_DEFINED, PM_TOKEN_EOF) != PM_TOKEN_EOF)) {
|
7010
|
+
if (width == 8 && (lex_keyword(parser, current_start, "defined?", width, PM_LEX_STATE_ARG, PM_TOKEN_KEYWORD_DEFINED, PM_TOKEN_EOF) != PM_TOKEN_EOF)) {
|
6654
7011
|
return PM_TOKEN_KEYWORD_DEFINED;
|
6655
7012
|
}
|
6656
7013
|
}
|
@@ -6678,67 +7035,66 @@ lex_identifier(pm_parser_t *parser, bool previous_command_start) {
|
|
6678
7035
|
|
6679
7036
|
if (parser->lex_state != PM_LEX_STATE_DOT) {
|
6680
7037
|
pm_token_type_t type;
|
6681
|
-
|
6682
7038
|
switch (width) {
|
6683
7039
|
case 2:
|
6684
|
-
if (lex_keyword(parser, "do", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_DO, PM_TOKEN_EOF) != PM_TOKEN_EOF) {
|
7040
|
+
if (lex_keyword(parser, current_start, "do", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_DO, PM_TOKEN_EOF) != PM_TOKEN_EOF) {
|
6685
7041
|
if (pm_do_loop_stack_p(parser)) {
|
6686
7042
|
return PM_TOKEN_KEYWORD_DO_LOOP;
|
6687
7043
|
}
|
6688
7044
|
return PM_TOKEN_KEYWORD_DO;
|
6689
7045
|
}
|
6690
7046
|
|
6691
|
-
if ((type = lex_keyword(parser, "if", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_IF, PM_TOKEN_KEYWORD_IF_MODIFIER)) != PM_TOKEN_EOF) return type;
|
6692
|
-
if ((type = lex_keyword(parser, "in", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_IN, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6693
|
-
if ((type = lex_keyword(parser, "or", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_OR, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7047
|
+
if ((type = lex_keyword(parser, current_start, "if", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_IF, PM_TOKEN_KEYWORD_IF_MODIFIER)) != PM_TOKEN_EOF) return type;
|
7048
|
+
if ((type = lex_keyword(parser, current_start, "in", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_IN, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7049
|
+
if ((type = lex_keyword(parser, current_start, "or", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_OR, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6694
7050
|
break;
|
6695
7051
|
case 3:
|
6696
|
-
if ((type = lex_keyword(parser, "and", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_AND, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6697
|
-
if ((type = lex_keyword(parser, "def", width, PM_LEX_STATE_FNAME, PM_TOKEN_KEYWORD_DEF, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6698
|
-
if ((type = lex_keyword(parser, "end", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_END, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6699
|
-
if ((type = lex_keyword(parser, "END", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_END_UPCASE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6700
|
-
if ((type = lex_keyword(parser, "for", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_FOR, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6701
|
-
if ((type = lex_keyword(parser, "nil", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_NIL, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6702
|
-
if ((type = lex_keyword(parser, "not", width, PM_LEX_STATE_ARG, PM_TOKEN_KEYWORD_NOT, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7052
|
+
if ((type = lex_keyword(parser, current_start, "and", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_AND, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7053
|
+
if ((type = lex_keyword(parser, current_start, "def", width, PM_LEX_STATE_FNAME, PM_TOKEN_KEYWORD_DEF, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7054
|
+
if ((type = lex_keyword(parser, current_start, "end", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_END, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7055
|
+
if ((type = lex_keyword(parser, current_start, "END", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_END_UPCASE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7056
|
+
if ((type = lex_keyword(parser, current_start, "for", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_FOR, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7057
|
+
if ((type = lex_keyword(parser, current_start, "nil", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_NIL, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7058
|
+
if ((type = lex_keyword(parser, current_start, "not", width, PM_LEX_STATE_ARG, PM_TOKEN_KEYWORD_NOT, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6703
7059
|
break;
|
6704
7060
|
case 4:
|
6705
|
-
if ((type = lex_keyword(parser, "case", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_CASE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6706
|
-
if ((type = lex_keyword(parser, "else", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6707
|
-
if ((type = lex_keyword(parser, "next", width, PM_LEX_STATE_MID, PM_TOKEN_KEYWORD_NEXT, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6708
|
-
if ((type = lex_keyword(parser, "redo", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_REDO, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6709
|
-
if ((type = lex_keyword(parser, "self", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_SELF, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6710
|
-
if ((type = lex_keyword(parser, "then", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6711
|
-
if ((type = lex_keyword(parser, "true", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_TRUE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6712
|
-
if ((type = lex_keyword(parser, "when", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_WHEN, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7061
|
+
if ((type = lex_keyword(parser, current_start, "case", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_CASE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7062
|
+
if ((type = lex_keyword(parser, current_start, "else", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7063
|
+
if ((type = lex_keyword(parser, current_start, "next", width, PM_LEX_STATE_MID, PM_TOKEN_KEYWORD_NEXT, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7064
|
+
if ((type = lex_keyword(parser, current_start, "redo", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_REDO, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7065
|
+
if ((type = lex_keyword(parser, current_start, "self", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_SELF, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7066
|
+
if ((type = lex_keyword(parser, current_start, "then", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7067
|
+
if ((type = lex_keyword(parser, current_start, "true", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_TRUE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7068
|
+
if ((type = lex_keyword(parser, current_start, "when", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_WHEN, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6713
7069
|
break;
|
6714
7070
|
case 5:
|
6715
|
-
if ((type = lex_keyword(parser, "alias", width, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM, PM_TOKEN_KEYWORD_ALIAS, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6716
|
-
if ((type = lex_keyword(parser, "begin", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_BEGIN, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6717
|
-
if ((type = lex_keyword(parser, "BEGIN", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_BEGIN_UPCASE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6718
|
-
if ((type = lex_keyword(parser, "break", width, PM_LEX_STATE_MID, PM_TOKEN_KEYWORD_BREAK, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6719
|
-
if ((type = lex_keyword(parser, "class", width, PM_LEX_STATE_CLASS, PM_TOKEN_KEYWORD_CLASS, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6720
|
-
if ((type = lex_keyword(parser, "elsif", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_ELSIF, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6721
|
-
if ((type = lex_keyword(parser, "false", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_FALSE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6722
|
-
if ((type = lex_keyword(parser, "retry", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_RETRY, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6723
|
-
if ((type = lex_keyword(parser, "super", width, PM_LEX_STATE_ARG, PM_TOKEN_KEYWORD_SUPER, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6724
|
-
if ((type = lex_keyword(parser, "undef", width, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM, PM_TOKEN_KEYWORD_UNDEF, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6725
|
-
if ((type = lex_keyword(parser, "until", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_UNTIL, PM_TOKEN_KEYWORD_UNTIL_MODIFIER)) != PM_TOKEN_EOF) return type;
|
6726
|
-
if ((type = lex_keyword(parser, "while", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_WHILE, PM_TOKEN_KEYWORD_WHILE_MODIFIER)) != PM_TOKEN_EOF) return type;
|
6727
|
-
if ((type = lex_keyword(parser, "yield", width, PM_LEX_STATE_ARG, PM_TOKEN_KEYWORD_YIELD, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7071
|
+
if ((type = lex_keyword(parser, current_start, "alias", width, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM, PM_TOKEN_KEYWORD_ALIAS, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7072
|
+
if ((type = lex_keyword(parser, current_start, "begin", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_BEGIN, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7073
|
+
if ((type = lex_keyword(parser, current_start, "BEGIN", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_BEGIN_UPCASE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7074
|
+
if ((type = lex_keyword(parser, current_start, "break", width, PM_LEX_STATE_MID, PM_TOKEN_KEYWORD_BREAK, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7075
|
+
if ((type = lex_keyword(parser, current_start, "class", width, PM_LEX_STATE_CLASS, PM_TOKEN_KEYWORD_CLASS, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7076
|
+
if ((type = lex_keyword(parser, current_start, "elsif", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_ELSIF, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7077
|
+
if ((type = lex_keyword(parser, current_start, "false", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_FALSE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7078
|
+
if ((type = lex_keyword(parser, current_start, "retry", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD_RETRY, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7079
|
+
if ((type = lex_keyword(parser, current_start, "super", width, PM_LEX_STATE_ARG, PM_TOKEN_KEYWORD_SUPER, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7080
|
+
if ((type = lex_keyword(parser, current_start, "undef", width, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM, PM_TOKEN_KEYWORD_UNDEF, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7081
|
+
if ((type = lex_keyword(parser, current_start, "until", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_UNTIL, PM_TOKEN_KEYWORD_UNTIL_MODIFIER)) != PM_TOKEN_EOF) return type;
|
7082
|
+
if ((type = lex_keyword(parser, current_start, "while", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_WHILE, PM_TOKEN_KEYWORD_WHILE_MODIFIER)) != PM_TOKEN_EOF) return type;
|
7083
|
+
if ((type = lex_keyword(parser, current_start, "yield", width, PM_LEX_STATE_ARG, PM_TOKEN_KEYWORD_YIELD, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6728
7084
|
break;
|
6729
7085
|
case 6:
|
6730
|
-
if ((type = lex_keyword(parser, "ensure", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6731
|
-
if ((type = lex_keyword(parser, "module", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_MODULE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6732
|
-
if ((type = lex_keyword(parser, "rescue", width, PM_LEX_STATE_MID, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) != PM_TOKEN_EOF) return type;
|
6733
|
-
if ((type = lex_keyword(parser, "return", width, PM_LEX_STATE_MID, PM_TOKEN_KEYWORD_RETURN, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6734
|
-
if ((type = lex_keyword(parser, "unless", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_UNLESS, PM_TOKEN_KEYWORD_UNLESS_MODIFIER)) != PM_TOKEN_EOF) return type;
|
7086
|
+
if ((type = lex_keyword(parser, current_start, "ensure", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7087
|
+
if ((type = lex_keyword(parser, current_start, "module", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_MODULE, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7088
|
+
if ((type = lex_keyword(parser, current_start, "rescue", width, PM_LEX_STATE_MID, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) != PM_TOKEN_EOF) return type;
|
7089
|
+
if ((type = lex_keyword(parser, current_start, "return", width, PM_LEX_STATE_MID, PM_TOKEN_KEYWORD_RETURN, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7090
|
+
if ((type = lex_keyword(parser, current_start, "unless", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_UNLESS, PM_TOKEN_KEYWORD_UNLESS_MODIFIER)) != PM_TOKEN_EOF) return type;
|
6735
7091
|
break;
|
6736
7092
|
case 8:
|
6737
|
-
if ((type = lex_keyword(parser, "__LINE__", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD___LINE__, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6738
|
-
if ((type = lex_keyword(parser, "__FILE__", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD___FILE__, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7093
|
+
if ((type = lex_keyword(parser, current_start, "__LINE__", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD___LINE__, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7094
|
+
if ((type = lex_keyword(parser, current_start, "__FILE__", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD___FILE__, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6739
7095
|
break;
|
6740
7096
|
case 12:
|
6741
|
-
if ((type = lex_keyword(parser, "__ENCODING__", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD___ENCODING__, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
7097
|
+
if ((type = lex_keyword(parser, current_start, "__ENCODING__", width, PM_LEX_STATE_END, PM_TOKEN_KEYWORD___ENCODING__, PM_TOKEN_EOF)) != PM_TOKEN_EOF) return type;
|
6742
7098
|
break;
|
6743
7099
|
}
|
6744
7100
|
}
|
@@ -8676,6 +9032,8 @@ parser_lex(pm_parser_t *parser) {
|
|
8676
9032
|
|
8677
9033
|
if (parser->current.end < parser->end) {
|
8678
9034
|
lex_mode_push_list(parser, false, *parser->current.end++);
|
9035
|
+
} else {
|
9036
|
+
lex_mode_push_list_eof(parser);
|
8679
9037
|
}
|
8680
9038
|
|
8681
9039
|
LEX(PM_TOKEN_PERCENT_LOWER_I);
|
@@ -8685,6 +9043,8 @@ parser_lex(pm_parser_t *parser) {
|
|
8685
9043
|
|
8686
9044
|
if (parser->current.end < parser->end) {
|
8687
9045
|
lex_mode_push_list(parser, true, *parser->current.end++);
|
9046
|
+
} else {
|
9047
|
+
lex_mode_push_list_eof(parser);
|
8688
9048
|
}
|
8689
9049
|
|
8690
9050
|
LEX(PM_TOKEN_PERCENT_UPPER_I);
|
@@ -8696,6 +9056,8 @@ parser_lex(pm_parser_t *parser) {
|
|
8696
9056
|
lex_mode_push_regexp(parser, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end));
|
8697
9057
|
pm_newline_list_check_append(&parser->newline_list, parser->current.end);
|
8698
9058
|
parser->current.end++;
|
9059
|
+
} else {
|
9060
|
+
lex_mode_push_regexp(parser, '\0', '\0');
|
8699
9061
|
}
|
8700
9062
|
|
8701
9063
|
LEX(PM_TOKEN_REGEXP_BEGIN);
|
@@ -8707,6 +9069,8 @@ parser_lex(pm_parser_t *parser) {
|
|
8707
9069
|
lex_mode_push_string(parser, false, false, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end));
|
8708
9070
|
pm_newline_list_check_append(&parser->newline_list, parser->current.end);
|
8709
9071
|
parser->current.end++;
|
9072
|
+
} else {
|
9073
|
+
lex_mode_push_string_eof(parser);
|
8710
9074
|
}
|
8711
9075
|
|
8712
9076
|
LEX(PM_TOKEN_STRING_BEGIN);
|
@@ -8718,6 +9082,8 @@ parser_lex(pm_parser_t *parser) {
|
|
8718
9082
|
lex_mode_push_string(parser, true, false, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end));
|
8719
9083
|
pm_newline_list_check_append(&parser->newline_list, parser->current.end);
|
8720
9084
|
parser->current.end++;
|
9085
|
+
} else {
|
9086
|
+
lex_mode_push_string_eof(parser);
|
8721
9087
|
}
|
8722
9088
|
|
8723
9089
|
LEX(PM_TOKEN_STRING_BEGIN);
|
@@ -8729,6 +9095,8 @@ parser_lex(pm_parser_t *parser) {
|
|
8729
9095
|
lex_mode_push_string(parser, false, false, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end));
|
8730
9096
|
lex_state_set(parser, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM);
|
8731
9097
|
parser->current.end++;
|
9098
|
+
} else {
|
9099
|
+
lex_mode_push_string_eof(parser);
|
8732
9100
|
}
|
8733
9101
|
|
8734
9102
|
LEX(PM_TOKEN_SYMBOL_BEGIN);
|
@@ -8738,6 +9106,8 @@ parser_lex(pm_parser_t *parser) {
|
|
8738
9106
|
|
8739
9107
|
if (parser->current.end < parser->end) {
|
8740
9108
|
lex_mode_push_list(parser, false, *parser->current.end++);
|
9109
|
+
} else {
|
9110
|
+
lex_mode_push_list_eof(parser);
|
8741
9111
|
}
|
8742
9112
|
|
8743
9113
|
LEX(PM_TOKEN_PERCENT_LOWER_W);
|
@@ -8747,6 +9117,8 @@ parser_lex(pm_parser_t *parser) {
|
|
8747
9117
|
|
8748
9118
|
if (parser->current.end < parser->end) {
|
8749
9119
|
lex_mode_push_list(parser, true, *parser->current.end++);
|
9120
|
+
} else {
|
9121
|
+
lex_mode_push_list_eof(parser);
|
8750
9122
|
}
|
8751
9123
|
|
8752
9124
|
LEX(PM_TOKEN_PERCENT_UPPER_W);
|
@@ -8757,6 +9129,8 @@ parser_lex(pm_parser_t *parser) {
|
|
8757
9129
|
if (parser->current.end < parser->end) {
|
8758
9130
|
lex_mode_push_string(parser, true, false, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end));
|
8759
9131
|
parser->current.end++;
|
9132
|
+
} else {
|
9133
|
+
lex_mode_push_string_eof(parser);
|
8760
9134
|
}
|
8761
9135
|
|
8762
9136
|
LEX(PM_TOKEN_PERCENT_LOWER_X);
|
@@ -8859,7 +9233,7 @@ parser_lex(pm_parser_t *parser) {
|
|
8859
9233
|
!(last_state & (PM_LEX_STATE_DOT | PM_LEX_STATE_FNAME)) &&
|
8860
9234
|
(type == PM_TOKEN_IDENTIFIER) &&
|
8861
9235
|
((pm_parser_local_depth(parser, &parser->current) != -1) ||
|
8862
|
-
|
9236
|
+
pm_token_is_numbered_parameter(parser->current.start, parser->current.end))
|
8863
9237
|
) {
|
8864
9238
|
lex_state_set(parser, PM_LEX_STATE_END | PM_LEX_STATE_LABEL);
|
8865
9239
|
}
|
@@ -9511,6 +9885,7 @@ parser_lex(pm_parser_t *parser) {
|
|
9511
9885
|
parser->heredoc_end = parser->current.end;
|
9512
9886
|
}
|
9513
9887
|
|
9888
|
+
parser->current_string_common_whitespace = parser->lex_modes.current->as.heredoc.common_whitespace;
|
9514
9889
|
lex_mode_pop(parser);
|
9515
9890
|
if (!at_end) {
|
9516
9891
|
lex_state_set(parser, PM_LEX_STATE_END);
|
@@ -9728,11 +10103,11 @@ parser_lex(pm_parser_t *parser) {
|
|
9728
10103
|
typedef enum {
|
9729
10104
|
PM_BINDING_POWER_UNSET = 0, // used to indicate this token cannot be used as an infix operator
|
9730
10105
|
PM_BINDING_POWER_STATEMENT = 2,
|
9731
|
-
PM_BINDING_POWER_MODIFIER = 4, // if unless until while
|
10106
|
+
PM_BINDING_POWER_MODIFIER = 4, // if unless until while
|
9732
10107
|
PM_BINDING_POWER_MODIFIER_RESCUE = 6, // rescue
|
9733
10108
|
PM_BINDING_POWER_COMPOSITION = 8, // and or
|
9734
10109
|
PM_BINDING_POWER_NOT = 10, // not
|
9735
|
-
PM_BINDING_POWER_MATCH = 12, // =>
|
10110
|
+
PM_BINDING_POWER_MATCH = 12, // => in
|
9736
10111
|
PM_BINDING_POWER_DEFINED = 14, // defined?
|
9737
10112
|
PM_BINDING_POWER_ASSIGNMENT = 16, // = += -= *= /= %= &= |= ^= &&= ||= <<= >>= **=
|
9738
10113
|
PM_BINDING_POWER_TERNARY = 18, // ?:
|
@@ -9767,34 +10142,37 @@ typedef struct {
|
|
9767
10142
|
|
9768
10143
|
/** Whether or not this token can be used as a binary operator. */
|
9769
10144
|
bool binary;
|
10145
|
+
|
10146
|
+
/**
|
10147
|
+
* Whether or not this token can be used as non-associative binary operator.
|
10148
|
+
* Non-associative operators (e.g. in and =>) need special treatment in parse_expression.
|
10149
|
+
*/
|
10150
|
+
bool nonassoc;
|
9770
10151
|
} pm_binding_powers_t;
|
9771
10152
|
|
9772
|
-
#define BINDING_POWER_ASSIGNMENT { PM_BINDING_POWER_UNARY, PM_BINDING_POWER_ASSIGNMENT, true }
|
9773
|
-
#define LEFT_ASSOCIATIVE(precedence) { precedence, precedence + 1, true }
|
9774
|
-
#define RIGHT_ASSOCIATIVE(precedence) { precedence, precedence, true }
|
9775
|
-
#define
|
10153
|
+
#define BINDING_POWER_ASSIGNMENT { PM_BINDING_POWER_UNARY, PM_BINDING_POWER_ASSIGNMENT, true, false }
|
10154
|
+
#define LEFT_ASSOCIATIVE(precedence) { precedence, precedence + 1, true, false }
|
10155
|
+
#define RIGHT_ASSOCIATIVE(precedence) { precedence, precedence, true, false }
|
10156
|
+
#define NON_ASSOCIATIVE(precedence) { precedence + 1, precedence + 1, true, true }
|
10157
|
+
#define RIGHT_ASSOCIATIVE_UNARY(precedence) { precedence, precedence, false, false }
|
9776
10158
|
|
9777
10159
|
pm_binding_powers_t pm_binding_powers[PM_TOKEN_MAXIMUM] = {
|
9778
|
-
// if unless until while
|
10160
|
+
// if unless until while
|
9779
10161
|
[PM_TOKEN_KEYWORD_IF_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER),
|
9780
10162
|
[PM_TOKEN_KEYWORD_UNLESS_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER),
|
9781
10163
|
[PM_TOKEN_KEYWORD_UNTIL_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER),
|
9782
10164
|
[PM_TOKEN_KEYWORD_WHILE_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER),
|
9783
|
-
[PM_TOKEN_KEYWORD_IN] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER),
|
9784
10165
|
|
9785
|
-
// rescue
|
9786
|
-
[PM_TOKEN_KEYWORD_RESCUE_MODIFIER] =
|
9787
|
-
PM_BINDING_POWER_ASSIGNMENT,
|
9788
|
-
PM_BINDING_POWER_MODIFIER_RESCUE + 1,
|
9789
|
-
true
|
9790
|
-
},
|
10166
|
+
// rescue
|
10167
|
+
[PM_TOKEN_KEYWORD_RESCUE_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER_RESCUE),
|
9791
10168
|
|
9792
10169
|
// and or
|
9793
10170
|
[PM_TOKEN_KEYWORD_AND] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_COMPOSITION),
|
9794
10171
|
[PM_TOKEN_KEYWORD_OR] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_COMPOSITION),
|
9795
10172
|
|
9796
|
-
// =>
|
9797
|
-
[PM_TOKEN_EQUAL_GREATER] =
|
10173
|
+
// => in
|
10174
|
+
[PM_TOKEN_EQUAL_GREATER] = NON_ASSOCIATIVE(PM_BINDING_POWER_MATCH),
|
10175
|
+
[PM_TOKEN_KEYWORD_IN] = NON_ASSOCIATIVE(PM_BINDING_POWER_MATCH),
|
9798
10176
|
|
9799
10177
|
// &&= &= ^= = >>= <<= -= %= |= += /= *= **=
|
9800
10178
|
[PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL] = BINDING_POWER_ASSIGNMENT,
|
@@ -9816,8 +10194,8 @@ pm_binding_powers_t pm_binding_powers[PM_TOKEN_MAXIMUM] = {
|
|
9816
10194
|
[PM_TOKEN_QUESTION_MARK] = RIGHT_ASSOCIATIVE(PM_BINDING_POWER_TERNARY),
|
9817
10195
|
|
9818
10196
|
// .. ...
|
9819
|
-
[PM_TOKEN_DOT_DOT] =
|
9820
|
-
[PM_TOKEN_DOT_DOT_DOT] =
|
10197
|
+
[PM_TOKEN_DOT_DOT] = NON_ASSOCIATIVE(PM_BINDING_POWER_RANGE),
|
10198
|
+
[PM_TOKEN_DOT_DOT_DOT] = NON_ASSOCIATIVE(PM_BINDING_POWER_RANGE),
|
9821
10199
|
|
9822
10200
|
// ||
|
9823
10201
|
[PM_TOKEN_PIPE_PIPE] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_LOGICAL_OR),
|
@@ -9862,7 +10240,7 @@ pm_binding_powers_t pm_binding_powers[PM_TOKEN_MAXIMUM] = {
|
|
9862
10240
|
|
9863
10241
|
// -@
|
9864
10242
|
[PM_TOKEN_UMINUS] = RIGHT_ASSOCIATIVE_UNARY(PM_BINDING_POWER_UMINUS),
|
9865
|
-
[PM_TOKEN_UMINUS_NUM] = { PM_BINDING_POWER_UMINUS, PM_BINDING_POWER_MAX, false },
|
10243
|
+
[PM_TOKEN_UMINUS_NUM] = { PM_BINDING_POWER_UMINUS, PM_BINDING_POWER_MAX, false, false },
|
9866
10244
|
|
9867
10245
|
// **
|
9868
10246
|
[PM_TOKEN_STAR_STAR] = RIGHT_ASSOCIATIVE(PM_BINDING_POWER_EXPONENT),
|
@@ -10038,6 +10416,16 @@ expect3(pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, pm_to
|
|
10038
10416
|
static pm_node_t *
|
10039
10417
|
parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, pm_diagnostic_id_t diag_id);
|
10040
10418
|
|
10419
|
+
/**
|
10420
|
+
* This is a wrapper of parse_expression, which also checks whether the resulting node is value expression.
|
10421
|
+
*/
|
10422
|
+
static pm_node_t *
|
10423
|
+
parse_value_expression(pm_parser_t *parser, pm_binding_power_t binding_power, pm_diagnostic_id_t diag_id) {
|
10424
|
+
pm_node_t *node = parse_expression(parser, binding_power, diag_id);
|
10425
|
+
pm_assert_value_expression(parser, node);
|
10426
|
+
return node;
|
10427
|
+
}
|
10428
|
+
|
10041
10429
|
/**
|
10042
10430
|
* This function controls whether or not we will attempt to parse an expression
|
10043
10431
|
* beginning at the subsequent token. It is used when we are in a context where
|
@@ -10121,11 +10509,11 @@ static pm_node_t *
|
|
10121
10509
|
parse_starred_expression(pm_parser_t *parser, pm_binding_power_t binding_power, pm_diagnostic_id_t diag_id) {
|
10122
10510
|
if (accept1(parser, PM_TOKEN_USTAR)) {
|
10123
10511
|
pm_token_t operator = parser->previous;
|
10124
|
-
pm_node_t *expression =
|
10512
|
+
pm_node_t *expression = parse_value_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
|
10125
10513
|
return (pm_node_t *) pm_splat_node_create(parser, &operator, expression);
|
10126
10514
|
}
|
10127
10515
|
|
10128
|
-
return
|
10516
|
+
return parse_value_expression(parser, binding_power, diag_id);
|
10129
10517
|
}
|
10130
10518
|
|
10131
10519
|
/**
|
@@ -10147,6 +10535,8 @@ parse_write_name(pm_parser_t *parser, pm_constant_id_t *name_field) {
|
|
10147
10535
|
name[length] = '=';
|
10148
10536
|
|
10149
10537
|
// Now switch the name to the new string.
|
10538
|
+
// This silences clang analyzer warning about leak of memory pointed by `name`.
|
10539
|
+
// NOLINTNEXTLINE(clang-analyzer-*)
|
10150
10540
|
*name_field = pm_constant_pool_insert_owned(&parser->constant_pool, name, length + 1);
|
10151
10541
|
}
|
10152
10542
|
|
@@ -10179,8 +10569,8 @@ parse_target(pm_parser_t *parser, pm_node_t *target) {
|
|
10179
10569
|
target->type = PM_GLOBAL_VARIABLE_TARGET_NODE;
|
10180
10570
|
return target;
|
10181
10571
|
case PM_LOCAL_VARIABLE_READ_NODE:
|
10182
|
-
if (
|
10183
|
-
|
10572
|
+
if (pm_token_is_numbered_parameter(target->location.start, target->location.end)) {
|
10573
|
+
PM_PARSER_ERR_NODE_FORMAT(parser, target, PM_ERR_PARAMETER_NUMBERED_RESERVED, target->location.start);
|
10184
10574
|
} else {
|
10185
10575
|
assert(sizeof(pm_local_variable_target_node_t) == sizeof(pm_local_variable_read_node_t));
|
10186
10576
|
target->type = PM_LOCAL_VARIABLE_TARGET_NODE;
|
@@ -10238,10 +10628,7 @@ parse_target(pm_parser_t *parser, pm_node_t *target) {
|
|
10238
10628
|
assert(sizeof(pm_local_variable_target_node_t) == sizeof(pm_local_variable_read_node_t));
|
10239
10629
|
target->type = PM_LOCAL_VARIABLE_TARGET_NODE;
|
10240
10630
|
|
10241
|
-
|
10242
|
-
pm_parser_err_location(parser, &message, PM_ERR_PARAMETER_NUMBERED_RESERVED);
|
10243
|
-
}
|
10244
|
-
|
10631
|
+
pm_refute_numbered_parameter(parser, message.start, message.end);
|
10245
10632
|
return target;
|
10246
10633
|
}
|
10247
10634
|
|
@@ -10284,8 +10671,12 @@ static pm_node_t *
|
|
10284
10671
|
parse_target_validate(pm_parser_t *parser, pm_node_t *target) {
|
10285
10672
|
pm_node_t *result = parse_target(parser, target);
|
10286
10673
|
|
10287
|
-
// Ensure that we have
|
10288
|
-
if (
|
10674
|
+
// Ensure that we have one of an =, an 'in' in for indexes, and a ')' in parens after the targets.
|
10675
|
+
if (
|
10676
|
+
!match1(parser, PM_TOKEN_EQUAL) &&
|
10677
|
+
!(context_p(parser, PM_CONTEXT_FOR_INDEX) && match1(parser, PM_TOKEN_KEYWORD_IN)) &&
|
10678
|
+
!(context_p(parser, PM_CONTEXT_PARENS) && match1(parser, PM_TOKEN_PARENTHESIS_RIGHT))
|
10679
|
+
) {
|
10289
10680
|
pm_parser_err_node(parser, result, PM_ERR_WRITE_TARGET_UNEXPECTED);
|
10290
10681
|
}
|
10291
10682
|
|
@@ -10322,10 +10713,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
|
|
10322
10713
|
return (pm_node_t *) node;
|
10323
10714
|
}
|
10324
10715
|
case PM_LOCAL_VARIABLE_READ_NODE: {
|
10325
|
-
|
10326
|
-
pm_parser_err_node(parser, target, PM_ERR_PARAMETER_NUMBERED_RESERVED);
|
10327
|
-
}
|
10328
|
-
|
10716
|
+
pm_refute_numbered_parameter(parser, target->location.start, target->location.end);
|
10329
10717
|
pm_local_variable_read_node_t *local_read = (pm_local_variable_read_node_t *) target;
|
10330
10718
|
|
10331
10719
|
pm_constant_id_t constant_id = local_read->name;
|
@@ -10387,10 +10775,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
|
|
10387
10775
|
pm_constant_id_t constant_id = pm_parser_constant_id_location(parser, message.start, message.end);
|
10388
10776
|
target = (pm_node_t *) pm_local_variable_write_node_create(parser, constant_id, 0, value, &message, operator);
|
10389
10777
|
|
10390
|
-
|
10391
|
-
pm_parser_err_location(parser, &message, PM_ERR_PARAMETER_NUMBERED_RESERVED);
|
10392
|
-
}
|
10393
|
-
|
10778
|
+
pm_refute_numbered_parameter(parser, message.start, message.end);
|
10394
10779
|
return target;
|
10395
10780
|
}
|
10396
10781
|
|
@@ -10616,7 +11001,7 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) {
|
|
10616
11001
|
pm_node_t *value = NULL;
|
10617
11002
|
|
10618
11003
|
if (token_begins_expression_p(parser->current.type)) {
|
10619
|
-
value =
|
11004
|
+
value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
|
10620
11005
|
} else if (pm_parser_local_depth(parser, &operator) == -1) {
|
10621
11006
|
pm_parser_err_token(parser, &operator, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
|
10622
11007
|
}
|
@@ -10634,7 +11019,7 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) {
|
|
10634
11019
|
pm_node_t *value = NULL;
|
10635
11020
|
|
10636
11021
|
if (token_begins_expression_p(parser->current.type)) {
|
10637
|
-
value =
|
11022
|
+
value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_HASH_EXPRESSION_AFTER_LABEL);
|
10638
11023
|
} else {
|
10639
11024
|
if (parser->encoding.isupper_char(label.start, (label.end - 1) - label.start)) {
|
10640
11025
|
pm_token_t constant = { .type = PM_TOKEN_CONSTANT, .start = label.start, .end = label.end - 1 };
|
@@ -10658,7 +11043,7 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) {
|
|
10658
11043
|
break;
|
10659
11044
|
}
|
10660
11045
|
default: {
|
10661
|
-
pm_node_t *key =
|
11046
|
+
pm_node_t *key = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_HASH_KEY);
|
10662
11047
|
pm_token_t operator;
|
10663
11048
|
|
10664
11049
|
if (pm_symbol_node_label_p(key)) {
|
@@ -10668,7 +11053,7 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) {
|
|
10668
11053
|
operator = parser->previous;
|
10669
11054
|
}
|
10670
11055
|
|
10671
|
-
pm_node_t *value =
|
11056
|
+
pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_HASH_VALUE);
|
10672
11057
|
element = (pm_node_t *) pm_assoc_node_create(parser, key, &operator, value);
|
10673
11058
|
break;
|
10674
11059
|
}
|
@@ -10726,13 +11111,18 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|
10726
11111
|
return;
|
10727
11112
|
}
|
10728
11113
|
|
11114
|
+
bool parsed_first_argument = false;
|
10729
11115
|
bool parsed_bare_hash = false;
|
10730
11116
|
bool parsed_block_argument = false;
|
11117
|
+
bool parsed_forwarding_arguments = false;
|
10731
11118
|
|
10732
11119
|
while (!match1(parser, PM_TOKEN_EOF)) {
|
10733
11120
|
if (parsed_block_argument) {
|
10734
11121
|
pm_parser_err_current(parser, PM_ERR_ARGUMENT_AFTER_BLOCK);
|
10735
11122
|
}
|
11123
|
+
if (parsed_forwarding_arguments) {
|
11124
|
+
pm_parser_err_current(parser, PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES);
|
11125
|
+
}
|
10736
11126
|
|
10737
11127
|
pm_node_t *argument = NULL;
|
10738
11128
|
|
@@ -10764,7 +11154,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|
10764
11154
|
pm_node_t *expression = NULL;
|
10765
11155
|
|
10766
11156
|
if (token_begins_expression_p(parser->current.type)) {
|
10767
|
-
expression =
|
11157
|
+
expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_EXPECT_ARGUMENT);
|
10768
11158
|
} else if (pm_parser_local_depth(parser, &operator) == -1) {
|
10769
11159
|
pm_parser_err_token(parser, &operator, PM_ERR_ARGUMENT_NO_FORWARDING_AMP);
|
10770
11160
|
}
|
@@ -10783,14 +11173,14 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|
10783
11173
|
parser_lex(parser);
|
10784
11174
|
pm_token_t operator = parser->previous;
|
10785
11175
|
|
10786
|
-
if (
|
11176
|
+
if (match3(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_COMMA, PM_TOKEN_SEMICOLON)) {
|
10787
11177
|
if (pm_parser_local_depth(parser, &parser->previous) == -1) {
|
10788
11178
|
pm_parser_err_token(parser, &operator, PM_ERR_ARGUMENT_NO_FORWARDING_STAR);
|
10789
11179
|
}
|
10790
11180
|
|
10791
11181
|
argument = (pm_node_t *) pm_splat_node_create(parser, &operator, NULL);
|
10792
11182
|
} else {
|
10793
|
-
pm_node_t *expression =
|
11183
|
+
pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT);
|
10794
11184
|
|
10795
11185
|
if (parsed_bare_hash) {
|
10796
11186
|
pm_parser_err(parser, operator.start, expression->location.end, PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT);
|
@@ -10816,9 +11206,13 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|
10816
11206
|
if (pm_parser_local_depth(parser, &parser->previous) == -1) {
|
10817
11207
|
pm_parser_err_previous(parser, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
|
10818
11208
|
}
|
11209
|
+
if (parsed_first_argument && terminator == PM_TOKEN_EOF) {
|
11210
|
+
pm_parser_err_previous(parser, PM_ERR_ARGUMENT_FORWARDING_UNBOUND);
|
11211
|
+
}
|
10819
11212
|
|
10820
11213
|
argument = (pm_node_t *) pm_forwarding_arguments_node_create(parser, &parser->previous);
|
10821
11214
|
parse_arguments_append(parser, arguments, argument);
|
11215
|
+
parsed_forwarding_arguments = true;
|
10822
11216
|
break;
|
10823
11217
|
}
|
10824
11218
|
}
|
@@ -10826,7 +11220,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|
10826
11220
|
/* fallthrough */
|
10827
11221
|
default: {
|
10828
11222
|
if (argument == NULL) {
|
10829
|
-
argument =
|
11223
|
+
argument = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_EXPECT_ARGUMENT);
|
10830
11224
|
}
|
10831
11225
|
|
10832
11226
|
bool contains_keyword_splat = false;
|
@@ -10845,7 +11239,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|
10845
11239
|
pm_keyword_hash_node_t *bare_hash = pm_keyword_hash_node_create(parser);
|
10846
11240
|
|
10847
11241
|
// Finish parsing the one we are part way through
|
10848
|
-
pm_node_t *value =
|
11242
|
+
pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_HASH_VALUE);
|
10849
11243
|
|
10850
11244
|
argument = (pm_node_t *) pm_assoc_node_create(parser, argument, &operator, value);
|
10851
11245
|
pm_keyword_hash_node_elements_append(bare_hash, argument);
|
@@ -10870,6 +11264,8 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|
10870
11264
|
}
|
10871
11265
|
}
|
10872
11266
|
|
11267
|
+
parsed_first_argument = true;
|
11268
|
+
|
10873
11269
|
// If parsing the argument failed, we need to stop parsing arguments.
|
10874
11270
|
if (PM_NODE_TYPE_P(argument, PM_MISSING_NODE) || parser->recovering) break;
|
10875
11271
|
|
@@ -11029,7 +11425,7 @@ parse_parameters(
|
|
11029
11425
|
pm_binding_power_t binding_power,
|
11030
11426
|
bool uses_parentheses,
|
11031
11427
|
bool allows_trailing_comma,
|
11032
|
-
bool
|
11428
|
+
bool allows_forwarding_parameters
|
11033
11429
|
) {
|
11034
11430
|
pm_parameters_node_t *params = pm_parameters_node_create(parser);
|
11035
11431
|
bool looping = true;
|
@@ -11064,7 +11460,10 @@ parse_parameters(
|
|
11064
11460
|
pm_parser_local_add_token(parser, &name);
|
11065
11461
|
} else {
|
11066
11462
|
name = not_provided(parser);
|
11067
|
-
|
11463
|
+
|
11464
|
+
if (allows_forwarding_parameters) {
|
11465
|
+
pm_parser_local_add_token(parser, &operator);
|
11466
|
+
}
|
11068
11467
|
}
|
11069
11468
|
|
11070
11469
|
pm_block_parameter_node_t *param = pm_block_parameter_node_create(parser, &name, &operator);
|
@@ -11078,7 +11477,7 @@ parse_parameters(
|
|
11078
11477
|
break;
|
11079
11478
|
}
|
11080
11479
|
case PM_TOKEN_UDOT_DOT_DOT: {
|
11081
|
-
if (!
|
11480
|
+
if (!allows_forwarding_parameters) {
|
11082
11481
|
pm_parser_err_current(parser, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
|
11083
11482
|
}
|
11084
11483
|
|
@@ -11086,9 +11485,7 @@ parse_parameters(
|
|
11086
11485
|
update_parameter_state(parser, &parser->current, &order);
|
11087
11486
|
parser_lex(parser);
|
11088
11487
|
|
11089
|
-
if (
|
11090
|
-
pm_parser_local_add_constant(parser, "*", 1);
|
11091
|
-
pm_parser_local_add_constant(parser, "&", 1);
|
11488
|
+
if (allows_forwarding_parameters) {
|
11092
11489
|
pm_parser_local_add_token(parser, &parser->previous);
|
11093
11490
|
}
|
11094
11491
|
|
@@ -11148,7 +11545,7 @@ parse_parameters(
|
|
11148
11545
|
if (accept1(parser, PM_TOKEN_EQUAL)) {
|
11149
11546
|
pm_token_t operator = parser->previous;
|
11150
11547
|
context_push(parser, PM_CONTEXT_DEFAULT_PARAMS);
|
11151
|
-
pm_node_t *value =
|
11548
|
+
pm_node_t *value = parse_value_expression(parser, binding_power, PM_ERR_PARAMETER_NO_DEFAULT);
|
11152
11549
|
|
11153
11550
|
pm_optional_parameter_node_t *param = pm_optional_parameter_node_create(parser, &name, &operator, value);
|
11154
11551
|
pm_parameters_node_optionals_append(params, param);
|
@@ -11207,7 +11604,7 @@ parse_parameters(
|
|
11207
11604
|
|
11208
11605
|
if (token_begins_expression_p(parser->current.type)) {
|
11209
11606
|
context_push(parser, PM_CONTEXT_DEFAULT_PARAMS);
|
11210
|
-
pm_node_t *value =
|
11607
|
+
pm_node_t *value = parse_value_expression(parser, binding_power, PM_ERR_PARAMETER_NO_DEFAULT_KW);
|
11211
11608
|
context_pop(parser);
|
11212
11609
|
param = (pm_node_t *) pm_optional_keyword_parameter_node_create(parser, &name, value);
|
11213
11610
|
}
|
@@ -11244,7 +11641,10 @@ parse_parameters(
|
|
11244
11641
|
pm_parser_local_add_token(parser, &name);
|
11245
11642
|
} else {
|
11246
11643
|
name = not_provided(parser);
|
11247
|
-
|
11644
|
+
|
11645
|
+
if (allows_forwarding_parameters) {
|
11646
|
+
pm_parser_local_add_token(parser, &operator);
|
11647
|
+
}
|
11248
11648
|
}
|
11249
11649
|
|
11250
11650
|
pm_rest_parameter_node_t *param = pm_rest_parameter_node_create(parser, &operator, &name);
|
@@ -11276,7 +11676,10 @@ parse_parameters(
|
|
11276
11676
|
pm_parser_local_add_token(parser, &name);
|
11277
11677
|
} else {
|
11278
11678
|
name = not_provided(parser);
|
11279
|
-
|
11679
|
+
|
11680
|
+
if (allows_forwarding_parameters) {
|
11681
|
+
pm_parser_local_add_token(parser, &operator);
|
11682
|
+
}
|
11280
11683
|
}
|
11281
11684
|
|
11282
11685
|
param = (pm_node_t *) pm_keyword_rest_parameter_node_create(parser, &operator, &name);
|
@@ -11622,6 +12025,13 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept
|
|
11622
12025
|
// argument to this method call.
|
11623
12026
|
parse_arguments(parser, arguments, true, PM_TOKEN_EOF);
|
11624
12027
|
|
12028
|
+
// If we have done with the arguments and still not consumed the comma,
|
12029
|
+
// then we have a trailing comma where we need to check whether it is
|
12030
|
+
// allowed or not.
|
12031
|
+
if (parser->previous.type == PM_TOKEN_COMMA && !match1(parser, PM_TOKEN_SEMICOLON)) {
|
12032
|
+
pm_parser_err_previous(parser, PM_ERR_EXPECT_ARGUMENT);
|
12033
|
+
}
|
12034
|
+
|
11625
12035
|
pm_accepts_block_stack_pop(parser);
|
11626
12036
|
}
|
11627
12037
|
|
@@ -11658,14 +12068,19 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept
|
|
11658
12068
|
}
|
11659
12069
|
|
11660
12070
|
static inline pm_node_t *
|
11661
|
-
parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_context_t context) {
|
12071
|
+
parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_context_t context, pm_token_t *then_keyword) {
|
11662
12072
|
context_push(parser, PM_CONTEXT_PREDICATE);
|
11663
12073
|
pm_diagnostic_id_t error_id = context == PM_CONTEXT_IF ? PM_ERR_CONDITIONAL_IF_PREDICATE : PM_ERR_CONDITIONAL_UNLESS_PREDICATE;
|
11664
|
-
pm_node_t *predicate =
|
12074
|
+
pm_node_t *predicate = parse_value_expression(parser, binding_power, error_id);
|
11665
12075
|
|
11666
12076
|
// Predicates are closed by a term, a "then", or a term and then a "then".
|
11667
12077
|
bool predicate_closed = accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
|
11668
|
-
|
12078
|
+
|
12079
|
+
if (accept1(parser, PM_TOKEN_KEYWORD_THEN)) {
|
12080
|
+
predicate_closed = true;
|
12081
|
+
*then_keyword = parser->previous;
|
12082
|
+
}
|
12083
|
+
|
11669
12084
|
if (!predicate_closed) {
|
11670
12085
|
pm_parser_err_current(parser, PM_ERR_CONDITIONAL_PREDICATE_TERM);
|
11671
12086
|
}
|
@@ -11677,7 +12092,9 @@ parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_contex
|
|
11677
12092
|
static inline pm_node_t *
|
11678
12093
|
parse_conditional(pm_parser_t *parser, pm_context_t context) {
|
11679
12094
|
pm_token_t keyword = parser->previous;
|
11680
|
-
|
12095
|
+
pm_token_t then_keyword = not_provided(parser);
|
12096
|
+
|
12097
|
+
pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, context, &then_keyword);
|
11681
12098
|
pm_statements_node_t *statements = NULL;
|
11682
12099
|
|
11683
12100
|
if (!match3(parser, PM_TOKEN_KEYWORD_ELSIF, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) {
|
@@ -11692,10 +12109,10 @@ parse_conditional(pm_parser_t *parser, pm_context_t context) {
|
|
11692
12109
|
|
11693
12110
|
switch (context) {
|
11694
12111
|
case PM_CONTEXT_IF:
|
11695
|
-
parent = (pm_node_t *) pm_if_node_create(parser, &keyword, predicate, statements, NULL, &end_keyword);
|
12112
|
+
parent = (pm_node_t *) pm_if_node_create(parser, &keyword, predicate, &then_keyword, statements, NULL, &end_keyword);
|
11696
12113
|
break;
|
11697
12114
|
case PM_CONTEXT_UNLESS:
|
11698
|
-
parent = (pm_node_t *) pm_unless_node_create(parser, &keyword, predicate, statements);
|
12115
|
+
parent = (pm_node_t *) pm_unless_node_create(parser, &keyword, predicate, &then_keyword, statements);
|
11699
12116
|
break;
|
11700
12117
|
default:
|
11701
12118
|
assert(false && "unreachable");
|
@@ -11709,14 +12126,14 @@ parse_conditional(pm_parser_t *parser, pm_context_t context) {
|
|
11709
12126
|
if (context == PM_CONTEXT_IF) {
|
11710
12127
|
while (accept1(parser, PM_TOKEN_KEYWORD_ELSIF)) {
|
11711
12128
|
pm_token_t elsif_keyword = parser->previous;
|
11712
|
-
pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, PM_CONTEXT_ELSIF);
|
12129
|
+
pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, PM_CONTEXT_ELSIF, &then_keyword);
|
11713
12130
|
pm_accepts_block_stack_push(parser, true);
|
11714
12131
|
pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_ELSIF);
|
11715
12132
|
pm_accepts_block_stack_pop(parser);
|
11716
12133
|
|
11717
12134
|
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
|
11718
12135
|
|
11719
|
-
pm_node_t *elsif = (pm_node_t *) pm_if_node_create(parser, &elsif_keyword, predicate, statements, NULL, &end_keyword);
|
12136
|
+
pm_node_t *elsif = (pm_node_t *) pm_if_node_create(parser, &elsif_keyword, predicate, &then_keyword, statements, NULL, &end_keyword);
|
11720
12137
|
((pm_if_node_t *) current)->consequent = elsif;
|
11721
12138
|
current = elsif;
|
11722
12139
|
}
|
@@ -12165,7 +12582,7 @@ parse_variable_call(pm_parser_t *parser) {
|
|
12165
12582
|
return (pm_node_t *) pm_local_variable_read_node_create(parser, &parser->previous, (uint32_t) depth);
|
12166
12583
|
}
|
12167
12584
|
|
12168
|
-
if (!parser->current_scope->closed &&
|
12585
|
+
if (!parser->current_scope->closed && pm_token_is_numbered_parameter(parser->previous.start, parser->previous.end)) {
|
12169
12586
|
// Indicate that this scope is using numbered params so that child
|
12170
12587
|
// scopes cannot.
|
12171
12588
|
parser->current_scope->numbered_params = true;
|
@@ -12212,15 +12629,23 @@ parse_variable_call(pm_parser_t *parser) {
|
|
12212
12629
|
return (pm_node_t *) node;
|
12213
12630
|
}
|
12214
12631
|
|
12632
|
+
/**
|
12633
|
+
* Parse the method definition name based on the current token available on the
|
12634
|
+
* parser. If it does not match a valid method definition name, then a missing
|
12635
|
+
* token is returned.
|
12636
|
+
*/
|
12215
12637
|
static inline pm_token_t
|
12216
12638
|
parse_method_definition_name(pm_parser_t *parser) {
|
12217
12639
|
switch (parser->current.type) {
|
12218
12640
|
case PM_CASE_KEYWORD:
|
12219
12641
|
case PM_TOKEN_CONSTANT:
|
12220
|
-
case PM_TOKEN_IDENTIFIER:
|
12221
12642
|
case PM_TOKEN_METHOD_NAME:
|
12222
12643
|
parser_lex(parser);
|
12223
12644
|
return parser->previous;
|
12645
|
+
case PM_TOKEN_IDENTIFIER:
|
12646
|
+
pm_refute_numbered_parameter(parser, parser->current.start, parser->current.end);
|
12647
|
+
parser_lex(parser);
|
12648
|
+
return parser->previous;
|
12224
12649
|
case PM_CASE_OPERATOR:
|
12225
12650
|
lex_state_set(parser, PM_LEX_STATE_ENDFN);
|
12226
12651
|
parser_lex(parser);
|
@@ -12781,7 +13206,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
|
|
12781
13206
|
pm_token_t lparen = parser->current;
|
12782
13207
|
parser_lex(parser);
|
12783
13208
|
|
12784
|
-
pm_node_t *expression =
|
13209
|
+
pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN);
|
12785
13210
|
parser->pattern_matching_newlines = previous_pattern_matching_newlines;
|
12786
13211
|
|
12787
13212
|
accept1(parser, PM_TOKEN_NEWLINE);
|
@@ -13024,9 +13449,10 @@ parse_strings_empty_content(const uint8_t *location) {
|
|
13024
13449
|
* Parse a set of strings that could be concatenated together.
|
13025
13450
|
*/
|
13026
13451
|
static inline pm_node_t *
|
13027
|
-
parse_strings(pm_parser_t *parser) {
|
13452
|
+
parse_strings(pm_parser_t *parser, pm_node_t *current) {
|
13028
13453
|
assert(parser->current.type == PM_TOKEN_STRING_BEGIN);
|
13029
|
-
|
13454
|
+
|
13455
|
+
bool concating = false;
|
13030
13456
|
bool state_is_arg_labeled = lex_state_p(parser, PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED);
|
13031
13457
|
|
13032
13458
|
while (match1(parser, PM_TOKEN_STRING_BEGIN)) {
|
@@ -13162,7 +13588,7 @@ parse_strings(pm_parser_t *parser) {
|
|
13162
13588
|
}
|
13163
13589
|
}
|
13164
13590
|
|
13165
|
-
if (
|
13591
|
+
if (current == NULL) {
|
13166
13592
|
// If the node we just parsed is a symbol node, then we can't
|
13167
13593
|
// concatenate it with anything else, so we can now return that
|
13168
13594
|
// node.
|
@@ -13172,7 +13598,7 @@ parse_strings(pm_parser_t *parser) {
|
|
13172
13598
|
|
13173
13599
|
// If we don't already have a node, then it's fine and we can just
|
13174
13600
|
// set the result to be the node we just parsed.
|
13175
|
-
|
13601
|
+
current = node;
|
13176
13602
|
} else {
|
13177
13603
|
// Otherwise we need to check the type of the node we just parsed.
|
13178
13604
|
// If it cannot be concatenated with the previous node, then we'll
|
@@ -13181,13 +13607,22 @@ parse_strings(pm_parser_t *parser) {
|
|
13181
13607
|
pm_parser_err_node(parser, node, PM_ERR_STRING_CONCATENATION);
|
13182
13608
|
}
|
13183
13609
|
|
13184
|
-
//
|
13185
|
-
//
|
13186
|
-
|
13610
|
+
// If we haven't already created our container for concatenation,
|
13611
|
+
// we'll do that now.
|
13612
|
+
if (!concating) {
|
13613
|
+
concating = true;
|
13614
|
+
pm_token_t bounds = not_provided(parser);
|
13615
|
+
|
13616
|
+
pm_interpolated_string_node_t *container = pm_interpolated_string_node_create(parser, &bounds, NULL, &bounds);
|
13617
|
+
pm_interpolated_string_node_append(container, current);
|
13618
|
+
current = (pm_node_t *) container;
|
13619
|
+
}
|
13620
|
+
|
13621
|
+
pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, node);
|
13187
13622
|
}
|
13188
13623
|
}
|
13189
13624
|
|
13190
|
-
return
|
13625
|
+
return current;
|
13191
13626
|
}
|
13192
13627
|
|
13193
13628
|
/**
|
@@ -13304,7 +13739,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13304
13739
|
// Otherwise, we're going to parse the first statement in the list
|
13305
13740
|
// of statements within the parentheses.
|
13306
13741
|
pm_accepts_block_stack_push(parser, true);
|
13742
|
+
context_push(parser, PM_CONTEXT_PARENS);
|
13307
13743
|
pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_STATEMENT, PM_ERR_CANNOT_PARSE_EXPRESSION);
|
13744
|
+
context_pop(parser);
|
13308
13745
|
|
13309
13746
|
// Determine if this statement is followed by a terminator. In the
|
13310
13747
|
// case of a single statement, this is fine. But in the case of
|
@@ -13446,8 +13883,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13446
13883
|
// Characters can be followed by strings in which case they are
|
13447
13884
|
// automatically concatenated.
|
13448
13885
|
if (match1(parser, PM_TOKEN_STRING_BEGIN)) {
|
13449
|
-
|
13450
|
-
return (pm_node_t *) pm_string_concat_node_create(parser, node, concat);
|
13886
|
+
return parse_strings(parser, node);
|
13451
13887
|
}
|
13452
13888
|
|
13453
13889
|
return node;
|
@@ -13661,7 +14097,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13661
14097
|
cast->base.type = PM_X_STRING_NODE;
|
13662
14098
|
}
|
13663
14099
|
|
13664
|
-
size_t common_whitespace =
|
14100
|
+
size_t common_whitespace = parser->current_string_common_whitespace;
|
13665
14101
|
if (indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) {
|
13666
14102
|
parse_heredoc_dedent_string(&cast->unescaped, common_whitespace);
|
13667
14103
|
}
|
@@ -13707,7 +14143,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13707
14143
|
|
13708
14144
|
// If this is a heredoc that is indented with a ~, then we need
|
13709
14145
|
// to dedent each line by the common leading whitespace.
|
13710
|
-
size_t common_whitespace =
|
14146
|
+
size_t common_whitespace = parser->current_string_common_whitespace;
|
13711
14147
|
if (indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) {
|
13712
14148
|
pm_node_list_t *nodes;
|
13713
14149
|
if (quote == PM_HEREDOC_QUOTE_BACKTICK) {
|
@@ -13721,8 +14157,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13721
14157
|
}
|
13722
14158
|
|
13723
14159
|
if (match1(parser, PM_TOKEN_STRING_BEGIN)) {
|
13724
|
-
|
13725
|
-
return (pm_node_t *) pm_string_concat_node_create(parser, node, concat);
|
14160
|
+
return parse_strings(parser, node);
|
13726
14161
|
}
|
13727
14162
|
|
13728
14163
|
return node;
|
@@ -13811,21 +14246,23 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13811
14246
|
} else if (!token_begins_expression_p(parser->current.type)) {
|
13812
14247
|
predicate = NULL;
|
13813
14248
|
} else {
|
13814
|
-
predicate =
|
14249
|
+
predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_ERR_CASE_EXPRESSION_AFTER_CASE);
|
13815
14250
|
while (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON));
|
13816
14251
|
}
|
13817
14252
|
|
13818
14253
|
if (accept1(parser, PM_TOKEN_KEYWORD_END)) {
|
13819
14254
|
pm_parser_err_token(parser, &case_keyword, PM_ERR_CASE_MISSING_CONDITIONS);
|
13820
|
-
return (pm_node_t *) pm_case_node_create(parser, &case_keyword, predicate,
|
14255
|
+
return (pm_node_t *) pm_case_node_create(parser, &case_keyword, predicate, &parser->previous);
|
13821
14256
|
}
|
13822
14257
|
|
13823
14258
|
// At this point we can create a case node, though we don't yet know if it
|
13824
14259
|
// is a case-in or case-when node.
|
13825
14260
|
pm_token_t end_keyword = not_provided(parser);
|
13826
|
-
|
14261
|
+
pm_node_t *node;
|
13827
14262
|
|
13828
14263
|
if (match1(parser, PM_TOKEN_KEYWORD_WHEN)) {
|
14264
|
+
pm_case_node_t *case_node = pm_case_node_create(parser, &case_keyword, predicate, &end_keyword);
|
14265
|
+
|
13829
14266
|
// At this point we've seen a when keyword, so we know this is a
|
13830
14267
|
// case-when node. We will continue to parse the when nodes until we hit
|
13831
14268
|
// the end of the list.
|
@@ -13836,14 +14273,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13836
14273
|
do {
|
13837
14274
|
if (accept1(parser, PM_TOKEN_USTAR)) {
|
13838
14275
|
pm_token_t operator = parser->previous;
|
13839
|
-
pm_node_t *expression =
|
14276
|
+
pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
|
13840
14277
|
|
13841
14278
|
pm_splat_node_t *splat_node = pm_splat_node_create(parser, &operator, expression);
|
13842
14279
|
pm_when_node_conditions_append(when_node, (pm_node_t *) splat_node);
|
13843
14280
|
|
13844
14281
|
if (PM_NODE_TYPE_P(expression, PM_MISSING_NODE)) break;
|
13845
14282
|
} else {
|
13846
|
-
pm_node_t *condition =
|
14283
|
+
pm_node_t *condition = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_CASE_EXPRESSION_AFTER_WHEN);
|
13847
14284
|
pm_when_node_conditions_append(when_node, condition);
|
13848
14285
|
|
13849
14286
|
if (PM_NODE_TYPE_P(condition, PM_MISSING_NODE)) break;
|
@@ -13865,7 +14302,23 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13865
14302
|
|
13866
14303
|
pm_case_node_condition_append(case_node, (pm_node_t *) when_node);
|
13867
14304
|
}
|
14305
|
+
|
14306
|
+
// If we didn't parse any conditions (in or when) then we need
|
14307
|
+
// to indicate that we have an error.
|
14308
|
+
if (case_node->conditions.size == 0) {
|
14309
|
+
pm_parser_err_token(parser, &case_keyword, PM_ERR_CASE_MISSING_CONDITIONS);
|
14310
|
+
}
|
14311
|
+
|
14312
|
+
node = (pm_node_t *) case_node;
|
13868
14313
|
} else {
|
14314
|
+
pm_case_match_node_t *case_node = pm_case_match_node_create(parser, &case_keyword, predicate, &end_keyword);
|
14315
|
+
|
14316
|
+
// If this is a case-match node (i.e., it is a pattern matching
|
14317
|
+
// case statement) then we must have a predicate.
|
14318
|
+
if (predicate == NULL) {
|
14319
|
+
pm_parser_err_token(parser, &case_keyword, PM_ERR_CASE_MATCH_MISSING_PREDICATE);
|
14320
|
+
}
|
14321
|
+
|
13869
14322
|
// At this point we expect that we're parsing a case-in node. We will
|
13870
14323
|
// continue to parse the in nodes until we hit the end of the list.
|
13871
14324
|
while (match1(parser, PM_TOKEN_KEYWORD_IN)) {
|
@@ -13884,11 +14337,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13884
14337
|
// for guard clauses in the form of `if` or `unless` statements.
|
13885
14338
|
if (accept1(parser, PM_TOKEN_KEYWORD_IF_MODIFIER)) {
|
13886
14339
|
pm_token_t keyword = parser->previous;
|
13887
|
-
pm_node_t *predicate =
|
14340
|
+
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_CONDITIONAL_IF_PREDICATE);
|
13888
14341
|
pattern = (pm_node_t *) pm_if_node_modifier_create(parser, pattern, &keyword, predicate);
|
13889
14342
|
} else if (accept1(parser, PM_TOKEN_KEYWORD_UNLESS_MODIFIER)) {
|
13890
14343
|
pm_token_t keyword = parser->previous;
|
13891
|
-
pm_node_t *predicate =
|
14344
|
+
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_CONDITIONAL_UNLESS_PREDICATE);
|
13892
14345
|
pattern = (pm_node_t *) pm_unless_node_modifier_create(parser, pattern, &keyword, predicate);
|
13893
14346
|
}
|
13894
14347
|
|
@@ -13919,14 +14372,16 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13919
14372
|
// Now that we have the full pattern and statements, we can create the
|
13920
14373
|
// node and attach it to the case node.
|
13921
14374
|
pm_node_t *condition = (pm_node_t *) pm_in_node_create(parser, pattern, statements, &in_keyword, &then_keyword);
|
13922
|
-
|
14375
|
+
pm_case_match_node_condition_append(case_node, condition);
|
13923
14376
|
}
|
13924
|
-
}
|
13925
14377
|
|
13926
|
-
|
13927
|
-
|
13928
|
-
|
13929
|
-
|
14378
|
+
// If we didn't parse any conditions (in or when) then we need
|
14379
|
+
// to indicate that we have an error.
|
14380
|
+
if (case_node->conditions.size == 0) {
|
14381
|
+
pm_parser_err_token(parser, &case_keyword, PM_ERR_CASE_MISSING_CONDITIONS);
|
14382
|
+
}
|
14383
|
+
|
14384
|
+
node = (pm_node_t *) case_node;
|
13930
14385
|
}
|
13931
14386
|
|
13932
14387
|
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
|
@@ -13940,12 +14395,21 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13940
14395
|
else_node = pm_else_node_create(parser, &else_keyword, NULL, &parser->current);
|
13941
14396
|
}
|
13942
14397
|
|
13943
|
-
|
14398
|
+
if (PM_NODE_TYPE_P(node, PM_CASE_NODE)) {
|
14399
|
+
pm_case_node_consequent_set((pm_case_node_t *) node, else_node);
|
14400
|
+
} else {
|
14401
|
+
pm_case_match_node_consequent_set((pm_case_match_node_t *) node, else_node);
|
14402
|
+
}
|
13944
14403
|
}
|
13945
14404
|
|
13946
14405
|
expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CASE_TERM);
|
13947
|
-
|
13948
|
-
|
14406
|
+
if (PM_NODE_TYPE_P(node, PM_CASE_NODE)) {
|
14407
|
+
pm_case_node_end_keyword_loc_set((pm_case_node_t *) node, &parser->previous);
|
14408
|
+
} else {
|
14409
|
+
pm_case_match_node_end_keyword_loc_set((pm_case_match_node_t *) node, &parser->previous);
|
14410
|
+
}
|
14411
|
+
|
14412
|
+
return node;
|
13949
14413
|
}
|
13950
14414
|
case PM_TOKEN_KEYWORD_BEGIN: {
|
13951
14415
|
parser_lex(parser);
|
@@ -14101,7 +14565,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14101
14565
|
parser->command_start = true;
|
14102
14566
|
parser_lex(parser);
|
14103
14567
|
|
14104
|
-
superclass =
|
14568
|
+
superclass = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_ERR_CLASS_SUPERCLASS);
|
14105
14569
|
} else {
|
14106
14570
|
inheritance_operator = not_provided(parser);
|
14107
14571
|
superclass = NULL;
|
@@ -14172,6 +14636,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14172
14636
|
operator = parser->previous;
|
14173
14637
|
name = parse_method_definition_name(parser);
|
14174
14638
|
} else {
|
14639
|
+
pm_refute_numbered_parameter(parser, parser->previous.start, parser->previous.end);
|
14175
14640
|
pm_parser_scope_push(parser, true);
|
14176
14641
|
name = parser->previous;
|
14177
14642
|
}
|
@@ -14245,7 +14710,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14245
14710
|
case PM_TOKEN_PARENTHESIS_LEFT: {
|
14246
14711
|
parser_lex(parser);
|
14247
14712
|
pm_token_t lparen = parser->previous;
|
14248
|
-
pm_node_t *expression =
|
14713
|
+
pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, PM_ERR_DEF_RECEIVER);
|
14249
14714
|
|
14250
14715
|
expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN);
|
14251
14716
|
pm_token_t rparen = parser->previous;
|
@@ -14326,6 +14791,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14326
14791
|
equal = parser->previous;
|
14327
14792
|
|
14328
14793
|
context_push(parser, PM_CONTEXT_DEF);
|
14794
|
+
pm_do_loop_stack_push(parser, false);
|
14329
14795
|
statements = (pm_node_t *) pm_statements_node_create(parser);
|
14330
14796
|
|
14331
14797
|
pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, PM_ERR_DEF_ENDLESS);
|
@@ -14338,6 +14804,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14338
14804
|
}
|
14339
14805
|
|
14340
14806
|
pm_statements_node_body_append((pm_statements_node_t *) statements, statement);
|
14807
|
+
pm_do_loop_stack_pop(parser);
|
14341
14808
|
context_pop(parser);
|
14342
14809
|
end_keyword = not_provided(parser);
|
14343
14810
|
} else {
|
@@ -14425,6 +14892,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14425
14892
|
parser_lex(parser);
|
14426
14893
|
pm_token_t keyword = parser->previous;
|
14427
14894
|
|
14895
|
+
if (context_def_p(parser)) {
|
14896
|
+
pm_parser_warn_token(parser, &keyword, PM_WARN_END_IN_METHOD);
|
14897
|
+
}
|
14898
|
+
|
14428
14899
|
expect1(parser, PM_TOKEN_BRACE_LEFT, PM_ERR_END_UPCASE_BRACE);
|
14429
14900
|
pm_token_t opening = parser->previous;
|
14430
14901
|
pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_POSTEXE);
|
@@ -14474,7 +14945,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14474
14945
|
expect1(parser, PM_TOKEN_KEYWORD_IN, PM_ERR_FOR_IN);
|
14475
14946
|
pm_token_t in_keyword = parser->previous;
|
14476
14947
|
|
14477
|
-
pm_node_t *collection =
|
14948
|
+
pm_node_t *collection = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_ERR_FOR_COLLECTION);
|
14478
14949
|
pm_do_loop_stack_pop(parser);
|
14479
14950
|
|
14480
14951
|
pm_token_t do_keyword;
|
@@ -14636,7 +15107,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14636
15107
|
parser_lex(parser);
|
14637
15108
|
pm_token_t keyword = parser->previous;
|
14638
15109
|
|
14639
|
-
pm_node_t *predicate =
|
15110
|
+
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
|
14640
15111
|
pm_do_loop_stack_pop(parser);
|
14641
15112
|
|
14642
15113
|
expect3(parser, PM_TOKEN_KEYWORD_DO_LOOP, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
|
@@ -14657,7 +15128,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14657
15128
|
parser_lex(parser);
|
14658
15129
|
pm_token_t keyword = parser->previous;
|
14659
15130
|
|
14660
|
-
pm_node_t *predicate =
|
15131
|
+
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
|
14661
15132
|
pm_do_loop_stack_pop(parser);
|
14662
15133
|
|
14663
15134
|
expect3(parser, PM_TOKEN_KEYWORD_DO_LOOP, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
|
@@ -15293,7 +15764,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15293
15764
|
return (pm_node_t *) node;
|
15294
15765
|
}
|
15295
15766
|
case PM_TOKEN_STRING_BEGIN:
|
15296
|
-
return parse_strings(parser);
|
15767
|
+
return parse_strings(parser, NULL);
|
15297
15768
|
case PM_TOKEN_SYMBOL_BEGIN: {
|
15298
15769
|
pm_lex_mode_t lex_mode = *parser->lex_modes.current;
|
15299
15770
|
parser_lex(parser);
|
@@ -15310,10 +15781,29 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15310
15781
|
}
|
15311
15782
|
|
15312
15783
|
static inline pm_node_t *
|
15313
|
-
parse_assignment_value(pm_parser_t *parser, pm_binding_power_t
|
15784
|
+
parse_assignment_value(pm_parser_t *parser, pm_binding_power_t binding_power, pm_diagnostic_id_t diag_id) {
|
15785
|
+
pm_node_t *value = parse_value_expression(parser, binding_power, diag_id);
|
15786
|
+
|
15787
|
+
// Contradicting binding powers, the right-hand-side value of rthe assignment allows the `rescue` modifier.
|
15788
|
+
if (match1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) {
|
15789
|
+
pm_token_t rescue = parser->current;
|
15790
|
+
parser_lex(parser);
|
15791
|
+
pm_node_t *right = parse_expression(parser, binding_power, PM_ERR_RESCUE_MODIFIER_VALUE);
|
15792
|
+
|
15793
|
+
return (pm_node_t *) pm_rescue_modifier_node_create(parser, value, &rescue, right);
|
15794
|
+
}
|
15795
|
+
|
15796
|
+
return value;
|
15797
|
+
}
|
15798
|
+
|
15799
|
+
|
15800
|
+
static inline pm_node_t *
|
15801
|
+
parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, pm_diagnostic_id_t diag_id) {
|
15314
15802
|
pm_node_t *value = parse_starred_expression(parser, binding_power, diag_id);
|
15315
15803
|
|
15804
|
+
bool is_single_value = true;
|
15316
15805
|
if (previous_binding_power == PM_BINDING_POWER_STATEMENT && (PM_NODE_TYPE_P(value, PM_SPLAT_NODE) || match1(parser, PM_TOKEN_COMMA))) {
|
15806
|
+
is_single_value = false;
|
15317
15807
|
pm_token_t opening = not_provided(parser);
|
15318
15808
|
pm_array_node_t *array = pm_array_node_create(parser, &opening);
|
15319
15809
|
|
@@ -15327,6 +15817,15 @@ parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_
|
|
15327
15817
|
}
|
15328
15818
|
}
|
15329
15819
|
|
15820
|
+
// Contradicting binding powers, the right-hand-side value of the assignment allows the `rescue` modifier.
|
15821
|
+
if (is_single_value && match1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) {
|
15822
|
+
pm_token_t rescue = parser->current;
|
15823
|
+
parser_lex(parser);
|
15824
|
+
pm_node_t *right = parse_expression(parser, binding_power, PM_ERR_RESCUE_MODIFIER_VALUE);
|
15825
|
+
|
15826
|
+
return (pm_node_t *) pm_rescue_modifier_node_create(parser, value, &rescue, right);
|
15827
|
+
}
|
15828
|
+
|
15330
15829
|
return value;
|
15331
15830
|
}
|
15332
15831
|
|
@@ -15352,6 +15851,25 @@ parse_call_operator_write(pm_parser_t *parser, pm_call_node_t *call_node, const
|
|
15352
15851
|
}
|
15353
15852
|
}
|
15354
15853
|
|
15854
|
+
static bool
|
15855
|
+
name_is_identifier(pm_parser_t *parser, const uint8_t *source, size_t length) {
|
15856
|
+
if (length == 0) {
|
15857
|
+
return false;
|
15858
|
+
}
|
15859
|
+
|
15860
|
+
size_t width = char_is_identifier_start(parser, source);
|
15861
|
+
if (!width) {
|
15862
|
+
return false;
|
15863
|
+
}
|
15864
|
+
|
15865
|
+
uint8_t *cursor = ((uint8_t *)source) + width;
|
15866
|
+
while (cursor < source + length && (width = char_is_identifier(parser, cursor))) {
|
15867
|
+
cursor += width;
|
15868
|
+
}
|
15869
|
+
|
15870
|
+
return cursor == source + length;
|
15871
|
+
}
|
15872
|
+
|
15355
15873
|
/**
|
15356
15874
|
* Potentially change a =~ with a regular expression with named captures into a
|
15357
15875
|
* match write node.
|
@@ -15362,42 +15880,77 @@ parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t *
|
|
15362
15880
|
pm_node_t *result;
|
15363
15881
|
|
15364
15882
|
if (pm_regexp_named_capture_group_names(pm_string_source(content), pm_string_length(content), &named_captures, parser->encoding_changed, &parser->encoding) && (named_captures.length > 0)) {
|
15365
|
-
|
15883
|
+
// Since we should not create a MatchWriteNode when all capture names
|
15884
|
+
// are invalid, creating a MatchWriteNode is delayed here.
|
15885
|
+
pm_match_write_node_t *match = NULL;
|
15886
|
+
pm_constant_id_list_t names = { 0 };
|
15366
15887
|
|
15367
15888
|
for (size_t index = 0; index < named_captures.length; index++) {
|
15368
|
-
pm_string_t *
|
15889
|
+
pm_string_t *string = &named_captures.strings[index];
|
15890
|
+
|
15891
|
+
const uint8_t *source = pm_string_source(string);
|
15892
|
+
size_t length = pm_string_length(string);
|
15369
15893
|
|
15370
|
-
|
15371
|
-
|
15894
|
+
pm_location_t location;
|
15895
|
+
pm_constant_id_t name;
|
15896
|
+
|
15897
|
+
// If the name of the capture group isn't a valid identifier, we do
|
15898
|
+
// not add it to the local table.
|
15899
|
+
if (!name_is_identifier(parser, source, length)) continue;
|
15372
15900
|
|
15373
|
-
pm_constant_id_t local;
|
15374
15901
|
if (content->type == PM_STRING_SHARED) {
|
15375
15902
|
// If the unescaped string is a slice of the source, then we can
|
15376
15903
|
// copy the names directly. The pointers will line up.
|
15377
|
-
|
15378
|
-
|
15379
|
-
|
15380
|
-
pm_parser_err(parser, source, source + length, PM_ERR_PARAMETER_NUMBERED_RESERVED);
|
15381
|
-
}
|
15904
|
+
location = (pm_location_t) { .start = source, .end = source + length };
|
15905
|
+
name = pm_parser_constant_id_location(parser, location.start, location.end);
|
15906
|
+
pm_refute_numbered_parameter(parser, source, source + length);
|
15382
15907
|
} else {
|
15383
15908
|
// Otherwise, the name is a slice of the malloc-ed owned string,
|
15384
15909
|
// in which case we need to copy it out into a new string.
|
15910
|
+
location = call->receiver->location;
|
15911
|
+
|
15385
15912
|
void *memory = malloc(length);
|
15386
15913
|
if (memory == NULL) abort();
|
15387
15914
|
|
15388
15915
|
memcpy(memory, source, length);
|
15389
|
-
|
15916
|
+
name = pm_parser_constant_id_owned(parser, (const uint8_t *) memory, length);
|
15390
15917
|
|
15391
|
-
if (
|
15918
|
+
if (pm_token_is_numbered_parameter(source, source + length)) {
|
15392
15919
|
const pm_location_t *location = &call->receiver->location;
|
15393
|
-
|
15920
|
+
PM_PARSER_ERR_LOCATION_FORMAT(parser, location, PM_ERR_PARAMETER_NUMBERED_RESERVED, location->start);
|
15394
15921
|
}
|
15395
15922
|
}
|
15396
15923
|
|
15397
|
-
|
15924
|
+
if (name != 0) {
|
15925
|
+
// We dont want to create duplicate targets if the capture name
|
15926
|
+
// is duplicated.
|
15927
|
+
if (pm_constant_id_list_includes(&names, name)) continue;
|
15928
|
+
pm_constant_id_list_append(&names, name);
|
15929
|
+
|
15930
|
+
// Here we lazily create the MatchWriteNode since we know we're
|
15931
|
+
// about to add a target.
|
15932
|
+
if (match == NULL) match = pm_match_write_node_create(parser, call);
|
15933
|
+
|
15934
|
+
// First, find the depth of the local that is being assigned.
|
15935
|
+
int depth;
|
15936
|
+
if ((depth = pm_parser_local_depth_constant_id(parser, name)) == -1) {
|
15937
|
+
pm_parser_local_add(parser, name);
|
15938
|
+
}
|
15939
|
+
|
15940
|
+
// Next, create the local variable target and add it to the
|
15941
|
+
// list of targets for the match.
|
15942
|
+
pm_node_t *target = (pm_node_t *) pm_local_variable_target_node_create_values(parser, &location, name, depth == -1 ? 0 : (uint32_t) depth);
|
15943
|
+
pm_node_list_append(&match->targets, target);
|
15944
|
+
}
|
15945
|
+
}
|
15946
|
+
|
15947
|
+
if (match != NULL) {
|
15948
|
+
result = (pm_node_t *) match;
|
15949
|
+
} else {
|
15950
|
+
result = (pm_node_t *) call;
|
15398
15951
|
}
|
15399
15952
|
|
15400
|
-
|
15953
|
+
pm_constant_id_list_free(&names);
|
15401
15954
|
} else {
|
15402
15955
|
result = (pm_node_t *) call;
|
15403
15956
|
}
|
@@ -15426,7 +15979,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15426
15979
|
/* fallthrough */
|
15427
15980
|
case PM_CASE_WRITABLE: {
|
15428
15981
|
parser_lex(parser);
|
15429
|
-
pm_node_t *value =
|
15982
|
+
pm_node_t *value = parse_assignment_values(parser, previous_binding_power, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
|
15430
15983
|
return parse_write(parser, node, &token, value);
|
15431
15984
|
}
|
15432
15985
|
case PM_SPLAT_NODE: {
|
@@ -15434,7 +15987,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15434
15987
|
pm_multi_target_node_targets_append(parser, multi_target, node);
|
15435
15988
|
|
15436
15989
|
parser_lex(parser);
|
15437
|
-
pm_node_t *value =
|
15990
|
+
pm_node_t *value = parse_assignment_values(parser, previous_binding_power, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
|
15438
15991
|
return parse_write(parser, (pm_node_t *) multi_target, &token, value);
|
15439
15992
|
}
|
15440
15993
|
default:
|
@@ -15456,7 +16009,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15456
16009
|
case PM_GLOBAL_VARIABLE_READ_NODE: {
|
15457
16010
|
parser_lex(parser);
|
15458
16011
|
|
15459
|
-
pm_node_t *value =
|
16012
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
15460
16013
|
pm_node_t *result = (pm_node_t *) pm_global_variable_and_write_node_create(parser, node, &token, value);
|
15461
16014
|
|
15462
16015
|
pm_node_destroy(parser, node);
|
@@ -15465,7 +16018,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15465
16018
|
case PM_CLASS_VARIABLE_READ_NODE: {
|
15466
16019
|
parser_lex(parser);
|
15467
16020
|
|
15468
|
-
pm_node_t *value =
|
16021
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
15469
16022
|
pm_node_t *result = (pm_node_t *) pm_class_variable_and_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value);
|
15470
16023
|
|
15471
16024
|
pm_node_destroy(parser, node);
|
@@ -15474,13 +16027,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15474
16027
|
case PM_CONSTANT_PATH_NODE: {
|
15475
16028
|
parser_lex(parser);
|
15476
16029
|
|
15477
|
-
pm_node_t *value =
|
16030
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
15478
16031
|
return (pm_node_t *) pm_constant_path_and_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
|
15479
16032
|
}
|
15480
16033
|
case PM_CONSTANT_READ_NODE: {
|
15481
16034
|
parser_lex(parser);
|
15482
16035
|
|
15483
|
-
pm_node_t *value =
|
16036
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
15484
16037
|
pm_node_t *result = (pm_node_t *) pm_constant_and_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
|
15485
16038
|
|
15486
16039
|
pm_node_destroy(parser, node);
|
@@ -15489,7 +16042,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15489
16042
|
case PM_INSTANCE_VARIABLE_READ_NODE: {
|
15490
16043
|
parser_lex(parser);
|
15491
16044
|
|
15492
|
-
pm_node_t *value =
|
16045
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
15493
16046
|
pm_node_t *result = (pm_node_t *) pm_instance_variable_and_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value);
|
15494
16047
|
|
15495
16048
|
pm_node_destroy(parser, node);
|
@@ -15499,7 +16052,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15499
16052
|
pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node;
|
15500
16053
|
parser_lex(parser);
|
15501
16054
|
|
15502
|
-
pm_node_t *value =
|
16055
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
15503
16056
|
pm_node_t *result = (pm_node_t *) pm_local_variable_and_write_node_create(parser, node, &token, value, cast->name, cast->depth);
|
15504
16057
|
|
15505
16058
|
pm_node_destroy(parser, node);
|
@@ -15513,14 +16066,11 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15513
16066
|
// receiver that could have been a local variable) then we
|
15514
16067
|
// will transform it into a local variable write.
|
15515
16068
|
if (pm_call_node_variable_call_p(cast)) {
|
15516
|
-
pm_location_t message_loc = cast->message_loc;
|
15517
|
-
|
15518
|
-
|
15519
|
-
if (token_is_numbered_parameter(message_loc.start, message_loc.end)) {
|
15520
|
-
pm_parser_err_location(parser, &message_loc, PM_ERR_PARAMETER_NUMBERED_RESERVED);
|
15521
|
-
}
|
16069
|
+
pm_location_t *message_loc = &cast->message_loc;
|
16070
|
+
pm_refute_numbered_parameter(parser, message_loc->start, message_loc->end);
|
15522
16071
|
|
15523
|
-
|
16072
|
+
pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc->start, message_loc->end);
|
16073
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
15524
16074
|
pm_node_t *result = (pm_node_t *) pm_local_variable_and_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0);
|
15525
16075
|
|
15526
16076
|
pm_node_destroy(parser, (pm_node_t *) cast);
|
@@ -15531,7 +16081,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15531
16081
|
// this is an aref expression, and we can transform it into
|
15532
16082
|
// an aset expression.
|
15533
16083
|
if (pm_call_node_index_p(cast)) {
|
15534
|
-
pm_node_t *value =
|
16084
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
15535
16085
|
return (pm_node_t *) pm_index_and_write_node_create(parser, cast, &token, value);
|
15536
16086
|
}
|
15537
16087
|
|
@@ -15543,7 +16093,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15543
16093
|
}
|
15544
16094
|
|
15545
16095
|
parse_call_operator_write(parser, cast, &token);
|
15546
|
-
pm_node_t *value =
|
16096
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
15547
16097
|
return (pm_node_t *) pm_call_and_write_node_create(parser, cast, &token, value);
|
15548
16098
|
}
|
15549
16099
|
case PM_MULTI_WRITE_NODE: {
|
@@ -15570,7 +16120,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15570
16120
|
case PM_GLOBAL_VARIABLE_READ_NODE: {
|
15571
16121
|
parser_lex(parser);
|
15572
16122
|
|
15573
|
-
pm_node_t *value =
|
16123
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
15574
16124
|
pm_node_t *result = (pm_node_t *) pm_global_variable_or_write_node_create(parser, node, &token, value);
|
15575
16125
|
|
15576
16126
|
pm_node_destroy(parser, node);
|
@@ -15579,7 +16129,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15579
16129
|
case PM_CLASS_VARIABLE_READ_NODE: {
|
15580
16130
|
parser_lex(parser);
|
15581
16131
|
|
15582
|
-
pm_node_t *value =
|
16132
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
15583
16133
|
pm_node_t *result = (pm_node_t *) pm_class_variable_or_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value);
|
15584
16134
|
|
15585
16135
|
pm_node_destroy(parser, node);
|
@@ -15588,13 +16138,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15588
16138
|
case PM_CONSTANT_PATH_NODE: {
|
15589
16139
|
parser_lex(parser);
|
15590
16140
|
|
15591
|
-
pm_node_t *value =
|
16141
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
15592
16142
|
return (pm_node_t *) pm_constant_path_or_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
|
15593
16143
|
}
|
15594
16144
|
case PM_CONSTANT_READ_NODE: {
|
15595
16145
|
parser_lex(parser);
|
15596
16146
|
|
15597
|
-
pm_node_t *value =
|
16147
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
15598
16148
|
pm_node_t *result = (pm_node_t *) pm_constant_or_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
|
15599
16149
|
|
15600
16150
|
pm_node_destroy(parser, node);
|
@@ -15603,7 +16153,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15603
16153
|
case PM_INSTANCE_VARIABLE_READ_NODE: {
|
15604
16154
|
parser_lex(parser);
|
15605
16155
|
|
15606
|
-
pm_node_t *value =
|
16156
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
15607
16157
|
pm_node_t *result = (pm_node_t *) pm_instance_variable_or_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value);
|
15608
16158
|
|
15609
16159
|
pm_node_destroy(parser, node);
|
@@ -15613,7 +16163,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15613
16163
|
pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node;
|
15614
16164
|
parser_lex(parser);
|
15615
16165
|
|
15616
|
-
pm_node_t *value =
|
16166
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
15617
16167
|
pm_node_t *result = (pm_node_t *) pm_local_variable_or_write_node_create(parser, node, &token, value, cast->name, cast->depth);
|
15618
16168
|
|
15619
16169
|
pm_node_destroy(parser, node);
|
@@ -15627,14 +16177,11 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15627
16177
|
// receiver that could have been a local variable) then we
|
15628
16178
|
// will transform it into a local variable write.
|
15629
16179
|
if (pm_call_node_variable_call_p(cast)) {
|
15630
|
-
pm_location_t message_loc = cast->message_loc;
|
15631
|
-
|
16180
|
+
pm_location_t *message_loc = &cast->message_loc;
|
16181
|
+
pm_refute_numbered_parameter(parser, message_loc->start, message_loc->end);
|
15632
16182
|
|
15633
|
-
|
15634
|
-
|
15635
|
-
}
|
15636
|
-
|
15637
|
-
pm_node_t *value = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16183
|
+
pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc->start, message_loc->end);
|
16184
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
15638
16185
|
pm_node_t *result = (pm_node_t *) pm_local_variable_or_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0);
|
15639
16186
|
|
15640
16187
|
pm_node_destroy(parser, (pm_node_t *) cast);
|
@@ -15645,7 +16192,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15645
16192
|
// this is an aref expression, and we can transform it into
|
15646
16193
|
// an aset expression.
|
15647
16194
|
if (pm_call_node_index_p(cast)) {
|
15648
|
-
pm_node_t *value =
|
16195
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
15649
16196
|
return (pm_node_t *) pm_index_or_write_node_create(parser, cast, &token, value);
|
15650
16197
|
}
|
15651
16198
|
|
@@ -15657,7 +16204,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15657
16204
|
}
|
15658
16205
|
|
15659
16206
|
parse_call_operator_write(parser, cast, &token);
|
15660
|
-
pm_node_t *value =
|
16207
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
15661
16208
|
return (pm_node_t *) pm_call_or_write_node_create(parser, cast, &token, value);
|
15662
16209
|
}
|
15663
16210
|
case PM_MULTI_WRITE_NODE: {
|
@@ -15694,7 +16241,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15694
16241
|
case PM_GLOBAL_VARIABLE_READ_NODE: {
|
15695
16242
|
parser_lex(parser);
|
15696
16243
|
|
15697
|
-
pm_node_t *value =
|
16244
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
15698
16245
|
pm_node_t *result = (pm_node_t *) pm_global_variable_operator_write_node_create(parser, node, &token, value);
|
15699
16246
|
|
15700
16247
|
pm_node_destroy(parser, node);
|
@@ -15703,7 +16250,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15703
16250
|
case PM_CLASS_VARIABLE_READ_NODE: {
|
15704
16251
|
parser_lex(parser);
|
15705
16252
|
|
15706
|
-
pm_node_t *value =
|
16253
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
15707
16254
|
pm_node_t *result = (pm_node_t *) pm_class_variable_operator_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value);
|
15708
16255
|
|
15709
16256
|
pm_node_destroy(parser, node);
|
@@ -15712,13 +16259,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15712
16259
|
case PM_CONSTANT_PATH_NODE: {
|
15713
16260
|
parser_lex(parser);
|
15714
16261
|
|
15715
|
-
pm_node_t *value =
|
16262
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
15716
16263
|
return (pm_node_t *) pm_constant_path_operator_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
|
15717
16264
|
}
|
15718
16265
|
case PM_CONSTANT_READ_NODE: {
|
15719
16266
|
parser_lex(parser);
|
15720
16267
|
|
15721
|
-
pm_node_t *value =
|
16268
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
15722
16269
|
pm_node_t *result = (pm_node_t *) pm_constant_operator_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
|
15723
16270
|
|
15724
16271
|
pm_node_destroy(parser, node);
|
@@ -15727,7 +16274,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15727
16274
|
case PM_INSTANCE_VARIABLE_READ_NODE: {
|
15728
16275
|
parser_lex(parser);
|
15729
16276
|
|
15730
|
-
pm_node_t *value =
|
16277
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
15731
16278
|
pm_node_t *result = (pm_node_t *) pm_instance_variable_operator_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value);
|
15732
16279
|
|
15733
16280
|
pm_node_destroy(parser, node);
|
@@ -15737,7 +16284,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15737
16284
|
pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node;
|
15738
16285
|
parser_lex(parser);
|
15739
16286
|
|
15740
|
-
pm_node_t *value =
|
16287
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
15741
16288
|
pm_node_t *result = (pm_node_t *) pm_local_variable_operator_write_node_create(parser, node, &token, value, cast->name, cast->depth);
|
15742
16289
|
|
15743
16290
|
pm_node_destroy(parser, node);
|
@@ -15751,14 +16298,11 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15751
16298
|
// receiver that could have been a local variable) then we
|
15752
16299
|
// will transform it into a local variable write.
|
15753
16300
|
if (pm_call_node_variable_call_p(cast)) {
|
15754
|
-
pm_location_t message_loc = cast->message_loc;
|
15755
|
-
|
16301
|
+
pm_location_t *message_loc = &cast->message_loc;
|
16302
|
+
pm_refute_numbered_parameter(parser, message_loc->start, message_loc->end);
|
15756
16303
|
|
15757
|
-
|
15758
|
-
|
15759
|
-
}
|
15760
|
-
|
15761
|
-
pm_node_t *value = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16304
|
+
pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc->start, message_loc->end);
|
16305
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
15762
16306
|
pm_node_t *result = (pm_node_t *) pm_local_variable_operator_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0);
|
15763
16307
|
|
15764
16308
|
pm_node_destroy(parser, (pm_node_t *) cast);
|
@@ -15769,7 +16313,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15769
16313
|
// this is an aref expression, and we can transform it into
|
15770
16314
|
// an aset expression.
|
15771
16315
|
if (pm_call_node_index_p(cast)) {
|
15772
|
-
pm_node_t *value =
|
16316
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
15773
16317
|
return (pm_node_t *) pm_index_operator_write_node_create(parser, cast, &token, value);
|
15774
16318
|
}
|
15775
16319
|
|
@@ -15781,7 +16325,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15781
16325
|
}
|
15782
16326
|
|
15783
16327
|
parse_call_operator_write(parser, cast, &token);
|
15784
|
-
pm_node_t *value =
|
16328
|
+
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
15785
16329
|
return (pm_node_t *) pm_call_operator_write_node_create(parser, cast, &token, value);
|
15786
16330
|
}
|
15787
16331
|
case PM_MULTI_WRITE_NODE: {
|
@@ -15969,14 +16513,14 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15969
16513
|
pm_token_t keyword = parser->current;
|
15970
16514
|
parser_lex(parser);
|
15971
16515
|
|
15972
|
-
pm_node_t *predicate =
|
16516
|
+
pm_node_t *predicate = parse_value_expression(parser, binding_power, PM_ERR_CONDITIONAL_IF_PREDICATE);
|
15973
16517
|
return (pm_node_t *) pm_if_node_modifier_create(parser, node, &keyword, predicate);
|
15974
16518
|
}
|
15975
16519
|
case PM_TOKEN_KEYWORD_UNLESS_MODIFIER: {
|
15976
16520
|
pm_token_t keyword = parser->current;
|
15977
16521
|
parser_lex(parser);
|
15978
16522
|
|
15979
|
-
pm_node_t *predicate =
|
16523
|
+
pm_node_t *predicate = parse_value_expression(parser, binding_power, PM_ERR_CONDITIONAL_UNLESS_PREDICATE);
|
15980
16524
|
return (pm_node_t *) pm_unless_node_modifier_create(parser, node, &keyword, predicate);
|
15981
16525
|
}
|
15982
16526
|
case PM_TOKEN_KEYWORD_UNTIL_MODIFIER: {
|
@@ -15984,7 +16528,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15984
16528
|
pm_statements_node_t *statements = pm_statements_node_create(parser);
|
15985
16529
|
pm_statements_node_body_append(statements, node);
|
15986
16530
|
|
15987
|
-
pm_node_t *predicate =
|
16531
|
+
pm_node_t *predicate = parse_value_expression(parser, binding_power, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
|
15988
16532
|
return (pm_node_t *) pm_until_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0);
|
15989
16533
|
}
|
15990
16534
|
case PM_TOKEN_KEYWORD_WHILE_MODIFIER: {
|
@@ -15992,10 +16536,11 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15992
16536
|
pm_statements_node_t *statements = pm_statements_node_create(parser);
|
15993
16537
|
pm_statements_node_body_append(statements, node);
|
15994
16538
|
|
15995
|
-
pm_node_t *predicate =
|
16539
|
+
pm_node_t *predicate = parse_value_expression(parser, binding_power, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
|
15996
16540
|
return (pm_node_t *) pm_while_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0);
|
15997
16541
|
}
|
15998
16542
|
case PM_TOKEN_QUESTION_MARK: {
|
16543
|
+
pm_token_t qmark = parser->current;
|
15999
16544
|
parser_lex(parser);
|
16000
16545
|
pm_node_t *true_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_TERNARY_EXPRESSION_TRUE);
|
16001
16546
|
|
@@ -16009,7 +16554,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16009
16554
|
pm_token_t colon = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
|
16010
16555
|
pm_node_t *false_expression = (pm_node_t *) pm_missing_node_create(parser, colon.start, colon.end);
|
16011
16556
|
|
16012
|
-
return (pm_node_t *) pm_if_node_ternary_create(parser, node, true_expression, &colon, false_expression);
|
16557
|
+
return (pm_node_t *) pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression);
|
16013
16558
|
}
|
16014
16559
|
|
16015
16560
|
accept1(parser, PM_TOKEN_NEWLINE);
|
@@ -16018,7 +16563,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16018
16563
|
pm_token_t colon = parser->previous;
|
16019
16564
|
pm_node_t *false_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_TERNARY_EXPRESSION_FALSE);
|
16020
16565
|
|
16021
|
-
return (pm_node_t *) pm_if_node_ternary_create(parser, node, true_expression, &colon, false_expression);
|
16566
|
+
return (pm_node_t *) pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression);
|
16022
16567
|
}
|
16023
16568
|
case PM_TOKEN_COLON_COLON: {
|
16024
16569
|
parser_lex(parser);
|
@@ -16212,6 +16757,12 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, pm_diagn
|
|
16212
16757
|
current_binding_powers.binary
|
16213
16758
|
) {
|
16214
16759
|
node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right);
|
16760
|
+
if (
|
16761
|
+
current_binding_powers.nonassoc &&
|
16762
|
+
current_binding_powers.right <= pm_binding_powers[parser->current.type].left
|
16763
|
+
) {
|
16764
|
+
break;
|
16765
|
+
}
|
16215
16766
|
}
|
16216
16767
|
|
16217
16768
|
return node;
|