jsonpath/json_states.go

267 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",
}
var JSON = lexJsonRoot
func lexJsonRoot(l lexer, state *intStack) stateFn {
ignoreSpaceRun(l)
cur := l.peek()
var next stateFn
switch cur {
case '{':
next = stateJsonObjectOpen
case '[':
next = stateJsonArrayOpen
default:
next = l.errorf("Expected '{' or '[' at root of JSON instead of %#U", cur)
}
return next
}
func stateJsonObjectOpen(l lexer, state *intStack) stateFn {
cur := l.take()
if cur != '{' {
return l.errorf("Expected '{' as start of object instead of %#U", cur)
}
l.emit(jsonBraceLeft)
state.push(jsonBraceLeft)
return stateJsonObject
}
func stateJsonArrayOpen(l lexer, state *intStack) stateFn {
cur := l.take()
if cur != '[' {
return l.errorf("Expected '[' as start of array instead of %#U", cur)
}
l.emit(jsonBracketLeft)
state.push(jsonBracketLeft)
return stateJsonArray
}
func stateJsonObject(l lexer, state *intStack) stateFn {
var next stateFn
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
}
l.take()
l.emit(jsonBraceRight)
state.pop()
next = stateJsonAfterValue
case '"':
next = stateJsonKey
default:
next = l.errorf("Expected '}' or \" within an object instead of %#U", cur)
}
return next
}
func stateJsonArray(l lexer, state *intStack) stateFn {
var next stateFn
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
}
l.take()
l.emit(jsonBracketRight)
state.pop()
next = stateJsonAfterValue
default:
next = stateJsonValue
}
return next
}
func stateJsonAfterValue(l lexer, state *intStack) stateFn {
cur := l.take()
top, ok := state.peek()
topVal := noValue
if ok {
topVal = top
}
switch cur {
case ',':
l.emit(jsonComma)
switch topVal {
case jsonBraceLeft:
return stateJsonKey
case jsonBracketLeft:
return stateJsonValue
case noValue:
return l.errorf("Found %#U outside of array or object", cur)
default:
return l.errorf("Unexpected character in lexer stack: %#U", cur)
}
case '}':
l.emit(jsonBraceRight)
state.pop()
switch topVal {
case jsonBraceLeft:
return stateJsonAfterValue
case jsonBracketLeft:
return l.errorf("Unexpected %#U in array", cur)
case noValue:
return stateJsonAfterRoot
}
case ']':
l.emit(jsonBracketRight)
state.pop()
switch topVal {
case jsonBraceLeft:
return l.errorf("Unexpected %#U in object", cur)
case jsonBracketLeft:
return stateJsonAfterValue
case noValue:
return stateJsonAfterRoot
}
case eof:
if state.len() == 0 {
l.emit(jsonEOF)
return nil
} else {
return l.errorf("Unexpected EOF instead of value")
}
default:
return l.errorf("Unexpected character after json value token: %#U", cur)
}
return nil
}
func stateJsonKey(l lexer, state *intStack) stateFn {
if err := l.takeString(); err != nil {
return l.errorf(err.Error())
}
l.emit(jsonKey)
return stateJsonColon
}
func stateJsonColon(l lexer, state *intStack) stateFn {
cur := l.take()
if cur != ':' {
return l.errorf("Expected ':' after key string instead of %#U", cur)
}
l.emit(jsonColon)
return stateJsonValue
}
func stateJsonValue(l lexer, state *intStack) stateFn {
cur := l.peek()
switch cur {
case eof:
return l.errorf("Unexpected EOF instead of value")
case '"':
return stateJsonString
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return stateJsonNumber
case 't', 'f':
return stateJsonBool
case 'n':
return stateJsonNull
case '{':
return stateJsonObjectOpen
case '[':
return stateJsonArrayOpen
default:
return l.errorf("Unexpected character as start of value: %#U", cur)
}
}
func stateJsonString(l lexer, state *intStack) stateFn {
if err := l.takeString(); err != nil {
return l.errorf(err.Error())
}
l.emit(jsonString)
return stateJsonAfterValue
}
func stateJsonNumber(l lexer, state *intStack) stateFn {
if err := takeJSONNumeric(l); err != nil {
return l.errorf(err.Error())
}
l.emit(jsonNumber)
return stateJsonAfterValue
}
func stateJsonBool(l lexer, state *intStack) stateFn {
cur := l.peek()
var match []byte
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'")
}
l.emit(jsonBool)
return stateJsonAfterValue
}
func stateJsonNull(l lexer, state *intStack) stateFn {
if !takeExactSequence(l, nullBytes) {
return l.errorf("Could not parse value as 'null'")
}
l.emit(jsonNull)
return stateJsonAfterValue
}
func stateJsonAfterRoot(l lexer, state *intStack) stateFn {
cur := l.take()
if cur != eof {
return l.errorf("Expected EOF instead of %#U", cur)
}
l.emit(jsonEOF)
return nil
}