jsonpath/json_states.go

298 lines
5.4 KiB
Go
Raw Normal View History

2019-02-26 13:05:15 +04:00
package jsonpath
const (
jsonError = iota
jsonEOF
jsonBraceLeft
jsonBraceRight
jsonBracketLeft
jsonBracketRight
jsonColon
jsonComma
jsonNumber
jsonString
jsonNull
jsonKey
jsonBool
)
var trueBytes = []byte{'t', 'r', 'u', 'e'}
var falseBytes = []byte{'f', 'a', 'l', 's', 'e'}
var nullBytes = []byte{'n', 'u', 'l', 'l'}
var jsonTokenNames = map[int]string{
jsonEOF: "EOF",
jsonError: "ERROR",
jsonBraceLeft: "{",
jsonBraceRight: "}",
jsonBracketLeft: "[",
jsonBracketRight: "]",
jsonColon: ":",
jsonComma: ",",
jsonNumber: "NUMBER",
jsonString: "STRING",
jsonNull: "NULL",
jsonKey: "KEY",
jsonBool: "BOOL",
}
2019-10-19 01:41:57 +04:00
var JSON = lexJSONRoot
2019-02-26 13:05:15 +04:00
2019-10-19 01:41:57 +04:00
func lexJSONRoot(l lexer, state *intStack) stateFn {
2019-02-26 13:05:15 +04:00
var next stateFn
2019-10-19 01:41:57 +04:00
2019-10-19 02:14:19 +04:00
ignoreSpaceRun(l)
cur := l.peek()
2019-02-26 13:05:15 +04:00
switch cur {
case '{':
next = stateJSONObjectOpen
2019-02-26 13:05:15 +04:00
case '[':
next = stateJSONArrayOpen
2019-02-26 13:05:15 +04:00
default:
next = l.errorf("Expected '{' or '[' at root of JSON instead of %#U", cur)
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
return next
}
func stateJSONObjectOpen(l lexer, state *intStack) stateFn {
2019-02-26 13:05:15 +04:00
cur := l.take()
if cur != '{' {
return l.errorf("Expected '{' as start of object instead of %#U", cur)
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
l.emit(jsonBraceLeft)
state.push(jsonBraceLeft)
return stateJSONObject
2019-02-26 13:05:15 +04:00
}
func stateJSONArrayOpen(l lexer, state *intStack) stateFn {
2019-02-26 13:05:15 +04:00
cur := l.take()
if cur != '[' {
return l.errorf("Expected '[' as start of array instead of %#U", cur)
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
l.emit(jsonBracketLeft)
state.push(jsonBracketLeft)
return stateJSONArray
2019-02-26 13:05:15 +04:00
}
func stateJSONObject(l lexer, state *intStack) stateFn {
2019-02-26 13:05:15 +04:00
var next stateFn
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
cur := l.peek()
switch cur {
case '}':
if top, ok := state.peek(); ok && top != jsonBraceLeft {
next = l.errorf("Received %#U but has no matching '{'", cur)
break
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
l.take()
l.emit(jsonBraceRight)
state.pop()
2019-10-19 02:14:19 +04:00
next = stateJSONAfterValue
2019-02-26 13:05:15 +04:00
case '"':
next = stateJSONKey
2019-02-26 13:05:15 +04:00
default:
next = l.errorf("Expected '}' or \" within an object instead of %#U", cur)
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
return next
}
func stateJSONArray(l lexer, state *intStack) stateFn {
2019-02-26 13:05:15 +04:00
var next stateFn
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
cur := l.peek()
switch cur {
case ']':
if top, ok := state.peek(); ok && top != jsonBracketLeft {
next = l.errorf("Received %#U but has no matching '['", cur)
break
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
l.take()
l.emit(jsonBracketRight)
state.pop()
2019-10-19 02:14:19 +04:00
next = stateJSONAfterValue
2019-02-26 13:05:15 +04:00
default:
next = stateJSONValue
2019-02-26 13:05:15 +04:00
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
return next
}
func stateJSONAfterValue(l lexer, state *intStack) stateFn {
2019-02-26 13:05:15 +04:00
cur := l.take()
topVal := noValue
2019-10-19 02:14:19 +04:00
top, ok := state.peek()
2019-02-26 13:05:15 +04:00
if ok {
topVal = top
}
switch cur {
case ',':
l.emit(jsonComma)
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
switch topVal {
case jsonBraceLeft:
return stateJSONKey
2019-02-26 13:05:15 +04:00
case jsonBracketLeft:
return stateJSONValue
2019-02-26 13:05:15 +04:00
case noValue:
return l.errorf("found %#U outside of array or object", cur)
2019-02-26 13:05:15 +04:00
default:
return l.errorf("unexpected character in lexer stack: %#U", cur)
2019-02-26 13:05:15 +04:00
}
case '}':
l.emit(jsonBraceRight)
state.pop()
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
switch topVal {
case jsonBraceLeft:
return stateJSONAfterValue
2019-02-26 13:05:15 +04:00
case jsonBracketLeft:
return l.errorf("unexpected %#U in array", cur)
2019-02-26 13:05:15 +04:00
case noValue:
return stateJSONAfterRoot
2019-02-26 13:05:15 +04:00
}
case ']':
l.emit(jsonBracketRight)
state.pop()
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
switch topVal {
case jsonBraceLeft:
return l.errorf("unexpected %#U in object", cur)
2019-02-26 13:05:15 +04:00
case jsonBracketLeft:
return stateJSONAfterValue
2019-02-26 13:05:15 +04:00
case noValue:
return stateJSONAfterRoot
2019-02-26 13:05:15 +04:00
}
case eof:
if state.len() == 0 {
l.emit(jsonEOF)
return nil
}
return l.errorf("unexpected EOF instead of value")
2019-02-26 13:05:15 +04:00
default:
return l.errorf("unexpected character after json value token: %#U", cur)
2019-02-26 13:05:15 +04:00
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
return nil
}
func stateJSONKey(l lexer, state *intStack) stateFn {
2019-02-26 13:05:15 +04:00
if err := l.takeString(); err != nil {
return l.errorf(err.Error())
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
l.emit(jsonKey)
return stateJSONColon
2019-02-26 13:05:15 +04:00
}
func stateJSONColon(l lexer, state *intStack) stateFn {
2019-02-26 13:05:15 +04:00
cur := l.take()
if cur != ':' {
2019-10-19 02:14:19 +04:00
return l.errorf("expected ':' after key string instead of %#U", cur)
2019-02-26 13:05:15 +04:00
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
l.emit(jsonColon)
return stateJSONValue
2019-02-26 13:05:15 +04:00
}
func stateJSONValue(l lexer, state *intStack) stateFn {
2019-02-26 13:05:15 +04:00
cur := l.peek()
switch cur {
case eof:
return l.errorf("Unexpected EOF instead of value")
case '"':
return stateJSONString
2019-02-26 13:05:15 +04:00
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return stateJSONNumber
2019-02-26 13:05:15 +04:00
case 't', 'f':
return stateJSONBool
2019-02-26 13:05:15 +04:00
case 'n':
return stateJSONNull
2019-02-26 13:05:15 +04:00
case '{':
return stateJSONObjectOpen
2019-02-26 13:05:15 +04:00
case '[':
return stateJSONArrayOpen
2019-02-26 13:05:15 +04:00
default:
2019-10-19 02:14:19 +04:00
return l.errorf("unexpected character as start of value: %#U", cur)
2019-02-26 13:05:15 +04:00
}
}
func stateJSONString(l lexer, state *intStack) stateFn {
2019-02-26 13:05:15 +04:00
if err := l.takeString(); err != nil {
return l.errorf(err.Error())
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
l.emit(jsonString)
2019-10-19 02:14:19 +04:00
return stateJSONAfterValue
2019-02-26 13:05:15 +04:00
}
func stateJSONNumber(l lexer, state *intStack) stateFn {
2019-02-26 13:05:15 +04:00
if err := takeJSONNumeric(l); err != nil {
return l.errorf(err.Error())
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
l.emit(jsonNumber)
2019-10-19 02:14:19 +04:00
return stateJSONAfterValue
2019-02-26 13:05:15 +04:00
}
func stateJSONBool(l lexer, state *intStack) stateFn {
2019-02-26 13:05:15 +04:00
var match []byte
2019-10-19 02:14:19 +04:00
cur := l.peek()
2019-02-26 13:05:15 +04:00
switch cur {
case 't':
match = trueBytes
case 'f':
match = falseBytes
}
if !takeExactSequence(l, match) {
return l.errorf("Could not parse value as 'true' or 'false'")
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
l.emit(jsonBool)
2019-10-19 02:14:19 +04:00
return stateJSONAfterValue
2019-02-26 13:05:15 +04:00
}
func stateJSONNull(l lexer, state *intStack) stateFn {
2019-02-26 13:05:15 +04:00
if !takeExactSequence(l, nullBytes) {
return l.errorf("Could not parse value as 'null'")
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
l.emit(jsonNull)
2019-10-19 02:14:19 +04:00
return stateJSONAfterValue
2019-02-26 13:05:15 +04:00
}
func stateJSONAfterRoot(l lexer, state *intStack) stateFn {
2019-02-26 13:05:15 +04:00
cur := l.take()
if cur != eof {
return l.errorf("Expected EOF instead of %#U", cur)
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
l.emit(jsonEOF)
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
return nil
}