diff --git a/src/parser.zig b/src/parser.zig index caed4b8..f59cec2 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -1270,6 +1270,13 @@ pub const Parser = struct { return tok.tag; } + /// With `self.current` at `(`, true iff the parens enclose exactly a single + /// identifier — `( ident )`. Distinguishes a match-arm payload capture from + /// a parenthesized / tuple arm-value expression (`(5)`, `(a, b)`). + fn isLoneIdentParen(self: *Parser) bool { + return self.peekTag(1) == .identifier and self.peekTag(2) == .r_paren; + } + fn foreignRuntimeForOffset(self: *Parser, offset: usize) ?ast.ForeignRuntime { const tag = self.peekTag(offset); return switch (tag) { @@ -3093,13 +3100,15 @@ pub const Parser = struct { } else try self.parsePrimary(); // .variant try self.expect(.colon); - // Optional payload capture: (ident) + // Optional payload capture: `(ident)`. Disambiguated from a + // parenthesized / tuple arm-value expression (`(5)`, `(1, 1)`): + // a capture is exactly `( )`; anything else is the + // arm body (an expression) and is left for the body parse below. var capture: ?[]const u8 = null; - if (self.current.tag == .l_paren) { - self.advance(); - if (self.current.tag != .identifier) return self.fail("expected capture name"); + if (self.current.tag == .l_paren and self.isLoneIdentParen()) { + self.advance(); // '(' capture = self.tokenSlice(self.current); - self.advance(); + self.advance(); // ident try self.expect(.r_paren); }