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

Function parseExpansionRest

src/utils/bash/bashParser.ts:2803–3027  ·  view source on GitHub ↗
(
  P: ParseState,
  nodeType: string,
  stopAtSlash: boolean,
)

Source from the content-addressed store, hash-verified

2801}
2802
2803function parseExpansionRest(
2804 P: ParseState,
2805 nodeType: string,
2806 stopAtSlash: boolean,
2807): TsNode | null {
2808 // Don't skipBlanks — `${var:- }` space IS the word. Stop at } or newline
2809 // (`${var:\n}` emits no word). stopAtSlash=true stops at `/` for pat/repl
2810 // split in ${var/pat/repl}. nodeType 'replword' is word-mode for the
2811 // replacement in `/` `//` — same as 'word' but `(` is NOT array.
2812 const start = P.L.b
2813 // Value-substitution RHS starting with `(` parses as array: ${var:-(x)} →
2814 // (expansion (variable_name) (array (word))). Only for 'word' context (not
2815 // pattern-matching operators which emit regex, and not 'replword' where `(`
2816 // is a regular char per grammar `_expansion_regex_replacement`).
2817 if (nodeType === 'word' && peek(P.L) === '(') {
2818 advance(P.L)
2819 const open = mk(P, '(', start, P.L.b, [])
2820 const elems: TsNode[] = [open]
2821 while (P.L.i < P.L.len) {
2822 skipBlanks(P.L)
2823 const c = peek(P.L)
2824 if (c === ')' || c === '}' || c === '\n' || c === '') break
2825 const wStart = P.L.b
2826 while (P.L.i < P.L.len) {
2827 const wc = peek(P.L)
2828 if (
2829 wc === ')' ||
2830 wc === '}' ||
2831 wc === ' ' ||
2832 wc === '\t' ||
2833 wc === '\n' ||
2834 wc === ''
2835 ) {
2836 break
2837 }
2838 advance(P.L)
2839 }
2840 if (P.L.b > wStart) elems.push(mk(P, 'word', wStart, P.L.b, []))
2841 else break
2842 }
2843 if (peek(P.L) === ')') {
2844 const cStart = P.L.b
2845 advance(P.L)
2846 elems.push(mk(P, ')', cStart, P.L.b, []))
2847 }
2848 while (peek(P.L) === '\n') advance(P.L)
2849 return mk(P, 'array', start, P.L.b, elems)
2850 }
2851 // REGEX mode: flat single-span scan. Quotes are opaque (skipped past so
2852 // `/` inside them doesn't break stopAtSlash), but NOT emitted as separate
2853 // nodes — the entire range becomes one regex node.
2854 if (nodeType === 'regex') {
2855 let braceDepth = 0
2856 while (P.L.i < P.L.len) {
2857 const c = peek(P.L)
2858 if (c === '\n') break
2859 if (braceDepth === 0) {
2860 if (c === '}') break

Callers 1

parseExpansionBodyFunction · 0.85

Calls 14

advanceFunction · 0.85
skipBlanksFunction · 0.85
flushSegFunction · 0.85
parseDollarLikeFunction · 0.85
isIdentStartFunction · 0.85
isDigitFunction · 0.85
parseDoubleQuotedFunction · 0.85
parseProcessSubFunction · 0.85
parseBacktickFunction · 0.85
shiftMethod · 0.80
peekFunction · 0.70
mkFunction · 0.70

Tested by

no test coverage detected