* Parse subscript index content. Parsed arithmetically per tree-sitter grammar: * `${a[1+2]}` → binary_expression; `${a[++i]}` → unary_expression(word); * `${a[(($n+1))]}` → compound_statement(binary_expression). Falls back to * simple patterns (@, *) as word.
(P: ParseState)
| 1525 | * simple patterns (@, *) as word. |
| 1526 | */ |
| 1527 | function parseSubscriptIndexInline(P: ParseState): TsNode | null { |
| 1528 | skipBlanks(P.L) |
| 1529 | const c = peek(P.L) |
| 1530 | // @ or * alone → word (associative array all-keys) |
| 1531 | if ((c === '@' || c === '*') && peek(P.L, 1) === ']') { |
| 1532 | const s = P.L.b |
| 1533 | advance(P.L) |
| 1534 | return mk(P, 'word', s, P.L.b, []) |
| 1535 | } |
| 1536 | // ((expr)) → compound_statement wrapping the inner arithmetic |
| 1537 | if (c === '(' && peek(P.L, 1) === '(') { |
| 1538 | const oStart = P.L.b |
| 1539 | advance(P.L) |
| 1540 | advance(P.L) |
| 1541 | const open = mk(P, '((', oStart, P.L.b, []) |
| 1542 | const inner = parseArithExpr(P, '))', 'var') |
| 1543 | skipBlanks(P.L) |
| 1544 | let close: TsNode |
| 1545 | if (peek(P.L) === ')' && peek(P.L, 1) === ')') { |
| 1546 | const cs = P.L.b |
| 1547 | advance(P.L) |
| 1548 | advance(P.L) |
| 1549 | close = mk(P, '))', cs, P.L.b, []) |
| 1550 | } else { |
| 1551 | close = mk(P, '))', P.L.b, P.L.b, []) |
| 1552 | } |
| 1553 | const kids = inner ? [open, inner, close] : [open, close] |
| 1554 | return mk(P, 'compound_statement', open.startIndex, close.endIndex, kids) |
| 1555 | } |
| 1556 | // Arithmetic — but bare identifiers in subscript use 'word' mode per |
| 1557 | // tree-sitter (${words[++counter]} → unary_expression(word)). |
| 1558 | return parseArithExpr(P, ']', 'word') |
| 1559 | } |
| 1560 | |
| 1561 | /** Legacy byte-range subscript index parser — kept for callers that pre-scan. */ |
| 1562 | function parseSubscriptIndex( |
no test coverage detected