1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! The code-ground control-flow layer: `if`/`else`, `while`, `for … in …`,
//! `until`.
//!
//! B0.8 Wave B (`docs/decision-log.md` 2026-07-23 "Code-ground sitting",
//! issue #1177). Rides Wave A's statement infrastructure verbatim —
//! `parser/stmt.rs`'s `statement()` dispatcher gains the four branches
//! below, and every construct's body reuses `stmt::stmt_block` unchanged
//! (no second block shape for control-flow bodies). Mirrors
//! `brink-syntax`'s `~ { … }` T1b grammar (`parser/logic.rs`'s
//! `if_stmt`/`while_stmt`/`for_stmt`) structurally — that grammar is this
//! one's differential partner (`crates/internal/brink-ir/tests/
//! b08_native_control_flow.rs`) — with one difference: native hard-reserves
//! `if`/`while`/`for`/`in`/`until` as real lexer keywords (`syntax_kind.rs`
//! Finding #1's "`RustScript` reserves globally" posture), where the
//! brink-dialect treats them as contextual soft keywords matched by IDENT
//! text. `until` has no brink-dialect counterpart at all — it is native's
//! sole condition-park spelling, retiring `await` (decision-log item 4).
use crate;
use Parser;
/// Parse a control-flow *head* expression — one directly followed by a `{`
/// that opens the construct's body, so a trailing `TypeName { … }`
/// construction literal (B5, issue #1464) must not swallow that brace.
/// Rust's `no-struct-literal` restriction is the precedent; `(…)` restores
/// the literal form (`while (Weighted { 1: a }) == w { … }`).
/// `if cond (as name)? { … } (else if cond { … } | else { … })?` — the
/// optional `as` binding is B1b (issue #1475, `parser/binding.rs`), scoped
/// strictly to the success arm, so an `else`/`else if` arm never sees it.
pub
/// `else if cond { … }` (a chained `IF_STMT`, no `STMT_BLOCK` wrapper of
/// its own — mirrors `family.rs::else_branch`'s flat-chain precedent) or
/// `else { … }`.
/// `while cond (as name)? { … }`. Always a plain loop — native has no
/// `await` keyword to spell a persistent-await variant with (see module
/// doc).
pub
/// `for name in expr { … }` — single-binding iteration — or `for key, val
/// in expr { … }` — two-binding iteration (B2, issue #1461,
/// docs/stdlib-spec.md §5/§9's F10 ruling: "`for k, v in m` two-binding
/// iteration ... no pair shape ever materializes"). The second binding is
/// the one additive HIR field the B0 fence reserved (`val_name`,
/// docs/b0-sequencing.md:356) — no new node, no destructuring beyond the
/// flat `name, name` pair.
pub
/// `until <cond>;` — the condition-park statement (decision-log item 4).
/// Always `;`-terminated, like every other code-ground statement
/// (`stmt.rs`'s `let_stmt`/`assign_stmt` precedent) — it has no body of its
/// own to delimit it, unlike `if`/`while`/`for`.
pub