(P: ParseState)
| 2429 | } |
| 2430 | |
| 2431 | function parseDollarLike(P: ParseState): TsNode | null { |
| 2432 | const c1 = peek(P.L, 1) |
| 2433 | const dStart = P.L.b |
| 2434 | if (c1 === '(' && peek(P.L, 2) === '(') { |
| 2435 | // $(( arithmetic )) |
| 2436 | advance(P.L) |
| 2437 | advance(P.L) |
| 2438 | advance(P.L) |
| 2439 | const open = mk(P, '$((', dStart, P.L.b, []) |
| 2440 | const exprs = parseArithCommaList(P, '))', 'var') |
| 2441 | skipBlanks(P.L) |
| 2442 | let close: TsNode |
| 2443 | if (peek(P.L) === ')' && peek(P.L, 1) === ')') { |
| 2444 | const cStart = P.L.b |
| 2445 | advance(P.L) |
| 2446 | advance(P.L) |
| 2447 | close = mk(P, '))', cStart, P.L.b, []) |
| 2448 | } else { |
| 2449 | close = mk(P, '))', P.L.b, P.L.b, []) |
| 2450 | } |
| 2451 | return mk(P, 'arithmetic_expansion', dStart, close.endIndex, [ |
| 2452 | open, |
| 2453 | ...exprs, |
| 2454 | close, |
| 2455 | ]) |
| 2456 | } |
| 2457 | if (c1 === '[') { |
| 2458 | // $[ arithmetic ] — legacy bash syntax, same as $((...)) |
| 2459 | advance(P.L) |
| 2460 | advance(P.L) |
| 2461 | const open = mk(P, '$[', dStart, P.L.b, []) |
| 2462 | const exprs = parseArithCommaList(P, ']', 'var') |
| 2463 | skipBlanks(P.L) |
| 2464 | let close: TsNode |
| 2465 | if (peek(P.L) === ']') { |
| 2466 | const cStart = P.L.b |
| 2467 | advance(P.L) |
| 2468 | close = mk(P, ']', cStart, P.L.b, []) |
| 2469 | } else { |
| 2470 | close = mk(P, ']', P.L.b, P.L.b, []) |
| 2471 | } |
| 2472 | return mk(P, 'arithmetic_expansion', dStart, close.endIndex, [ |
| 2473 | open, |
| 2474 | ...exprs, |
| 2475 | close, |
| 2476 | ]) |
| 2477 | } |
| 2478 | if (c1 === '(') { |
| 2479 | advance(P.L) |
| 2480 | advance(P.L) |
| 2481 | const open = mk(P, '$(', dStart, P.L.b, []) |
| 2482 | let body = parseStatements(P, ')') |
| 2483 | skipBlanks(P.L) |
| 2484 | let close: TsNode |
| 2485 | if (peek(P.L) === ')') { |
| 2486 | const cStart = P.L.b |
| 2487 | advance(P.L) |
| 2488 | close = mk(P, ')', cStart, P.L.b, []) |
no test coverage detected