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>
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user