(P: ParseState, forTok: Token)
| 3198 | } |
| 3199 | |
| 3200 | function parseFor(P: ParseState, forTok: Token): TsNode { |
| 3201 | const forKw = leaf(P, forTok.value, forTok) |
| 3202 | skipBlanks(P.L) |
| 3203 | // C-style for (( ; ; )) — only for `for`, not `select` |
| 3204 | if (forTok.value === 'for' && peek(P.L) === '(' && peek(P.L, 1) === '(') { |
| 3205 | const oStart = P.L.b |
| 3206 | advance(P.L) |
| 3207 | advance(P.L) |
| 3208 | const open = mk(P, '((', oStart, P.L.b, []) |
| 3209 | const kids: TsNode[] = [forKw, open] |
| 3210 | // init; cond; update — all three use 'assign' mode so `c = expr` emits |
| 3211 | // variable_assignment, while bare idents (c in `c<=5`) → word. Each |
| 3212 | // clause may be a comma-separated list. |
| 3213 | for (let k = 0; k < 3; k++) { |
| 3214 | skipBlanks(P.L) |
| 3215 | const es = parseArithCommaList(P, k < 2 ? ';' : '))', 'assign') |
| 3216 | kids.push(...es) |
| 3217 | if (k < 2) { |
| 3218 | if (peek(P.L) === ';') { |
| 3219 | const s = P.L.b |
| 3220 | advance(P.L) |
| 3221 | kids.push(mk(P, ';', s, P.L.b, [])) |
| 3222 | } |
| 3223 | } |
| 3224 | } |
| 3225 | skipBlanks(P.L) |
| 3226 | if (peek(P.L) === ')' && peek(P.L, 1) === ')') { |
| 3227 | const cStart = P.L.b |
| 3228 | advance(P.L) |
| 3229 | advance(P.L) |
| 3230 | kids.push(mk(P, '))', cStart, P.L.b, [])) |
| 3231 | } |
| 3232 | // Optional ; or newline |
| 3233 | const save = saveLex(P.L) |
| 3234 | const sep = nextToken(P.L, 'cmd') |
| 3235 | if (sep.type === 'OP' && sep.value === ';') { |
| 3236 | kids.push(leaf(P, ';', sep)) |
| 3237 | } else if (sep.type !== 'NEWLINE') { |
| 3238 | restoreLex(P.L, save) |
| 3239 | } |
| 3240 | const dg = parseDoGroup(P) |
| 3241 | if (dg) { |
| 3242 | kids.push(dg) |
| 3243 | } else { |
| 3244 | // C-style for can also use `{ ... }` body instead of `do ... done` |
| 3245 | skipNewlines(P) |
| 3246 | skipBlanks(P.L) |
| 3247 | if (peek(P.L) === '{') { |
| 3248 | const bOpen = P.L.b |
| 3249 | advance(P.L) |
| 3250 | const brace = mk(P, '{', bOpen, P.L.b, []) |
| 3251 | const body = parseStatements(P, '}') |
| 3252 | let bClose: TsNode |
| 3253 | if (peek(P.L) === '}') { |
| 3254 | const cs = P.L.b |
| 3255 | advance(P.L) |
| 3256 | bClose = mk(P, '}', cs, P.L.b, []) |
| 3257 | } else { |
no test coverage detected