while loops

This commit is contained in:
2026-06-21 23:26:11 +02:00
parent f4194492cc
commit 380b5943b3
12 changed files with 548 additions and 16 deletions
+93
View File
@@ -928,6 +928,9 @@ parse_statement :: proc(parser: ^Parser) -> ast.Stmt_Id {
if current(parser).kind == .Keyword_If {
return parse_if(parser)
}
if current(parser).kind == .Keyword_While {
return parse_while(parser)
}
if current(parser).kind == .Identifier || current(parser).kind == .Underscore {
start_cursor := parser.cursor
@@ -1123,6 +1126,96 @@ parse_if :: proc(parser: ^Parser) -> ast.Stmt_Id {
return id
}
parse_while_update :: proc(parser: ^Parser) -> ast.Stmt_Id {
parenthesized := false
if _, ok := allow(parser, .Left_Paren); ok {
parenthesized = true
parser.delimiter_depth += 1
skip_newlines(parser)
}
update := ast.INVALID_STMT
if current(parser).kind == .Left_Brace ||
current(parser).kind == .Right_Paren ||
current(parser).kind == .Eof {
diagnostic := source.add(
parser.diagnostics,
current(parser).span,
"expected a while update statement after ':'",
)
update = ast.stmt_id(len(parser.module.statements))
append(&parser.module.statements, ast.Stmt{
kind=.Invalid,
span=current(parser).span,
expr=ast.INVALID_EXPR,
update=ast.INVALID_STMT,
diagnostic=diagnostic,
})
} else {
saved := parser.no_struct_literal
parser.no_struct_literal = true
update = parse_statement(parser)
parser.no_struct_literal = saved
statement := &parser.module.statements[update]
switch statement.kind {
case .Assignment, .Expression:
case .Invalid, .Declaration, .Return, .If, .While:
diagnostic := source.add(
parser.diagnostics,
statement.span,
"while update must be an assignment, sink, or expression statement",
)
statement.kind = .Invalid
statement.diagnostic = diagnostic
}
}
if parenthesized {
skip_newlines(parser)
if _, ok := allow(parser, .Right_Paren); !ok {
source.add(parser.diagnostics, current(parser).span, "expected ')' after while update")
for current(parser).kind != .Right_Paren &&
current(parser).kind != .Left_Brace &&
current(parser).kind != .Newline &&
current(parser).kind != .Eof {
advance(parser)
}
_, _ = allow(parser, .Right_Paren)
}
parser.delimiter_depth -= 1
}
return update
}
parse_while :: proc(parser: ^Parser) -> ast.Stmt_Id {
start := advance(parser) // consume 'while'
skip_newlines(parser)
saved := parser.no_struct_literal
parser.no_struct_literal = true
condition := parse_expression(parser)
parser.no_struct_literal = saved
skip_newlines(parser)
update := ast.INVALID_STMT
if _, ok := allow(parser, .Colon); ok {
skip_newlines(parser)
update = parse_while_update(parser)
skip_newlines(parser)
}
body := parse_block(parser)
id := ast.stmt_id(len(parser.module.statements))
append(&parser.module.statements, ast.Stmt{
kind=.While,
span=span_from(start.span, previous(parser).span),
expr=condition,
body=body,
update=update,
diagnostic=source.INVALID_DIAGNOSTIC,
})
return id
}
parse_function :: proc(parser: ^Parser, name: token.Token, c_abi: bool) {
advance(parser)
if _, ok := allow(parser, .Left_Paren); !ok {