MCPcopy
hub / github.com/codeaashu/claude-code / parseExpansionRest

Function parseExpansionRest

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

Source from the content-addressed store, hash-verified

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

Callers 1

parseExpansionBodyFunction · 0.85

Calls 14

advanceFunction · 0.85
mkFunction · 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

Tested by

no test coverage detected