zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 8095b097d29a3f0536c9cdf6307a8cc09ec2faab (tree)
parent 63e459fb66fa6e9e9d0d99908b4379083224b080
Author: Motiejus Jakštys <motiejus@jakstys.lt>
Date:   Sat, 14 Feb 2026 20:31:22 +0000

parser: add anyframe, labeled switch, fix inline fallthrough

- Implement anyframe and anyframe->T parsing in parseTypeExpr and
  parsePrimaryTypeExpr (was failing with unsupported error).
- Add labeled switch support: identifier:switch in parsePrimaryExpr
  and parsePrimaryTypeExpr, with main_token = switch_token - 2.
- Fix TOKEN_KEYWORD_INLINE fallthrough into TOKEN_PERIOD case in
  parsePrimaryTypeExpr; handle it separately expecting for/while.

Reduces corpus test failures from 20 to 7.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Diffstat:
Mstage0/parser.c | 48+++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 41 insertions(+), 7 deletions(-)

diff --git a/stage0/parser.c b/stage0/parser.c @@ -122,7 +122,7 @@ static void parsePtrPayload(Parser*); static AstNodeIndex parseSingleAssignExpr(Parser*); static AstNodeIndex parseSuffixExpr(Parser*); static AstNodeIndex parseSuffixOp(Parser*, AstNodeIndex); -static AstNodeIndex parseSwitchExpr(Parser*); +static AstNodeIndex parseSwitchExpr(Parser*, bool is_labeled); static AstNodeIndex parseSwitchItem(Parser*); static AstNodeIndex parseSwitchProng(Parser*); static AstSubRange parseSwitchProngList(Parser*); @@ -978,7 +978,7 @@ static AstNodeIndex parseLabeledStatement(Parser* p) { if (loop_stmt != 0) return loop_stmt; - const AstNodeIndex switch_expr = parseSwitchExpr(p); + const AstNodeIndex switch_expr = parseSwitchExpr(p, false); if (switch_expr != 0) return switch_expr; @@ -1571,7 +1571,20 @@ static AstNodeIndex parseTypeExpr(Parser* p) { .data = { .lhs = parseTypeExpr(p), .rhs = 0 }, }); case TOKEN_KEYWORD_ANYFRAME: - fail(p, "unsupported type expression"); + if (p->token_tags[p->tok_i + 1] == TOKEN_ARROW) { + const AstTokenIndex anyframe_tok = nextToken(p); + const AstTokenIndex arrow_tok = nextToken(p); + const AstNodeIndex return_type = parseTypeExpr(p); + if (return_type == 0) + fail(p, "expected type expression"); + return addNode(&p->nodes, + (AstNodeItem) { + .tag = AST_NODE_ANYFRAME_TYPE, + .main_token = anyframe_tok, + .data = { .lhs = arrow_tok, .rhs = return_type }, + }); + } + return parseErrorUnionExpr(p); case TOKEN_ASTERISK: { const AstTokenIndex asterisk = nextToken(p); const PtrModifiers mods = parsePtrModifiers(p); @@ -1889,6 +1902,9 @@ static AstNodeIndex parsePrimaryExpr(Parser* p) { case TOKEN_KEYWORD_WHILE: p->tok_i += 2; return parseWhileExpr(p); + case TOKEN_KEYWORD_SWITCH: + p->tok_i += 2; + return parseSwitchExpr(p, true); case TOKEN_L_BRACE: p->tok_i += 2; return parseBlock(p); @@ -2462,7 +2478,12 @@ static AstNodeIndex parsePrimaryTypeExpr(Parser* p) { .data = {}, }); case TOKEN_KEYWORD_ANYFRAME: - fail(p, "unsupported primary type expression"); + return addNode(&p->nodes, + (AstNodeItem) { + .tag = AST_NODE_ANYFRAME_LITERAL, + .main_token = nextToken(p), + .data = {}, + }); case TOKEN_STRING_LITERAL: return addNode(&p->nodes, (AstNodeItem) { @@ -2477,7 +2498,7 @@ static AstNodeIndex parsePrimaryTypeExpr(Parser* p) { case TOKEN_KEYWORD_IF: return parseIfExpr(p); case TOKEN_KEYWORD_SWITCH: - return parseSwitchExpr(p); + return parseSwitchExpr(p, false); case TOKEN_KEYWORD_EXTERN: case TOKEN_KEYWORD_PACKED: // extern/packed can precede struct/union/enum @@ -2527,6 +2548,9 @@ static AstNodeIndex parsePrimaryTypeExpr(Parser* p) { return parseLabeledStatement(p); case TOKEN_KEYWORD_FOR: return parseLabeledStatement(p); + case TOKEN_KEYWORD_SWITCH: + p->tok_i += 2; + return parseSwitchExpr(p, true); default: break; } @@ -2542,6 +2566,13 @@ static AstNodeIndex parsePrimaryTypeExpr(Parser* p) { case TOKEN_KEYWORD_WHILE: return parseWhileExpr(p); case TOKEN_KEYWORD_INLINE: + p->tok_i++; + if (p->token_tags[p->tok_i] == TOKEN_KEYWORD_FOR) + return parseForExpr(p); + if (p->token_tags[p->tok_i] == TOKEN_KEYWORD_WHILE) + return parseWhileExpr(p); + fail(p, "expected 'for' or 'while' after 'inline'"); + return 0; // tcc case TOKEN_PERIOD: switch (p->token_tags[p->tok_i + 1]) { case TOKEN_IDENTIFIER: { @@ -2623,11 +2654,14 @@ static AstNodeIndex parsePrimaryTypeExpr(Parser* p) { } } -static AstNodeIndex parseSwitchExpr(Parser* p) { +static AstNodeIndex parseSwitchExpr(Parser* p, bool is_labeled) { const AstTokenIndex switch_token = eatToken(p, TOKEN_KEYWORD_SWITCH); if (switch_token == null_token) return null_node; + const AstTokenIndex main_token + = is_labeled ? switch_token - 2 : switch_token; + expectToken(p, TOKEN_L_PAREN); const AstNodeIndex operand = expectExpr(p); expectToken(p, TOKEN_R_PAREN); @@ -2638,7 +2672,7 @@ static AstNodeIndex parseSwitchExpr(Parser* p) { return addNode(&p->nodes, (AstNodeItem) { .tag = comma ? AST_NODE_SWITCH_COMMA : AST_NODE_SWITCH, - .main_token = switch_token, + .main_token = main_token, .data = { .lhs = operand, .rhs = addExtra(p,