MCPcopy Index your code
hub / github.com/claude-code-best/claude-code / parseExpansionBody

Function parseExpansionBody

src/utils/bash/bashParser.ts:2551–2801  ·  view source on GitHub ↗
(P: ParseState)

Source from the content-addressed store, hash-verified

2549}
2550
2551function parseExpansionBody(P: ParseState): TsNode[] {
2552 const out: TsNode[] = []
2553 skipBlanks(P.L)
2554 // Bizarre cases: ${#!} ${!#} ${!##} ${!# } ${!## } all emit empty (expansion)
2555 // — both # and ! become anonymous nodes when only combined with each other
2556 // and optional trailing space before }. Note ${!##/} does NOT match (has
2557 // content after), so it parses normally as (special_variable_name)(regex).
2558 {
2559 const c0 = peek(P.L)
2560 const c1 = peek(P.L, 1)
2561 if (c0 === '#' && c1 === '!' && peek(P.L, 2) === '}') {
2562 advance(P.L)
2563 advance(P.L)
2564 return out
2565 }
2566 if (c0 === '!' && c1 === '#') {
2567 // ${!#} ${!##} with optional trailing space then }
2568 let j = 2
2569 if (peek(P.L, j) === '#') j++
2570 if (peek(P.L, j) === ' ') j++
2571 if (peek(P.L, j) === '}') {
2572 while (j-- > 0) advance(P.L)
2573 return out
2574 }
2575 }
2576 }
2577 // Optional # prefix for length
2578 if (peek(P.L) === '#') {
2579 const s = P.L.b
2580 advance(P.L)
2581 out.push(mk(P, '#', s, P.L.b, []))
2582 }
2583 // Optional ! prefix for indirect expansion: ${!varname} ${!prefix*} ${!prefix@}
2584 // Only when followed by an identifier — ${!} alone is special var $!
2585 // Also = ~ prefixes (zsh-style ${=var} ${~var})
2586 const pc = peek(P.L)
2587 if (
2588 (pc === '!' || pc === '=' || pc === '~') &&
2589 (isIdentStart(peek(P.L, 1)) || isDigit(peek(P.L, 1)))
2590 ) {
2591 const s = P.L.b
2592 advance(P.L)
2593 out.push(mk(P, pc, s, P.L.b, []))
2594 }
2595 skipBlanks(P.L)
2596 // Variable name
2597 if (isIdentStart(peek(P.L))) {
2598 const s = P.L.b
2599 while (isIdentChar(peek(P.L))) advance(P.L)
2600 out.push(mk(P, 'variable_name', s, P.L.b, []))
2601 } else if (isDigit(peek(P.L))) {
2602 const s = P.L.b
2603 while (isDigit(peek(P.L))) advance(P.L)
2604 out.push(mk(P, 'variable_name', s, P.L.b, []))
2605 } else if (SPECIAL_VARS.has(peek(P.L))) {
2606 const s = P.L.b
2607 advance(P.L)
2608 out.push(mk(P, 'special_variable_name', s, P.L.b, []))

Callers 1

parseDollarLikeFunction · 0.85

Calls 14

skipBlanksFunction · 0.85
advanceFunction · 0.85
isIdentStartFunction · 0.85
isDigitFunction · 0.85
isIdentCharFunction · 0.85
parseArithExprFunction · 0.85
parseDoubleQuotedFunction · 0.85
parseExpansionRestFunction · 0.85
peekFunction · 0.70
mkFunction · 0.70

Tested by

no test coverage detected