jsonpath/eval_states.go

211 lines
3.7 KiB
Go

package jsonpath
import (
"errors"
"fmt"
)
func evalRoot(e *Eval, i *Item) evalStateFn {
switch i.typ {
case jsonBraceLeft:
e.levelStack.push(i.typ)
return evalObjectAfterOpen
case jsonBracketLeft:
e.levelStack.push(i.typ)
return evalArrayAfterOpen
case jsonError:
return evalError(e, i)
default:
e.Error = errors.New(UnexpectedToken)
}
return nil
}
func evalObjectAfterOpen(e *Eval, i *Item) evalStateFn {
switch i.typ {
case jsonKey:
c := i.val[1 : len(i.val)-1]
if e.copyValues {
d := make([]byte, len(c))
copy(d, c)
c = d
}
e.nextKey = c
return evalObjectColon
case jsonBraceRight:
return rightBraceOrBracket(e)
case jsonError:
return evalError(e, i)
default:
e.Error = errors.New(UnexpectedToken)
}
return nil
}
func evalObjectColon(e *Eval, i *Item) evalStateFn {
switch i.typ {
case jsonColon:
return evalObjectValue
case jsonError:
return evalError(e, i)
default:
e.Error = errors.New(UnexpectedToken)
}
return nil
}
func evalObjectValue(e *Eval, i *Item) evalStateFn {
e.location.push(e.nextKey)
switch i.typ {
case jsonNull, jsonNumber, jsonString, jsonBool:
return evalObjectAfterValue
case jsonBraceLeft:
e.levelStack.push(i.typ)
return evalObjectAfterOpen
case jsonBracketLeft:
e.levelStack.push(i.typ)
return evalArrayAfterOpen
case jsonError:
return evalError(e, i)
default:
e.Error = errors.New(UnexpectedToken)
}
return nil
}
func evalObjectAfterValue(e *Eval, i *Item) evalStateFn {
e.location.pop()
switch i.typ {
case jsonComma:
return evalObjectAfterOpen
case jsonBraceRight:
return rightBraceOrBracket(e)
case jsonError:
return evalError(e, i)
default:
e.Error = errors.New(UnexpectedToken)
}
return nil
}
func rightBraceOrBracket(e *Eval) evalStateFn {
e.levelStack.pop()
lowerTyp, ok := e.levelStack.peek()
if !ok {
return evalRootEnd
}
switch lowerTyp {
case jsonBraceLeft:
return evalObjectAfterValue
case jsonBracketLeft:
return evalArrayAfterValue
}
return nil
}
func evalArrayAfterOpen(e *Eval, i *Item) evalStateFn {
e.prevIndex = -1
switch i.typ {
case jsonNull, jsonNumber, jsonString, jsonBool, jsonBraceLeft, jsonBracketLeft:
return evalArrayValue(e, i)
case jsonBracketRight:
setPrevIndex(e)
return rightBraceOrBracket(e)
case jsonError:
return evalError(e, i)
default:
e.Error = errors.New(UnexpectedToken)
}
return nil
}
func evalArrayValue(e *Eval, i *Item) evalStateFn {
e.prevIndex++
e.location.push(e.prevIndex)
switch i.typ {
case jsonNull, jsonNumber, jsonString, jsonBool:
return evalArrayAfterValue
case jsonBraceLeft:
e.levelStack.push(i.typ)
return evalObjectAfterOpen
case jsonBracketLeft:
e.levelStack.push(i.typ)
return evalArrayAfterOpen
case jsonError:
return evalError(e, i)
default:
e.Error = errors.New(UnexpectedToken)
}
return nil
}
func evalArrayAfterValue(e *Eval, i *Item) evalStateFn {
switch i.typ {
case jsonComma:
if val, ok := e.location.pop(); ok {
if valIndex, ok := val.(int); ok {
e.prevIndex = valIndex
}
}
return evalArrayValue
case jsonBracketRight:
e.location.pop()
setPrevIndex(e)
return rightBraceOrBracket(e)
case jsonError:
return evalError(e, i)
default:
e.Error = errors.New(UnexpectedToken)
}
return nil
}
func setPrevIndex(e *Eval) {
e.prevIndex = -1
peeked, ok := e.location.peek()
if ok {
if peekedIndex, intOk := peeked.(int); intOk {
e.prevIndex = peekedIndex
}
}
}
func evalRootEnd(e *Eval, i *Item) evalStateFn {
if i.typ != jsonEOF {
if i.typ == jsonError {
evalError(e, i)
} else {
e.Error = errors.New(BadStructure)
}
}
return nil
}
func evalError(e *Eval, i *Item) evalStateFn {
e.Error = fmt.Errorf("%s at byte index %d", string(i.val), i.pos)
return nil
}