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