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