Skip to content

Commit ff334c4

Browse files
kddnewtonEarlopain
authored andcommitted
Fix in handling
in is a unique keyword because it can be the start of a clause or an infix keyword. We need to be explicitly sure that even though in _could_ close an expression context (the body of another in clause) that we are not also parsing an inline in. The exception is the case of a command call, which can never be the LHS of an expression, and so we must immediately exit. [Bug #21925] [Bug #21674]
1 parent 674ffbb commit ff334c4

3 files changed

Lines changed: 93 additions & 6 deletions

File tree

snapshots/case_in_in.txt

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
@ ProgramNode (location: (1,0)-(4,3))
2+
├── flags: ∅
3+
├── locals: [:event]
4+
└── statements:
5+
@ StatementsNode (location: (1,0)-(4,3))
6+
├── flags: ∅
7+
└── body: (length: 1)
8+
└── @ CaseMatchNode (location: (1,0)-(4,3))
9+
├── flags: newline
10+
├── predicate:
11+
│ @ CallNode (location: (1,5)-(1,9))
12+
│ ├── flags: variable_call, ignore_visibility
13+
│ ├── receiver: ∅
14+
│ ├── call_operator_loc: ∅
15+
│ ├── name: :args
16+
│ ├── message_loc: (1,5)-(1,9) = "args"
17+
│ ├── opening_loc: ∅
18+
│ ├── arguments: ∅
19+
│ ├── closing_loc: ∅
20+
│ └── block: ∅
21+
├── conditions: (length: 1)
22+
│ └── @ InNode (location: (2,0)-(3,25))
23+
│ ├── flags: ∅
24+
│ ├── pattern:
25+
│ │ @ ArrayPatternNode (location: (2,3)-(2,10))
26+
│ │ ├── flags: ∅
27+
│ │ ├── constant: ∅
28+
│ │ ├── requireds: (length: 1)
29+
│ │ │ └── @ LocalVariableTargetNode (location: (2,4)-(2,9))
30+
│ │ │ ├── flags: ∅
31+
│ │ │ ├── name: :event
32+
│ │ │ └── depth: 0
33+
│ │ ├── rest: ∅
34+
│ │ ├── posts: (length: 0)
35+
│ │ ├── opening_loc: (2,3)-(2,4) = "["
36+
│ │ └── closing_loc: (2,9)-(2,10) = "]"
37+
│ ├── statements:
38+
│ │ @ StatementsNode (location: (3,2)-(3,25))
39+
│ │ ├── flags: ∅
40+
│ │ └── body: (length: 1)
41+
│ │ └── @ MatchPredicateNode (location: (3,2)-(3,25))
42+
│ │ ├── flags: newline
43+
│ │ ├── value:
44+
│ │ │ @ CallNode (location: (3,2)-(3,15))
45+
│ │ │ ├── flags: ∅
46+
│ │ │ ├── receiver:
47+
│ │ │ │ @ CallNode (location: (3,2)-(3,9))
48+
│ │ │ │ ├── flags: variable_call, ignore_visibility
49+
│ │ │ │ ├── receiver: ∅
50+
│ │ │ │ ├── call_operator_loc: ∅
51+
│ │ │ │ ├── name: :context
52+
│ │ │ │ ├── message_loc: (3,2)-(3,9) = "context"
53+
│ │ │ │ ├── opening_loc: ∅
54+
│ │ │ │ ├── arguments: ∅
55+
│ │ │ │ ├── closing_loc: ∅
56+
│ │ │ │ └── block: ∅
57+
│ │ │ ├── call_operator_loc: (3,9)-(3,10) = "."
58+
│ │ │ ├── name: :event
59+
│ │ │ ├── message_loc: (3,10)-(3,15) = "event"
60+
│ │ │ ├── opening_loc: ∅
61+
│ │ │ ├── arguments: ∅
62+
│ │ │ ├── closing_loc: ∅
63+
│ │ │ └── block: ∅
64+
│ │ ├── pattern:
65+
│ │ │ @ PinnedVariableNode (location: (3,19)-(3,25))
66+
│ │ │ ├── flags: ∅
67+
│ │ │ ├── variable:
68+
│ │ │ │ @ LocalVariableReadNode (location: (3,20)-(3,25))
69+
│ │ │ │ ├── flags: ∅
70+
│ │ │ │ ├── name: :event
71+
│ │ │ │ └── depth: 0
72+
│ │ │ └── operator_loc: (3,19)-(3,20) = "^"
73+
│ │ └── operator_loc: (3,16)-(3,18) = "in"
74+
│ ├── in_loc: (2,0)-(2,2) = "in"
75+
│ └── then_loc: ∅
76+
├── else_clause: ∅
77+
├── case_keyword_loc: (1,0)-(1,4) = "case"
78+
└── end_keyword_loc: (4,0)-(4,3) = "end"

src/prism.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22339,12 +22339,6 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
2233922339
) {
2234022340
node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, accepts_command_call, (uint16_t) (depth + 1));
2234122341

22342-
if (context_terminator(parser->current_context->context, &parser->current)) {
22343-
// If this token terminates the current context, then we need to
22344-
// stop parsing the expression, as it has become a statement.
22345-
return node;
22346-
}
22347-
2234822342
switch (PM_NODE_TYPE(node)) {
2234922343
case PM_MULTI_WRITE_NODE:
2235022344
// Multi-write nodes are statements, and cannot be followed by
@@ -22457,6 +22451,17 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
2245722451
break;
2245822452
}
2245922453
}
22454+
22455+
if (context_terminator(parser->current_context->context, &parser->current)) {
22456+
pm_binding_powers_t next_binding_powers = pm_binding_powers[parser->current.type];
22457+
if (
22458+
!next_binding_powers.binary ||
22459+
binding_power > next_binding_powers.left ||
22460+
(PM_NODE_TYPE_P(node, PM_CALL_NODE) && pm_call_node_command_p((pm_call_node_t *) node))
22461+
) {
22462+
return node;
22463+
}
22464+
}
2246022465
}
2246122466

2246222467
return node;

test/prism/fixtures/case_in_in.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
case args
2+
in [event]
3+
context.event in ^event
4+
end

0 commit comments

Comments
 (0)