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