@@ -12626,14 +12626,48 @@ parse_string_part(pm_parser_t *parser) {
12626
12626
}
12627
12627
}
12628
12628
12629
+ /**
12630
+ * When creating a symbol, unary operators that cannot be binary operators
12631
+ * automatically drop trailing `@` characters. This happens at the parser level,
12632
+ * such that `~@` is parsed as `~` and `!@` is parsed as `!`. We do that here.
12633
+ */
12634
+ static pm_node_t *
12635
+ parse_operator_symbol(pm_parser_t *parser, const pm_token_t *opening, pm_lex_state_t next_state) {
12636
+ pm_token_t closing = not_provided(parser);
12637
+ pm_symbol_node_t *symbol = pm_symbol_node_create(parser, opening, &parser->current, &closing);
12638
+
12639
+ const uint8_t *end = parser->current.end;
12640
+ switch (parser->current.type) {
12641
+ case PM_TOKEN_TILDE:
12642
+ case PM_TOKEN_BANG:
12643
+ if (parser->current.end[-1] == '@') end--;
12644
+ break;
12645
+ default:
12646
+ break;
12647
+ }
12648
+
12649
+ if (next_state != PM_LEX_STATE_NONE) lex_state_set(parser, next_state);
12650
+ parser_lex(parser);
12651
+
12652
+ pm_string_shared_init(&symbol->unescaped, parser->previous.start, end);
12653
+ return (pm_node_t *) symbol;
12654
+ }
12655
+
12656
+ /**
12657
+ * Parse a symbol node. This function will get called immediately after finding
12658
+ * a symbol opening token. This handles parsing bare symbols and interpolated
12659
+ * symbols.
12660
+ */
12629
12661
static pm_node_t *
12630
12662
parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_state) {
12631
- pm_token_t opening = parser->previous;
12663
+ const pm_token_t opening = parser->previous;
12632
12664
12633
12665
if (lex_mode->mode != PM_LEX_STRING) {
12634
12666
if (next_state != PM_LEX_STATE_NONE) lex_state_set(parser, next_state);
12635
12667
12636
12668
switch (parser->current.type) {
12669
+ case PM_CASE_OPERATOR:
12670
+ return parse_operator_symbol(parser, &opening, next_state == PM_LEX_STATE_NONE ? PM_LEX_STATE_ENDFN : next_state);
12637
12671
case PM_TOKEN_IDENTIFIER:
12638
12672
case PM_TOKEN_CONSTANT:
12639
12673
case PM_TOKEN_INSTANCE_VARIABLE:
@@ -12645,10 +12679,6 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
12645
12679
case PM_CASE_KEYWORD:
12646
12680
parser_lex(parser);
12647
12681
break;
12648
- case PM_CASE_OPERATOR:
12649
- lex_state_set(parser, next_state == PM_LEX_STATE_NONE ? PM_LEX_STATE_ENDFN : next_state);
12650
- parser_lex(parser);
12651
- break;
12652
12682
default:
12653
12683
expect2(parser, PM_TOKEN_IDENTIFIER, PM_TOKEN_METHOD_NAME, PM_ERR_SYMBOL_INVALID);
12654
12684
break;
@@ -12764,8 +12794,11 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
12764
12794
static inline pm_node_t *
12765
12795
parse_undef_argument(pm_parser_t *parser) {
12766
12796
switch (parser->current.type) {
12797
+ case PM_CASE_OPERATOR: {
12798
+ const pm_token_t opening = not_provided(parser);
12799
+ return parse_operator_symbol(parser, &opening, PM_LEX_STATE_NONE);
12800
+ }
12767
12801
case PM_CASE_KEYWORD:
12768
- case PM_CASE_OPERATOR:
12769
12802
case PM_TOKEN_CONSTANT:
12770
12803
case PM_TOKEN_IDENTIFIER:
12771
12804
case PM_TOKEN_METHOD_NAME: {
@@ -12799,16 +12832,17 @@ parse_undef_argument(pm_parser_t *parser) {
12799
12832
static inline pm_node_t *
12800
12833
parse_alias_argument(pm_parser_t *parser, bool first) {
12801
12834
switch (parser->current.type) {
12802
- case PM_CASE_OPERATOR:
12835
+ case PM_CASE_OPERATOR: {
12836
+ const pm_token_t opening = not_provided(parser);
12837
+ return parse_operator_symbol(parser, &opening, first ? PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM : PM_LEX_STATE_NONE);
12838
+ }
12803
12839
case PM_CASE_KEYWORD:
12804
12840
case PM_TOKEN_CONSTANT:
12805
12841
case PM_TOKEN_IDENTIFIER:
12806
12842
case PM_TOKEN_METHOD_NAME: {
12807
- if (first) {
12808
- lex_state_set(parser, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM);
12809
- }
12810
-
12843
+ if (first) lex_state_set(parser, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM);
12811
12844
parser_lex(parser);
12845
+
12812
12846
pm_token_t opening = not_provided(parser);
12813
12847
pm_token_t closing = not_provided(parser);
12814
12848
pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &parser->previous, &closing);
0 commit comments