Skip to content

Commit bc56e51

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.
1 parent f741032 commit bc56e51

3 files changed

Lines changed: 96 additions & 6 deletions

File tree

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
@@ -21652,12 +21652,6 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
2165221652
) {
2165321653
node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, accepts_command_call, (uint16_t) (depth + 1));
2165421654

21655-
if (context_terminator(parser->current_context->context, &parser->current)) {
21656-
// If this token terminates the current context, then we need to
21657-
// stop parsing the expression, as it has become a statement.
21658-
return node;
21659-
}
21660-
2166121655
switch (PM_NODE_TYPE(node)) {
2166221656
case PM_MULTI_WRITE_NODE:
2166321657
// Multi-write nodes are statements, and cannot be followed by
@@ -21770,6 +21764,17 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
2177021764
break;
2177121765
}
2177221766
}
21767+
21768+
if (context_terminator(parser->current_context->context, &parser->current)) {
21769+
pm_binding_powers_t next_binding_powers = pm_binding_powers[parser->current.type];
21770+
if (
21771+
!next_binding_powers.binary ||
21772+
binding_power > next_binding_powers.left ||
21773+
(PM_NODE_TYPE_P(node, PM_CALL_NODE) && pm_call_node_command_p((pm_call_node_t *) node))
21774+
) {
21775+
return node;
21776+
}
21777+
}
2177321778
}
2177421779

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