in query/parse.go [396:474]
func nextToken(in []byte) (*token, error) {
left := in[:]
parenCount := 0
var cur token
if len(left) == 0 {
return nil, nil
}
if left[0] == '-' {
return &token{
Type: tokNegate,
Text: []byte{'-'},
Input: in[:1],
}, nil
}
foundSpace := false
loop:
for len(left) > 0 {
c := left[0]
switch c {
case '(':
parenCount++
cur.Text = append(cur.Text, c)
left = left[1:]
case ')':
if parenCount == 0 {
if len(cur.Text) == 0 {
cur.Text = []byte{')'}
left = left[1:]
}
break loop
}
cur.Text = append(cur.Text, c)
left = left[1:]
parenCount--
case '"':
t, n, err := parseStringLiteral(left)
if err != nil {
return nil, err
}
cur.Text = append(cur.Text, t...)
left = left[n:]
case '\\':
left = left[1:]
if len(left) == 0 {
return nil, fmt.Errorf("query: lone \\ at end")
}
c := left[0]
cur.Text = append(cur.Text, '\\', c)
left = left[1:]
case ' ', '\n', '\t':
if parenCount > 0 {
foundSpace = true
}
break loop
default:
cur.Text = append(cur.Text, c)
left = left[1:]
}
}
if len(cur.Text) == 0 {
return nil, nil
}
if foundSpace && cur.Text[0] == '(' {
cur.Text = cur.Text[:1]
cur.Input = in[:1]
} else {
cur.Input = in[:len(in)-len(left)]
}
cur.setType()
return &cur, nil
}