Skip to content

Commit 20374ce

Browse files
committed
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 0aa2363 commit 20374ce

File tree

3 files changed

+96
-6
lines changed

3 files changed

+96
-6
lines changed

snapshots/case_in_in.txt

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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+
│ ├── equal_loc: ∅
21+
│ └── block: ∅
22+
├── conditions: (length: 1)
23+
│ └── @ InNode (location: (2,0)-(3,25))
24+
│ ├── flags: ∅
25+
│ ├── pattern:
26+
│ │ @ ArrayPatternNode (location: (2,3)-(2,10))
27+
│ │ ├── flags: ∅
28+
│ │ ├── constant: ∅
29+
│ │ ├── requireds: (length: 1)
30+
│ │ │ └── @ LocalVariableTargetNode (location: (2,4)-(2,9))
31+
│ │ │ ├── flags: ∅
32+
│ │ │ ├── name: :event
33+
│ │ │ └── depth: 0
34+
│ │ ├── rest: ∅
35+
│ │ ├── posts: (length: 0)
36+
│ │ ├── opening_loc: (2,3)-(2,4) = "["
37+
│ │ └── closing_loc: (2,9)-(2,10) = "]"
38+
│ ├── statements:
39+
│ │ @ StatementsNode (location: (3,2)-(3,25))
40+
│ │ ├── flags: ∅
41+
│ │ └── body: (length: 1)
42+
│ │ └── @ MatchPredicateNode (location: (3,2)-(3,25))
43+
│ │ ├── flags: newline
44+
│ │ ├── value:
45+
│ │ │ @ CallNode (location: (3,2)-(3,15))
46+
│ │ │ ├── flags: ∅
47+
│ │ │ ├── receiver:
48+
│ │ │ │ @ CallNode (location: (3,2)-(3,9))
49+
│ │ │ │ ├── flags: variable_call, ignore_visibility
50+
│ │ │ │ ├── receiver: ∅
51+
│ │ │ │ ├── call_operator_loc: ∅
52+
│ │ │ │ ├── name: :context
53+
│ │ │ │ ├── message_loc: (3,2)-(3,9) = "context"
54+
│ │ │ │ ├── opening_loc: ∅
55+
│ │ │ │ ├── arguments: ∅
56+
│ │ │ │ ├── closing_loc: ∅
57+
│ │ │ │ ├── equal_loc: ∅
58+
│ │ │ │ └── block: ∅
59+
│ │ │ ├── call_operator_loc: (3,9)-(3,10) = "."
60+
│ │ │ ├── name: :event
61+
│ │ │ ├── message_loc: (3,10)-(3,15) = "event"
62+
│ │ │ ├── opening_loc: ∅
63+
│ │ │ ├── arguments: ∅
64+
│ │ │ ├── closing_loc: ∅
65+
│ │ │ ├── equal_loc: ∅
66+
│ │ │ └── block: ∅
67+
│ │ ├── pattern:
68+
│ │ │ @ PinnedVariableNode (location: (3,19)-(3,25))
69+
│ │ │ ├── flags: ∅
70+
│ │ │ ├── variable:
71+
│ │ │ │ @ LocalVariableReadNode (location: (3,20)-(3,25))
72+
│ │ │ │ ├── flags: ∅
73+
│ │ │ │ ├── name: :event
74+
│ │ │ │ └── depth: 0
75+
│ │ │ └── operator_loc: (3,19)-(3,20) = "^"
76+
│ │ └── operator_loc: (3,16)-(3,18) = "in"
77+
│ ├── in_loc: (2,0)-(2,2) = "in"
78+
│ └── then_loc: ∅
79+
├── else_clause: ∅
80+
├── case_keyword_loc: (1,0)-(1,4) = "case"
81+
└── 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
@@ -21674,12 +21674,6 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
2167421674
) {
2167521675
node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, accepts_command_call, (uint16_t) (depth + 1));
2167621676

21677-
if (context_terminator(parser->current_context->context, &parser->current)) {
21678-
// If this token terminates the current context, then we need to
21679-
// stop parsing the expression, as it has become a statement.
21680-
return node;
21681-
}
21682-
2168321677
switch (PM_NODE_TYPE(node)) {
2168421678
case PM_MULTI_WRITE_NODE:
2168521679
// Multi-write nodes are statements, and cannot be followed by
@@ -21792,6 +21786,17 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
2179221786
break;
2179321787
}
2179421788
}
21789+
21790+
if (context_terminator(parser->current_context->context, &parser->current)) {
21791+
pm_binding_powers_t next_binding_powers = pm_binding_powers[parser->current.type];
21792+
if (
21793+
!next_binding_powers.binary ||
21794+
binding_power > next_binding_powers.left ||
21795+
(PM_NODE_TYPE_P(node, PM_CALL_NODE) && pm_call_node_command_p((pm_call_node_t *) node))
21796+
) {
21797+
return node;
21798+
}
21799+
}
2179521800
}
2179621801

2179721802
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)