Files
services/search/handler/parser.go
2022-01-07 09:58:10 +00:00

102 lines
2.3 KiB
Go

package handler
import (
"fmt"
"strings"
"github.com/bitly/go-simplejson"
)
func parseQueryString(query string) (*simplejson.Json, error) {
_, items := lex("foo", query)
res, err := parseQueryStringRec(items)
if err != nil {
return nil, err
}
js := simplejson.New()
js.Set("query", res)
return js, nil
}
const (
matchTypeRange = "range"
matchTypeMatch = "match"
matchTypeWildcard = "wildcard"
)
func parseQueryStringRec(items chan item) (*simplejson.Json, error) {
retTerm := simplejson.New()
currFieldName := ""
currBool := ""
currMatchType := matchTypeMatch
currPathAddition := ""
terms := []*simplejson.Json{}
itemLoop:
for it := range items {
if it.typ == itemError {
return nil, fmt.Errorf(it.val)
}
switch it.typ {
case itemIdentifier:
currFieldName = it.val
case itemString, itemBoolean, itemNumber:
currTerm := simplejson.New()
if strings.ContainsRune(it.val, '*') {
currMatchType = matchTypeWildcard
currPathAddition = "value"
}
path := []string{currMatchType, currFieldName}
if len(currPathAddition) > 0 {
path = append(path, currPathAddition)
}
currTerm.SetPath(path, it.val)
terms = append(terms, currTerm)
// reset
currFieldName = ""
currMatchType = matchTypeMatch
case itemBooleanOp:
thisBool := "must"
if strings.ToLower(it.val) == "or" {
thisBool = "should"
}
if len(currBool) == 0 {
currBool = thisBool
} else {
if thisBool != currBool {
// undefined behaviour order of precedence needs to be explicitly defined using parentheses
return nil, fmt.Errorf("error parsing query. Cannot mix boolean operators without explicitly defining precedence with parentheses")
}
}
case itemLeftParen:
currTerm, err := parseQueryStringRec(items)
if err != nil {
return nil, err
}
terms = append(terms, currTerm)
case itemRightParen:
break itemLoop
case itemOperator:
switch it.val {
case "==":
currMatchType = matchTypeMatch
currPathAddition = ""
case ">=":
currMatchType = matchTypeRange
currPathAddition = "gte"
case "<=":
currMatchType = matchTypeRange
currPathAddition = "lte"
}
}
}
if len(currBool) == 0 {
currBool = "must"
}
retTerm.SetPath([]string{"bool", currBool}, terms)
return retTerm, nil
}