block labels
This commit is contained in:
@@ -1036,10 +1036,20 @@ parse_yield :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
// checker rejects them outside a loop.
|
||||
parse_loop_control :: proc(parser: ^Parser, kind: ast.Stmt_Kind) -> ast.Stmt_Id {
|
||||
marker := advance(parser) // consume 'break' / 'continue'
|
||||
// `break :outer` / `continue :outer` targets the enclosing loop labeled `outer`.
|
||||
label := symbol.INVALID
|
||||
if _, ok := allow(parser, .Colon); ok {
|
||||
if name, name_ok := allow(parser, .Identifier); name_ok {
|
||||
label = name.symbol
|
||||
} else {
|
||||
source.add(parser.diagnostics, current(parser).span, "expected a loop label after ':'")
|
||||
}
|
||||
}
|
||||
id := ast.stmt_id(len(parser.module.statements))
|
||||
append(&parser.module.statements, ast.Stmt{
|
||||
kind=kind,
|
||||
span=marker.span,
|
||||
label=label,
|
||||
expr=ast.INVALID_EXPR,
|
||||
update=ast.INVALID_STMT,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
@@ -1169,6 +1179,26 @@ parse_statement :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
kind = .Declaration
|
||||
immutable = operator.kind == .Colon_Colon
|
||||
}
|
||||
// A labeled value block (`x :: blk: { … yield :blk v }`): the label lets a
|
||||
// `yield :blk` exit the block past a nested `if`. Block-init body + label.
|
||||
if current(parser).kind == .Identifier && peek(parser).kind == .Colon {
|
||||
label := parse_optional_loop_label(parser)
|
||||
body := parse_block(parser)
|
||||
id := ast.stmt_id(len(parser.module.statements))
|
||||
append(&parser.module.statements, ast.Stmt{
|
||||
kind=kind,
|
||||
span=span_from(name.span, previous(parser).span),
|
||||
name=name.symbol,
|
||||
type=type_syntax,
|
||||
immutable=immutable,
|
||||
label=label,
|
||||
target=ast.INVALID_EXPR,
|
||||
expr=ast.INVALID_EXPR,
|
||||
body=body,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
return id
|
||||
}
|
||||
// A `{` on the right is a value block: parse its statements now; the
|
||||
// checker turns its final `yield` into the declared/assigned value.
|
||||
if current(parser).kind == .Left_Brace {
|
||||
@@ -1227,6 +1257,22 @@ parse_statement :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
expr := parse_expression(parser)
|
||||
if _, ok := allow(parser, .Equal); ok {
|
||||
skip_newlines(parser)
|
||||
// A labeled value block assigned to a complex target (`a[i] = blk: { … }`).
|
||||
if current(parser).kind == .Identifier && peek(parser).kind == .Colon {
|
||||
label := parse_optional_loop_label(parser)
|
||||
body := parse_block(parser)
|
||||
id := ast.stmt_id(len(parser.module.statements))
|
||||
append(&parser.module.statements, ast.Stmt{
|
||||
kind=.Assignment,
|
||||
span=span_from(parser.module.exprs[expr].span, previous(parser).span),
|
||||
target=expr,
|
||||
label=label,
|
||||
expr=ast.INVALID_EXPR,
|
||||
body=body,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
return id
|
||||
}
|
||||
// A value block assigned to a complex target (`a[i] = { ... }`, `p.f = { ... }`).
|
||||
if current(parser).kind == .Left_Brace {
|
||||
brace := current(parser)
|
||||
|
||||
Reference in New Issue
Block a user