in variables.go [451:504]
func parseVarExp(lex <-chan token, pathSep string, maxIdx int64, enableNumKeys, allowEscapePath bool) (varEvaler, error) {
stack := []parseState{{st: stLeft}}
// parser loop
for tok := range lex {
switch tok.typ {
case tokOpen:
stack = append(stack, parseState{st: stLeft, isvar: true})
case tokClose:
// finalize and pop state
piece, err := stack[len(stack)-1].finalize(pathSep, maxIdx, enableNumKeys, allowEscapePath)
stack = stack[:len(stack)-1]
if err != nil {
return nil, err
}
// append result top stacked state
st := &stack[len(stack)-1]
st.pieces[st.st] = append(st.pieces[st.st], piece)
case tokSep: // switch from left to right
st := &stack[len(stack)-1]
if !st.isvar {
return nil, errors.New("default separator not within expansion")
}
if st.st == stRight {
st.pieces[st.st] = addString(st.pieces[st.st], tok.val)
} else {
// switch to 'right'
st.st = stRight
st.op = tok.val
}
case tokString:
// append raw string
st := &stack[len(stack)-1]
st.pieces[st.st] = addString(st.pieces[st.st], tok.val)
}
}
// validate and return final state
if len(stack) > 1 {
return nil, errors.New("missing '}'")
}
if len(stack) == 0 {
return nil, errors.New("fatal: expansion parse state empty")
}
result := stack[0].pieces[stLeft]
if len(result) == 1 {
return result[0], nil
}
return &splice{result}, nil
}