MCPcopy Create free account
hub / github.com/AnukarOP/claude-code-leaked / parseExpansionBody

Function parseExpansionBody

source code/utils/bash/bashParser.ts:2557–2807  ·  view source on GitHub ↗
(P: ParseState)

Source from the content-addressed store, hash-verified

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

Callers 1

parseDollarLikeFunction · 0.85

Calls 13

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

Tested by

no test coverage detected