@@ -12626,14 +12626,48 @@ parse_string_part(pm_parser_t *parser) {
1262612626 }
1262712627}
1262812628
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+ */
1262912661static pm_node_t *
1263012662parse_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;
1263212664
1263312665 if (lex_mode->mode != PM_LEX_STRING) {
1263412666 if (next_state != PM_LEX_STATE_NONE) lex_state_set(parser, next_state);
1263512667
1263612668 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);
1263712671 case PM_TOKEN_IDENTIFIER:
1263812672 case PM_TOKEN_CONSTANT:
1263912673 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
1264512679 case PM_CASE_KEYWORD:
1264612680 parser_lex(parser);
1264712681 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;
1265212682 default:
1265312683 expect2(parser, PM_TOKEN_IDENTIFIER, PM_TOKEN_METHOD_NAME, PM_ERR_SYMBOL_INVALID);
1265412684 break;
@@ -12764,8 +12794,11 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
1276412794static inline pm_node_t *
1276512795parse_undef_argument(pm_parser_t *parser) {
1276612796 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+ }
1276712801 case PM_CASE_KEYWORD:
12768- case PM_CASE_OPERATOR:
1276912802 case PM_TOKEN_CONSTANT:
1277012803 case PM_TOKEN_IDENTIFIER:
1277112804 case PM_TOKEN_METHOD_NAME: {
@@ -12799,16 +12832,17 @@ parse_undef_argument(pm_parser_t *parser) {
1279912832static inline pm_node_t *
1280012833parse_alias_argument(pm_parser_t *parser, bool first) {
1280112834 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+ }
1280312839 case PM_CASE_KEYWORD:
1280412840 case PM_TOKEN_CONSTANT:
1280512841 case PM_TOKEN_IDENTIFIER:
1280612842 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);
1281112844 parser_lex(parser);
12845+
1281212846 pm_token_t opening = not_provided(parser);
1281312847 pm_token_t closing = not_provided(parser);
1281412848 pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &parser->previous, &closing);
0 commit comments