Skip to content

Commit d139af0

Browse files
committed
Unary symbols that cannot be binary should drop @
1 parent ced3b8d commit d139af0

File tree

2 files changed

+47
-13
lines changed

2 files changed

+47
-13
lines changed

src/prism.c

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
*/
1262912661
static pm_node_t *
1263012662
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;
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
1276412794
static inline pm_node_t *
1276512795
parse_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) {
1279912832
static inline pm_node_t *
1280012833
parse_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);

test/prism/snapshots/symbols.txt

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)