Fix golint errors and export all returnable types
This commit is contained in:
parent
3ab215ed63
commit
ca047193ee
@ -1,10 +1,10 @@
|
|||||||
package jsonpath
|
package jsonpath
|
||||||
|
|
||||||
const (
|
const (
|
||||||
BadStructure = "Bad Structure"
|
BadStructure = "bad structure"
|
||||||
NoMoreResults = "No more results"
|
NoMoreResults = "no more results"
|
||||||
UnexpectedToken = "Unexpected token in evaluation"
|
UnexpectedToken = "unexpected token in evaluation"
|
||||||
AbruptTokenStreamEnd = "Token reader is not sending anymore tokens"
|
AbruptTokenStreamEnd = "token reader is not sending anymore tokens"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
31
eval.go
31
eval.go
@ -49,7 +49,7 @@ func newEvaluation(tr tokenReader, paths ...*Path) *Eval {
|
|||||||
location: *newStack(),
|
location: *newStack(),
|
||||||
levelStack: *newIntStack(),
|
levelStack: *newIntStack(),
|
||||||
state: evalRoot,
|
state: evalRoot,
|
||||||
queries: make(map[string]*query, 0),
|
queries: make(map[string]*query),
|
||||||
prevIndex: -1,
|
prevIndex: -1,
|
||||||
nextKey: nil,
|
nextKey: nil,
|
||||||
copyValues: true, // depends on which lexer is used
|
copyValues: true, // depends on which lexer is used
|
||||||
@ -61,7 +61,7 @@ func newEvaluation(tr tokenReader, paths ...*Path) *Eval {
|
|||||||
}
|
}
|
||||||
// Determine whether to copy emitted item values ([]byte) from lexer
|
// Determine whether to copy emitted item values ([]byte) from lexer
|
||||||
switch tr.(type) {
|
switch tr.(type) {
|
||||||
case *readerLexer:
|
case *ReaderLexer:
|
||||||
e.copyValues = true
|
e.copyValues = true
|
||||||
default:
|
default:
|
||||||
e.copyValues = false
|
e.copyValues = false
|
||||||
@ -100,6 +100,7 @@ func (e *Eval) Iterate() (*Results, bool) {
|
|||||||
for str, query := range e.queries {
|
for str, query := range e.queries {
|
||||||
anyRunning = true
|
anyRunning = true
|
||||||
query.state = query.state(query, e, t)
|
query.state = query.state(query, e, t)
|
||||||
|
|
||||||
if query.state == nil {
|
if query.state == nil {
|
||||||
delete(e.queries, str)
|
delete(e.queries, str)
|
||||||
}
|
}
|
||||||
@ -144,8 +145,8 @@ func (e *Eval) Next() (*Result, bool) {
|
|||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,9 +164,12 @@ func (q *query) trySpillOver() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
q.errors = append(q.errors, err)
|
q.errors = append(q.errors, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if exprRes {
|
if exprRes {
|
||||||
next, ok := q.buckets.peek()
|
next, ok := q.buckets.peek()
|
||||||
|
|
||||||
var spillover *Results
|
var spillover *Results
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
// fmt.Println("Spilling over into end queue")
|
// fmt.Println("Spilling over into end queue")
|
||||||
spillover = q.resultQueue
|
spillover = q.resultQueue
|
||||||
@ -174,6 +178,7 @@ func (q *query) trySpillOver() {
|
|||||||
nextBucket := next.(exprBucket)
|
nextBucket := next.(exprBucket)
|
||||||
spillover = nextBucket.results
|
spillover = nextBucket.results
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
v := bucket.results.Pop()
|
v := bucket.results.Pop()
|
||||||
if v != nil {
|
if v != nil {
|
||||||
@ -191,7 +196,7 @@ func pathMatchOp(q *query, e *Eval, i *Item) queryStateFn {
|
|||||||
curLocation := e.location.len() - 1
|
curLocation := e.location.len() - 1
|
||||||
|
|
||||||
if q.loc() > curLocation {
|
if q.loc() > curLocation {
|
||||||
q.pos -= 1
|
q.pos--
|
||||||
q.trySpillOver()
|
q.trySpillOver()
|
||||||
} else if q.loc() <= curLocation {
|
} else if q.loc() <= curLocation {
|
||||||
if q.loc() == curLocation-1 {
|
if q.loc() == curLocation-1 {
|
||||||
@ -218,7 +223,6 @@ func pathMatchOp(q *query, e *Eval, i *Item) queryStateFn {
|
|||||||
q.buckets.push(bucket)
|
q.buckets.push(bucket)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -228,15 +232,17 @@ func pathMatchOp(q *query, e *Eval, i *Item) queryStateFn {
|
|||||||
q.firstType = i.typ
|
q.firstType = i.typ
|
||||||
q.buffer.Write(i.val)
|
q.buffer.Write(i.val)
|
||||||
}
|
}
|
||||||
|
|
||||||
q.valLoc = *e.location.clone()
|
q.valLoc = *e.location.clone()
|
||||||
|
|
||||||
return pathEndValue
|
return pathEndValue
|
||||||
}
|
}
|
||||||
|
|
||||||
if q.loc() < -1 {
|
if q.loc() < -1 {
|
||||||
return nil
|
return nil
|
||||||
} else {
|
|
||||||
return pathMatchOp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return pathMatchOp
|
||||||
}
|
}
|
||||||
|
|
||||||
func pathEndValue(q *query, e *Eval, i *Item) queryStateFn {
|
func pathEndValue(q *query, e *Eval, i *Item) queryStateFn {
|
||||||
@ -278,14 +284,16 @@ func pathEndValue(q *query, e *Eval, i *Item) queryStateFn {
|
|||||||
|
|
||||||
q.valLoc = *newStack()
|
q.valLoc = *newStack()
|
||||||
q.buffer.Truncate(0)
|
q.buffer.Truncate(0)
|
||||||
q.pos -= 1
|
q.pos--
|
||||||
return pathMatchOp
|
return pathMatchOp
|
||||||
}
|
}
|
||||||
|
|
||||||
return pathEndValue
|
return pathEndValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *exprBucket) evaluate() (bool, error) {
|
func (b *exprBucket) evaluate() (bool, error) {
|
||||||
values := make(map[string]Item)
|
values := make(map[string]Item)
|
||||||
|
|
||||||
for _, q := range b.queries {
|
for _, q := range b.queries {
|
||||||
result := q.resultQueue.Pop()
|
result := q.resultQueue.Pop()
|
||||||
if result != nil {
|
if result != nil {
|
||||||
@ -293,6 +301,7 @@ func (b *exprBucket) evaluate() (bool, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
i := Item{
|
i := Item{
|
||||||
typ: t,
|
typ: t,
|
||||||
val: result.Value,
|
val: result.Value,
|
||||||
@ -305,11 +314,13 @@ func (b *exprBucket) evaluate() (bool, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
res_bool, ok := res.(bool)
|
|
||||||
|
resBool, ok := res.(bool)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, fmt.Errorf(exprErrorFinalValueNotBool, res)
|
return false, fmt.Errorf(exprErrorFinalValueNotBool, res)
|
||||||
}
|
}
|
||||||
return res_bool, nil
|
|
||||||
|
return resBool, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func itemMatchOperator(loc interface{}, op *operator) bool {
|
func itemMatchOperator(loc interface{}, op *operator) bool {
|
||||||
|
@ -18,6 +18,7 @@ func evalRoot(e *Eval, i *Item) evalStateFn {
|
|||||||
default:
|
default:
|
||||||
e.Error = errors.New(UnexpectedToken)
|
e.Error = errors.New(UnexpectedToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,12 +26,16 @@ func evalObjectAfterOpen(e *Eval, i *Item) evalStateFn {
|
|||||||
switch i.typ {
|
switch i.typ {
|
||||||
case jsonKey:
|
case jsonKey:
|
||||||
c := i.val[1 : len(i.val)-1]
|
c := i.val[1 : len(i.val)-1]
|
||||||
|
|
||||||
if e.copyValues {
|
if e.copyValues {
|
||||||
d := make([]byte, len(c))
|
d := make([]byte, len(c))
|
||||||
copy(d, c)
|
copy(d, c)
|
||||||
|
|
||||||
c = d
|
c = d
|
||||||
}
|
}
|
||||||
|
|
||||||
e.nextKey = c
|
e.nextKey = c
|
||||||
|
|
||||||
return evalObjectColon
|
return evalObjectColon
|
||||||
case jsonBraceRight:
|
case jsonBraceRight:
|
||||||
return rightBraceOrBracket(e)
|
return rightBraceOrBracket(e)
|
||||||
@ -39,6 +44,7 @@ func evalObjectAfterOpen(e *Eval, i *Item) evalStateFn {
|
|||||||
default:
|
default:
|
||||||
e.Error = errors.New(UnexpectedToken)
|
e.Error = errors.New(UnexpectedToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,11 +78,13 @@ func evalObjectValue(e *Eval, i *Item) evalStateFn {
|
|||||||
default:
|
default:
|
||||||
e.Error = errors.New(UnexpectedToken)
|
e.Error = errors.New(UnexpectedToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func evalObjectAfterValue(e *Eval, i *Item) evalStateFn {
|
func evalObjectAfterValue(e *Eval, i *Item) evalStateFn {
|
||||||
e.location.pop()
|
e.location.pop()
|
||||||
|
|
||||||
switch i.typ {
|
switch i.typ {
|
||||||
case jsonComma:
|
case jsonComma:
|
||||||
return evalObjectAfterOpen
|
return evalObjectAfterOpen
|
||||||
@ -87,6 +95,7 @@ func evalObjectAfterValue(e *Eval, i *Item) evalStateFn {
|
|||||||
default:
|
default:
|
||||||
e.Error = errors.New(UnexpectedToken)
|
e.Error = errors.New(UnexpectedToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,14 +105,15 @@ func rightBraceOrBracket(e *Eval) evalStateFn {
|
|||||||
lowerTyp, ok := e.levelStack.peek()
|
lowerTyp, ok := e.levelStack.peek()
|
||||||
if !ok {
|
if !ok {
|
||||||
return evalRootEnd
|
return evalRootEnd
|
||||||
} else {
|
}
|
||||||
|
|
||||||
switch lowerTyp {
|
switch lowerTyp {
|
||||||
case jsonBraceLeft:
|
case jsonBraceLeft:
|
||||||
return evalObjectAfterValue
|
return evalObjectAfterValue
|
||||||
case jsonBracketLeft:
|
case jsonBracketLeft:
|
||||||
return evalArrayAfterValue
|
return evalArrayAfterValue
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,13 +9,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
exprErrorMismatchedParens = "Mismatched parentheses"
|
exprErrorMismatchedParens = "mismatched parentheses"
|
||||||
exprErrorBadExpression = "Bad Expression"
|
exprErrorBadExpression = "bad expression"
|
||||||
exprErrorFinalValueNotBool = "Expression evaluated to a non-bool: %v"
|
exprErrorFinalValueNotBool = "expression evaluated to a non-bool: %v"
|
||||||
exprErrorNotEnoughOperands = "Not enough operands for operation %q"
|
exprErrorNotEnoughOperands = "not enough operands for operation %q"
|
||||||
exprErrorValueNotFound = "Value for %q not found"
|
exprErrorValueNotFound = "value for %q not found"
|
||||||
exprErrorBadValue = "Bad value %q for type %q"
|
exprErrorBadValue = "bad value %q for type %q"
|
||||||
exprErrorPathValueNotScalar = "Path value must be scalar value"
|
exprErrorPathValueNotScalar = "path value must be scalar value"
|
||||||
)
|
)
|
||||||
|
|
||||||
type exprErrorBadTypeComparison struct {
|
type exprErrorBadTypeComparison struct {
|
||||||
@ -141,15 +141,16 @@ func evaluatePostFix(postFixItems []Item, pathValues map[string]Item) (interface
|
|||||||
if !ok {
|
if !ok {
|
||||||
return false, fmt.Errorf(exprErrorValueNotFound, string(item.val))
|
return false, fmt.Errorf(exprErrorValueNotFound, string(item.val))
|
||||||
}
|
}
|
||||||
|
|
||||||
switch i.typ {
|
switch i.typ {
|
||||||
case jsonNull:
|
case jsonNull:
|
||||||
s.push(nil)
|
s.push(nil)
|
||||||
case jsonNumber:
|
case jsonNumber:
|
||||||
val_float, err := strconv.ParseFloat(string(i.val), 64)
|
valFloat, err := strconv.ParseFloat(string(i.val), 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf(exprErrorBadValue, string(item.val), jsonTokenNames[jsonNumber])
|
return false, fmt.Errorf(exprErrorBadValue, string(item.val), jsonTokenNames[jsonNumber])
|
||||||
}
|
}
|
||||||
s.push(val_float)
|
s.push(valFloat)
|
||||||
case jsonKey, jsonString:
|
case jsonKey, jsonString:
|
||||||
s.push(i.val)
|
s.push(i.val)
|
||||||
default:
|
default:
|
||||||
@ -173,14 +174,15 @@ func evaluatePostFix(postFixItems []Item, pathValues map[string]Item) (interface
|
|||||||
if !ok {
|
if !ok {
|
||||||
return false, fmt.Errorf(exprErrorNotEnoughOperands, exprTokenNames[item.typ])
|
return false, fmt.Errorf(exprErrorNotEnoughOperands, exprTokenNames[item.typ])
|
||||||
}
|
}
|
||||||
|
|
||||||
switch p.(type) {
|
switch p.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
err := take2Null(s, item.typ)
|
err := take2Null(s, item.typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
} else {
|
|
||||||
s.push(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.push(true)
|
||||||
case bool:
|
case bool:
|
||||||
a, b, err := take2Bool(s, item.typ)
|
a, b, err := take2Bool(s, item.typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -205,14 +207,15 @@ func evaluatePostFix(postFixItems []Item, pathValues map[string]Item) (interface
|
|||||||
if !ok {
|
if !ok {
|
||||||
return false, fmt.Errorf(exprErrorNotEnoughOperands, exprTokenNames[item.typ])
|
return false, fmt.Errorf(exprErrorNotEnoughOperands, exprTokenNames[item.typ])
|
||||||
}
|
}
|
||||||
|
|
||||||
switch p.(type) {
|
switch p.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
err := take2Null(s, item.typ)
|
err := take2Null(s, item.typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, err
|
return true, err
|
||||||
} else {
|
|
||||||
s.push(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.push(false)
|
||||||
case bool:
|
case bool:
|
||||||
a, b, err := take2Bool(s, item.typ)
|
a, b, err := take2Bool(s, item.typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -363,9 +366,9 @@ func take1Bool(s *stack, op int) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func take2Bool(s *stack, op int) (bool, bool, error) {
|
func take2Bool(s *stack, op int) (bool, bool, error) {
|
||||||
a, a_err := take1Bool(s, op)
|
a, aErr := take1Bool(s, op)
|
||||||
b, b_err := take1Bool(s, op)
|
b, bErr := take1Bool(s, op)
|
||||||
return a, b, firstError(a_err, b_err)
|
return a, b, firstError(aErr, bErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func take1Float(s *stack, op int) (float64, error) {
|
func take1Float(s *stack, op int) (float64, error) {
|
||||||
@ -383,9 +386,9 @@ func take1Float(s *stack, op int) (float64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func take2Float(s *stack, op int) (float64, float64, error) {
|
func take2Float(s *stack, op int) (float64, float64, error) {
|
||||||
a, a_err := take1Float(s, op)
|
a, aErr := take1Float(s, op)
|
||||||
b, b_err := take1Float(s, op)
|
b, bErr := take1Float(s, op)
|
||||||
return a, b, firstError(a_err, b_err)
|
return a, b, firstError(aErr, bErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func take1ByteSlice(s *stack, op int) ([]byte, error) {
|
func take1ByteSlice(s *stack, op int) ([]byte, error) {
|
||||||
@ -403,9 +406,9 @@ func take1ByteSlice(s *stack, op int) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func take2ByteSlice(s *stack, op int) ([]byte, []byte, error) {
|
func take2ByteSlice(s *stack, op int) ([]byte, []byte, error) {
|
||||||
a, a_err := take1ByteSlice(s, op)
|
a, aErr := take1ByteSlice(s, op)
|
||||||
b, b_err := take1ByteSlice(s, op)
|
b, bErr := take1ByteSlice(s, op)
|
||||||
return a, b, firstError(a_err, b_err)
|
return a, b, firstError(aErr, bErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func take1Null(s *stack, op int) error {
|
func take1Null(s *stack, op int) error {
|
||||||
@ -422,7 +425,7 @@ func take1Null(s *stack, op int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func take2Null(s *stack, op int) error {
|
func take2Null(s *stack, op int) error {
|
||||||
a_err := take1Null(s, op)
|
aErr := take1Null(s, op)
|
||||||
b_err := take1Null(s, op)
|
bErr := take1Null(s, op)
|
||||||
return firstError(a_err, b_err)
|
return firstError(aErr, bErr)
|
||||||
}
|
}
|
||||||
|
@ -149,9 +149,9 @@ func TestExpressions(t *testing.T) {
|
|||||||
items := readerToArray(lexer)
|
items := readerToArray(lexer)
|
||||||
// trim EOF
|
// trim EOF
|
||||||
items = items[0 : len(items)-1]
|
items = items[0 : len(items)-1]
|
||||||
items_post, err := infixToPostFix(items)
|
itemsPost, err := infixToPostFix(items)
|
||||||
if as.NoError(err, "Could not transform to postfix\nTest: %q", test.input) {
|
if as.NoError(err, "Could not transform to postfix\nTest: %q", test.input) {
|
||||||
val, err := evaluatePostFix(items_post, test.fields)
|
val, err := evaluatePostFix(itemsPost, test.fields)
|
||||||
if as.NoError(err, "Could not evaluate postfix\nTest Input: %q\nTest Values:%q\nError:%q", test.input, test.fields, err) {
|
if as.NoError(err, "Could not evaluate postfix\nTest Input: %q\nTest Values:%q\nError:%q", test.input, test.fields, err) {
|
||||||
as.EqualValues(test.expectedValue, val, "\nTest: %q\nActual: %v \nExpected %v\n", test.input, val, test.expectedValue)
|
as.EqualValues(test.expectedValue, val, "\nTest: %q\nActual: %v \nExpected %v\n", test.input, val, test.expectedValue)
|
||||||
}
|
}
|
||||||
@ -165,8 +165,8 @@ var exprErrorTests = []struct {
|
|||||||
expectedErrorSubstring string
|
expectedErrorSubstring string
|
||||||
}{
|
}{
|
||||||
{"@a == @b", map[string]Item{"@a": genValue(`"one"`, jsonString), "@b": genValue("3.4", jsonNumber)}, "cannot be compared"},
|
{"@a == @b", map[string]Item{"@a": genValue(`"one"`, jsonString), "@b": genValue("3.4", jsonNumber)}, "cannot be compared"},
|
||||||
{")(", nil, "Mismatched parentheses"},
|
{")(", nil, "mismatched parentheses"},
|
||||||
{")123", nil, "Mismatched parentheses"},
|
{")123", nil, "mismatched parentheses"},
|
||||||
{"20 == null", nil, "cannot be compared"},
|
{"20 == null", nil, "cannot be compared"},
|
||||||
{`"toronto" == null`, nil, "cannot be compared"},
|
{`"toronto" == null`, nil, "cannot be compared"},
|
||||||
{`false == 20`, nil, "cannot be compared"},
|
{`false == 20`, nil, "cannot be compared"},
|
||||||
@ -175,9 +175,9 @@ var exprErrorTests = []struct {
|
|||||||
{`"toronto" != null`, nil, "cannot be compared"},
|
{`"toronto" != null`, nil, "cannot be compared"},
|
||||||
{`false != 20`, nil, "cannot be compared"},
|
{`false != 20`, nil, "cannot be compared"},
|
||||||
{`"nick" != 20`, nil, "cannot be compared"},
|
{`"nick" != 20`, nil, "cannot be compared"},
|
||||||
{``, nil, "Bad Expression"},
|
{``, nil, "bad expression"},
|
||||||
{`==`, nil, "Bad Expression"},
|
{`==`, nil, "bad expression"},
|
||||||
{`!=`, nil, "Not enough operands"},
|
{`!=`, nil, "not enough operands"},
|
||||||
|
|
||||||
{`!23`, nil, "cannot be compared"},
|
{`!23`, nil, "cannot be compared"},
|
||||||
{`"nick" || true`, nil, "cannot be compared"},
|
{`"nick" || true`, nil, "cannot be compared"},
|
||||||
@ -210,13 +210,13 @@ func TestBadExpressions(t *testing.T) {
|
|||||||
items := readerToArray(lexer)
|
items := readerToArray(lexer)
|
||||||
// trim EOF
|
// trim EOF
|
||||||
items = items[0 : len(items)-1]
|
items = items[0 : len(items)-1]
|
||||||
items_post, err := infixToPostFix(items)
|
itemsPost, err := infixToPostFix(items)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
as.True(strings.Contains(err.Error(), test.expectedErrorSubstring), "Test Input: %q\nError %q does not contain %q", test.input, err.Error(), test.expectedErrorSubstring)
|
as.True(strings.Contains(err.Error(), test.expectedErrorSubstring), "Test Input: %q\nError %q does not contain %q", test.input, err.Error(), test.expectedErrorSubstring)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if as.NoError(err, "Could not transform to postfix\nTest: %q", test.input) {
|
if as.NoError(err, "Could not transform to postfix\nTest: %q", test.input) {
|
||||||
_, err := evaluatePostFix(items_post, test.fields)
|
_, err := evaluatePostFix(itemsPost, test.fields)
|
||||||
if as.Error(err, "Could not evaluate postfix\nTest Input: %q\nTest Values:%q\nError:%s", test.input, test.fields, err) {
|
if as.Error(err, "Could not evaluate postfix\nTest Input: %q\nTest Values:%q\nError:%s", test.input, test.fields, err) {
|
||||||
as.True(strings.Contains(err.Error(), test.expectedErrorSubstring), "Test Input: %q\nError %s does not contain %q", test.input, err.Error(), test.expectedErrorSubstring)
|
as.True(strings.Contains(err.Error(), test.expectedErrorSubstring), "Test Input: %q\nError %s does not contain %q", test.input, err.Error(), test.expectedErrorSubstring)
|
||||||
}
|
}
|
||||||
|
@ -134,9 +134,9 @@ func stateJSONAfterValue(l lexer, state *intStack) stateFn {
|
|||||||
case jsonBracketLeft:
|
case jsonBracketLeft:
|
||||||
return stateJSONValue
|
return stateJSONValue
|
||||||
case noValue:
|
case noValue:
|
||||||
return l.errorf("Found %#U outside of array or object", cur)
|
return l.errorf("found %#U outside of array or object", cur)
|
||||||
default:
|
default:
|
||||||
return l.errorf("Unexpected character in lexer stack: %#U", cur)
|
return l.errorf("unexpected character in lexer stack: %#U", cur)
|
||||||
}
|
}
|
||||||
case '}':
|
case '}':
|
||||||
l.emit(jsonBraceRight)
|
l.emit(jsonBraceRight)
|
||||||
@ -145,7 +145,7 @@ func stateJSONAfterValue(l lexer, state *intStack) stateFn {
|
|||||||
case jsonBraceLeft:
|
case jsonBraceLeft:
|
||||||
return stateJSONAfterValue
|
return stateJSONAfterValue
|
||||||
case jsonBracketLeft:
|
case jsonBracketLeft:
|
||||||
return l.errorf("Unexpected %#U in array", cur)
|
return l.errorf("unexpected %#U in array", cur)
|
||||||
case noValue:
|
case noValue:
|
||||||
return stateJSONAfterRoot
|
return stateJSONAfterRoot
|
||||||
}
|
}
|
||||||
@ -154,7 +154,7 @@ func stateJSONAfterValue(l lexer, state *intStack) stateFn {
|
|||||||
state.pop()
|
state.pop()
|
||||||
switch topVal {
|
switch topVal {
|
||||||
case jsonBraceLeft:
|
case jsonBraceLeft:
|
||||||
return l.errorf("Unexpected %#U in object", cur)
|
return l.errorf("unexpected %#U in object", cur)
|
||||||
case jsonBracketLeft:
|
case jsonBracketLeft:
|
||||||
return stateJSONAfterValue
|
return stateJSONAfterValue
|
||||||
case noValue:
|
case noValue:
|
||||||
@ -164,11 +164,11 @@ func stateJSONAfterValue(l lexer, state *intStack) stateFn {
|
|||||||
if state.len() == 0 {
|
if state.len() == 0 {
|
||||||
l.emit(jsonEOF)
|
l.emit(jsonEOF)
|
||||||
return nil
|
return nil
|
||||||
} else {
|
|
||||||
return l.errorf("Unexpected EOF instead of value")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return l.errorf("unexpected EOF instead of value")
|
||||||
default:
|
default:
|
||||||
return l.errorf("Unexpected character after json value token: %#U", cur)
|
return l.errorf("unexpected character after json value token: %#U", cur)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
type readerLexer struct {
|
type ReaderLexer struct {
|
||||||
lex
|
lex
|
||||||
bufInput *bufio.Reader
|
bufInput *bufio.Reader
|
||||||
input io.Reader
|
input io.Reader
|
||||||
@ -17,8 +17,8 @@ type readerLexer struct {
|
|||||||
lexeme *bytes.Buffer
|
lexeme *bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewReaderLexer(rr io.Reader, initial stateFn) *readerLexer {
|
func NewReaderLexer(rr io.Reader, initial stateFn) *ReaderLexer {
|
||||||
l := readerLexer{
|
l := ReaderLexer{
|
||||||
input: rr,
|
input: rr,
|
||||||
bufInput: bufio.NewReader(rr),
|
bufInput: bufio.NewReader(rr),
|
||||||
nextByte: noValue,
|
nextByte: noValue,
|
||||||
@ -28,7 +28,7 @@ func NewReaderLexer(rr io.Reader, initial stateFn) *readerLexer {
|
|||||||
return &l
|
return &l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *readerLexer) take() int {
|
func (l *ReaderLexer) take() int {
|
||||||
if l.nextByte == noValue {
|
if l.nextByte == noValue {
|
||||||
l.peek()
|
l.peek()
|
||||||
}
|
}
|
||||||
@ -39,10 +39,10 @@ func (l *readerLexer) take() int {
|
|||||||
return nr
|
return nr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *readerLexer) takeString() error {
|
func (l *ReaderLexer) takeString() error {
|
||||||
cur := l.take()
|
cur := l.take()
|
||||||
if cur != '"' {
|
if cur != '"' {
|
||||||
return fmt.Errorf("Expected \" as start of string instead of %#U", cur)
|
return fmt.Errorf("expected \" as start of string instead of %#U", cur)
|
||||||
}
|
}
|
||||||
|
|
||||||
var previous byte
|
var previous byte
|
||||||
@ -50,7 +50,7 @@ looper:
|
|||||||
for {
|
for {
|
||||||
curByte, err := l.bufInput.ReadByte()
|
curByte, err := l.bufInput.ReadByte()
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return errors.New("Unexpected EOF in string")
|
return errors.New("unexpected EOF in string")
|
||||||
}
|
}
|
||||||
l.lexeme.WriteByte(curByte)
|
l.lexeme.WriteByte(curByte)
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ looper:
|
|||||||
} else {
|
} else {
|
||||||
curByte, err = l.bufInput.ReadByte()
|
curByte, err = l.bufInput.ReadByte()
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return errors.New("Unexpected EOF in string")
|
return errors.New("unexpected EOF in string")
|
||||||
}
|
}
|
||||||
l.lexeme.WriteByte(curByte)
|
l.lexeme.WriteByte(curByte)
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ looper:
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *readerLexer) peek() int {
|
func (l *ReaderLexer) peek() int {
|
||||||
if l.nextByte != noValue {
|
if l.nextByte != noValue {
|
||||||
return l.nextByte
|
return l.nextByte
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ func (l *readerLexer) peek() int {
|
|||||||
return l.nextByte
|
return l.nextByte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *readerLexer) emit(t int) {
|
func (l *ReaderLexer) emit(t int) {
|
||||||
l.setItem(t, l.pos, l.lexeme.Bytes())
|
l.setItem(t, l.pos, l.lexeme.Bytes())
|
||||||
l.pos += Pos(l.lexeme.Len())
|
l.pos += Pos(l.lexeme.Len())
|
||||||
l.hasItem = true
|
l.hasItem = true
|
||||||
@ -117,18 +117,18 @@ func (l *readerLexer) emit(t int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *readerLexer) setItem(typ int, pos Pos, val []byte) {
|
func (l *ReaderLexer) setItem(typ int, pos Pos, val []byte) {
|
||||||
l.item.typ = typ
|
l.item.typ = typ
|
||||||
l.item.pos = pos
|
l.item.pos = pos
|
||||||
l.item.val = val
|
l.item.val = val
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *readerLexer) ignore() {
|
func (l *ReaderLexer) ignore() {
|
||||||
l.pos += Pos(l.lexeme.Len())
|
l.pos += Pos(l.lexeme.Len())
|
||||||
l.lexeme.Reset()
|
l.lexeme.Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *readerLexer) next() (*Item, bool) {
|
func (l *ReaderLexer) next() (*Item, bool) {
|
||||||
l.lexeme.Reset()
|
l.lexeme.Reset()
|
||||||
for {
|
for {
|
||||||
if l.currentStateFn == nil {
|
if l.currentStateFn == nil {
|
||||||
@ -145,14 +145,14 @@ func (l *readerLexer) next() (*Item, bool) {
|
|||||||
return &l.item, false
|
return &l.item, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *readerLexer) errorf(format string, args ...interface{}) stateFn {
|
func (l *ReaderLexer) errorf(format string, args ...interface{}) stateFn {
|
||||||
l.setItem(lexError, l.pos, []byte(fmt.Sprintf(format, args...)))
|
l.setItem(lexError, l.pos, []byte(fmt.Sprintf(format, args...)))
|
||||||
l.lexeme.Truncate(0)
|
l.lexeme.Truncate(0)
|
||||||
l.hasItem = true
|
l.hasItem = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *readerLexer) reset() {
|
func (l *ReaderLexer) reset() {
|
||||||
l.bufInput.Reset(l.input)
|
l.bufInput.Reset(l.input)
|
||||||
l.lexeme.Reset()
|
l.lexeme.Reset()
|
||||||
l.nextByte = noValue
|
l.nextByte = noValue
|
||||||
|
@ -5,31 +5,31 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sliceLexer struct {
|
type SliceLexer struct {
|
||||||
lex
|
lex
|
||||||
input []byte // the []byte being scanned.
|
input []byte // the []byte being scanned.
|
||||||
start Pos // start position of this Item.
|
start Pos // start position of this Item.
|
||||||
pos Pos // current position in the input
|
pos Pos // current position in the input
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSliceLexer(input []byte, initial stateFn) *sliceLexer {
|
func NewSliceLexer(input []byte, initial stateFn) *SliceLexer {
|
||||||
l := &sliceLexer{
|
l := &SliceLexer{
|
||||||
lex: newLex(initial),
|
lex: newLex(initial),
|
||||||
input: input,
|
input: input,
|
||||||
}
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *sliceLexer) take() int {
|
func (l *SliceLexer) take() int {
|
||||||
if int(l.pos) >= len(l.input) {
|
if int(l.pos) >= len(l.input) {
|
||||||
return eof
|
return eof
|
||||||
}
|
}
|
||||||
r := int(l.input[l.pos])
|
r := int(l.input[l.pos])
|
||||||
l.pos += 1
|
l.pos++
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *sliceLexer) takeString() error {
|
func (l *SliceLexer) takeString() error {
|
||||||
curPos := l.pos
|
curPos := l.pos
|
||||||
inputLen := len(l.input)
|
inputLen := len(l.input)
|
||||||
|
|
||||||
@ -67,14 +67,14 @@ looper:
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *sliceLexer) peek() int {
|
func (l *SliceLexer) peek() int {
|
||||||
if int(l.pos) >= len(l.input) {
|
if int(l.pos) >= len(l.input) {
|
||||||
return eof
|
return eof
|
||||||
}
|
}
|
||||||
return int(l.input[l.pos])
|
return int(l.input[l.pos])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *sliceLexer) emit(t int) {
|
func (l *SliceLexer) emit(t int) {
|
||||||
l.setItem(t, l.start, l.input[l.start:l.pos])
|
l.setItem(t, l.start, l.input[l.start:l.pos])
|
||||||
l.hasItem = true
|
l.hasItem = true
|
||||||
|
|
||||||
@ -91,17 +91,17 @@ func (l *sliceLexer) emit(t int) {
|
|||||||
l.start = l.pos
|
l.start = l.pos
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *sliceLexer) setItem(typ int, pos Pos, val []byte) {
|
func (l *SliceLexer) setItem(typ int, pos Pos, val []byte) {
|
||||||
l.item.typ = typ
|
l.item.typ = typ
|
||||||
l.item.pos = pos
|
l.item.pos = pos
|
||||||
l.item.val = val
|
l.item.val = val
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *sliceLexer) ignore() {
|
func (l *SliceLexer) ignore() {
|
||||||
l.start = l.pos
|
l.start = l.pos
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *sliceLexer) next() (*Item, bool) {
|
func (l *SliceLexer) next() (*Item, bool) {
|
||||||
for {
|
for {
|
||||||
if l.currentStateFn == nil {
|
if l.currentStateFn == nil {
|
||||||
break
|
break
|
||||||
@ -117,14 +117,14 @@ func (l *sliceLexer) next() (*Item, bool) {
|
|||||||
return &l.item, false
|
return &l.item, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *sliceLexer) errorf(format string, args ...interface{}) stateFn {
|
func (l *SliceLexer) errorf(format string, args ...interface{}) stateFn {
|
||||||
l.setItem(lexError, l.start, []byte(fmt.Sprintf(format, args...)))
|
l.setItem(lexError, l.start, []byte(fmt.Sprintf(format, args...)))
|
||||||
l.start = l.pos
|
l.start = l.pos
|
||||||
l.hasItem = true
|
l.hasItem = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *sliceLexer) reset() {
|
func (l *SliceLexer) reset() {
|
||||||
l.start = 0
|
l.start = 0
|
||||||
l.pos = 0
|
l.pos = 0
|
||||||
l.lex = newLex(l.initialState)
|
l.lex = newLex(l.initialState)
|
||||||
|
27
path.go
27
path.go
@ -33,6 +33,7 @@ type operator struct {
|
|||||||
whereClause []Item
|
whereClause []Item
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nolint:gocognit
|
||||||
func genIndexKey(tr tokenReader) (*operator, error) {
|
func genIndexKey(tr tokenReader) (*operator, error) {
|
||||||
k := &operator{}
|
k := &operator{}
|
||||||
var t *Item
|
var t *Item
|
||||||
@ -63,34 +64,36 @@ func genIndexKey(tr tokenReader) (*operator, error) {
|
|||||||
if t, ok = tr.next(); !ok {
|
if t, ok = tr.next(); !ok {
|
||||||
return nil, errors.New("Expected number or *, but got none")
|
return nil, errors.New("Expected number or *, but got none")
|
||||||
}
|
}
|
||||||
|
|
||||||
switch t.typ {
|
switch t.typ {
|
||||||
case pathIndexRange:
|
case pathIndexRange:
|
||||||
if t, ok = tr.next(); !ok {
|
if t, ok = tr.next(); !ok {
|
||||||
return nil, errors.New("Expected number or *, but got none")
|
return nil, errors.New("expected number or *, but got none")
|
||||||
}
|
}
|
||||||
|
|
||||||
switch t.typ {
|
switch t.typ {
|
||||||
case pathIndex:
|
case pathIndex:
|
||||||
v, err := strconv.Atoi(string(t.val))
|
v, err := strconv.Atoi(string(t.val))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Could not parse %q into int64", t.val)
|
return nil, fmt.Errorf("could not parse %q into int64", t.val)
|
||||||
}
|
}
|
||||||
k.indexEnd = v - 1
|
k.indexEnd = v - 1
|
||||||
k.hasIndexEnd = true
|
k.hasIndexEnd = true
|
||||||
|
|
||||||
if t, ok = tr.next(); !ok || t.typ != pathBracketRight {
|
if t, ok = tr.next(); !ok || t.typ != pathBracketRight {
|
||||||
return nil, errors.New("Expected ], but got none")
|
return nil, errors.New("expected ], but got none")
|
||||||
}
|
}
|
||||||
case pathBracketRight:
|
case pathBracketRight:
|
||||||
k.hasIndexEnd = false
|
k.hasIndexEnd = false
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unexpected value within brackets after index: %q", t.val)
|
return nil, fmt.Errorf("unexpected value within brackets after index: %q", t.val)
|
||||||
}
|
}
|
||||||
|
|
||||||
k.typ = opTypeIndexRange
|
k.typ = opTypeIndexRange
|
||||||
case pathBracketRight:
|
case pathBracketRight:
|
||||||
k.typ = opTypeIndex
|
k.typ = opTypeIndex
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unexpected value within brackets after index: %q", t.val)
|
return nil, fmt.Errorf("unexpected value within brackets after index: %q", t.val)
|
||||||
}
|
}
|
||||||
case pathKey:
|
case pathKey:
|
||||||
k.keyStrings = map[string]struct{}{
|
k.keyStrings = map[string]struct{}{
|
||||||
@ -99,10 +102,10 @@ func genIndexKey(tr tokenReader) (*operator, error) {
|
|||||||
k.typ = opTypeName
|
k.typ = opTypeName
|
||||||
|
|
||||||
if t, ok = tr.next(); !ok || t.typ != pathBracketRight {
|
if t, ok = tr.next(); !ok || t.typ != pathBracketRight {
|
||||||
return nil, errors.New("Expected ], but got none")
|
return nil, errors.New("expected ], but got none")
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unexpected value within brackets: %q", t.val)
|
return nil, fmt.Errorf("unexpected value within brackets: %q", t.val)
|
||||||
}
|
}
|
||||||
|
|
||||||
return k, nil
|
return k, nil
|
||||||
@ -166,21 +169,26 @@ func tokensToOperators(tr tokenReader) (*Path, error) {
|
|||||||
return nil, errors.New("Unexpected root node after start")
|
return nil, errors.New("Unexpected root node after start")
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case pathCurrent:
|
case pathCurrent:
|
||||||
if len(q.operators) != 0 {
|
if len(q.operators) != 0 {
|
||||||
return nil, errors.New("Unexpected current node after start")
|
return nil, errors.New("Unexpected current node after start")
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case pathPeriod:
|
case pathPeriod:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case pathBracketLeft:
|
case pathBracketLeft:
|
||||||
k, err := genIndexKey(tr)
|
k, err := genIndexKey(tr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
q.operators = append(q.operators, k)
|
q.operators = append(q.operators, k)
|
||||||
|
|
||||||
case pathKey:
|
case pathKey:
|
||||||
keyName := p.val
|
keyName := p.val
|
||||||
|
|
||||||
if len(p.val) == 0 {
|
if len(p.val) == 0 {
|
||||||
return nil, fmt.Errorf("Key length is zero at %d", p.pos)
|
return nil, fmt.Errorf("Key length is zero at %d", p.pos)
|
||||||
}
|
}
|
||||||
@ -196,11 +204,15 @@ func tokensToOperators(tr tokenReader) (*Path, error) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
case pathWildcard:
|
case pathWildcard:
|
||||||
q.operators = append(q.operators, &operator{typ: opTypeNameWild})
|
q.operators = append(q.operators, &operator{typ: opTypeNameWild})
|
||||||
|
|
||||||
case pathValue:
|
case pathValue:
|
||||||
q.captureEndValue = true
|
q.captureEndValue = true
|
||||||
|
|
||||||
case pathWhere:
|
case pathWhere:
|
||||||
|
|
||||||
case pathExpression:
|
case pathExpression:
|
||||||
if len(q.operators) == 0 {
|
if len(q.operators) == 0 {
|
||||||
return nil, errors.New("Cannot add where clause on last key")
|
return nil, errors.New("Cannot add where clause on last key")
|
||||||
@ -210,6 +222,7 @@ func tokensToOperators(tr tokenReader) (*Path, error) {
|
|||||||
return nil, errors.New("Expression on last key already set")
|
return nil, errors.New("Expression on last key already set")
|
||||||
}
|
}
|
||||||
last.whereClauseBytes = p.val
|
last.whereClauseBytes = p.val
|
||||||
|
|
||||||
case pathError:
|
case pathError:
|
||||||
return q, errors.New(string(p.val))
|
return q, errors.New(string(p.val))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user