in variables.go [365:449]
func lexer(in string) (<-chan token, <-chan error) {
lex := make(chan token, 1)
errors := make(chan error, 1)
go func() {
off := 0
content := in
defer func() {
if len(content) > 0 {
lex <- token{tokString, content}
}
close(lex)
close(errors)
}()
strToken := func(s string) {
if s != "" {
lex <- token{tokString, s}
}
}
varcount := 0
for len(content) > 0 {
idx := -1
if varcount == 0 {
idx = strings.IndexAny(content[off:], "$")
} else {
idx = strings.IndexAny(content[off:], "$:}")
}
if idx < 0 {
return
}
idx += off
off = idx + 1
switch content[idx] {
case ':':
if len(content) <= off { // found ':' at end of string
return
}
strToken(content[:idx])
switch content[off] {
case '+':
off++
lex <- sepAltToken
case '?':
off++
lex <- sepErrToken
default:
lex <- sepDefToken
}
case '}':
strToken(content[:idx])
lex <- closeToken
varcount--
case '$':
if len(content) <= off { // found '$' at end of string
return
}
switch content[off] {
case '{': // start variable
strToken(content[:idx])
lex <- openToken
off++
varcount++
case '$', '}': // escape $} and $$
content = content[:idx] + content[off:]
continue
default:
continue
}
}
content = content[off:]
off = 0
}
}()
return lex, errors
}