in cli/azd/pkg/yamlnode/yamlnode.go [291:407]
func parseElem(s string) ([]pathElem, error) {
result := []pathElem{}
elem := pathElem{kind: keyElem}
key := strings.Builder{}
inKey := true // whether we are currently parsing a key part of the element
for i := 0; i < len(s); i++ {
c := s[i]
switch c {
case '[':
inKey = false
// find the closing bracket
j := i + 1
for j < len(s) {
if s[j] == ']' {
break
}
j++
}
if j == len(s) {
return nil, fmt.Errorf("missing closing bracket ']' after '[': %s", s[i:])
}
// contents is the string between the brackets
contents := s[i+1 : j]
if contents == "" && j+1 < len(s) && s[j+1] == '?' { // empty brackets followed by '?'
elem.optionalKind = yaml.SequenceNode
i = j + 1
continue
}
idx, err := strconv.Atoi(contents)
if err != nil || idx < 0 {
return nil, fmt.Errorf("invalid sequence index: %s in %s", contents, s[i:j+1])
}
switch elem.kind {
case keyElem:
elem.key = key.String()
key.Reset()
if elem.key == "" {
return nil, fmt.Errorf("empty key in %s", s)
}
case indexElem:
// do nothing
}
result = append(result, elem)
elem = pathElem{kind: indexElem, idx: idx}
i = j
case ']':
return nil, fmt.Errorf("unexpected closing bracket '[' before ']': %s", s[i:])
case '?':
elem.optionalKind = yaml.MappingNode
if i != len(s)-1 {
return nil, fmt.Errorf(
"unexpected characters after optional qualifier `?`: %s: "+
"'?' is a special character; to escape using double quotes, try \"%s\"",
s[i+1:],
s[:i])
}
case '\\':
if i+1 < len(s) && s[i+1] == '"' {
key.WriteByte('"')
i++
}
case '"':
// find the closing quote
j := i + 1
for j < len(s) {
if s[j] == '\\' && j+1 < len(s) && s[j+1] == '"' {
key.WriteByte('"')
j += 2
continue
}
if s[j] == '"' {
break
}
key.WriteByte(s[j])
j++
}
if j == len(s) {
return nil, fmt.Errorf(
"missing closing quote '\"' near %s; to escape double quotes, try adding a preceding backslash", s[i:])
}
i = j
default:
if !inKey {
return nil, fmt.Errorf(
"unexpected characters after character `%s`: %s: "+
"'[', ']' are special characters; to escape using double quotes, try \"%s\"",
string(s[i-1]),
s[i:],
s[:i-1])
}
key.WriteByte(c)
}
}
if key.Len() > 0 {
elem.key = key.String()
elem.kind = keyElem
}
if len(result) == 0 && elem.key == "" {
return nil, fmt.Errorf("empty")
}
result = append(result, elem)
return result, nil
}