aboutsummaryrefslogblamecommitdiff
path: root/parser/states.go
blob: 92c80dceba4f9f04f484bc69e1e7e63d19cd3065 (plain) (tree)













































































































                                                                                    
package parser

func initJson(l *lexer) stateFunc {
	ignoreWhiteSpace(l)
	switch {
	case l.Accept("{"):
		l.Emit(lObjectStart)
		return stateInObject
	case l.Accept("["):
		l.Emit(lArrayStart)
	case l.Peek() == eof:
		return nil
	}
	return l.Errorf("Unknown token: %s", string(l.Peek()))
}

func stateInObject(l *lexer) stateFunc {
	// we in object, so we expect field keys and values
	ignoreWhiteSpace(l)
	if l.Accept("}") {
		l.Emit(lObjectEnd)
		// If meet close object return to previous state (including initial)
		return l.PopState()
	}
	ignoreWhiteSpace(l)
	l.Accept(",")
	ignoreWhiteSpace(l)
	if !scanQuotedString(l, '"') {
		return l.Errorf("Unknown token: %s", string(l.Peek()))
	}
	l.Emit(lObjectKey)
	ignoreWhiteSpace(l)
	if !l.Accept(":") {
		return l.Errorf("Expected ':'")
	}
	ignoreWhiteSpace(l)
	l.Emit(lObjectValue)
	switch {
	case scanQuotedString(l, '"'):
		l.Emit(lString)
		ignoreWhiteSpace(l)
		l.Accept(",")
		l.Ignore()
		ignoreWhiteSpace(l)
		return stateInObject
	case scanNumber(l):
		l.Emit(lNumber)
		ignoreWhiteSpace(l)
		l.Accept(",")
		l.Ignore()
		ignoreWhiteSpace(l)
		return stateInObject
	case l.AcceptAnyOf([]string{"true", "false"}, true):
		l.Emit(lBoolean)
		ignoreWhiteSpace(l)
		l.Accept(",")
		l.Ignore()
		ignoreWhiteSpace(l)
		return stateInObject
	case l.AcceptString("null", true):
		l.Emit(lNull)
		ignoreWhiteSpace(l)
		l.Accept(",")
		l.Ignore()
		ignoreWhiteSpace(l)
		return stateInObject
	case l.Accept("{"):
		l.Emit(lObjectStart)
		l.PushState(stateInObject)
		return stateInObject
	case l.Accept("["):
		l.Emit(lArrayStart)
		l.PushState(stateInObject)
		return stateInArray
	}
	return l.Errorf("Unknown token: %s", string(l.Peek()))
}

func stateInArray(l *lexer) stateFunc {
	ignoreWhiteSpace(l)
	l.Accept(",")
	ignoreWhiteSpace(l)
	switch {
	case scanQuotedString(l, '"'):
		l.Emit(lString)
	case scanNumber(l):
		l.Emit(lNumber)
	case l.AcceptAnyOf([]string{"true", "false"}, true):
		l.Emit(lBoolean)
	case l.AcceptString("null", true):
		l.Emit(lNull)
	case l.Accept("{"):
		l.Emit(lObjectStart)
		l.PushState(stateInArray)
		return stateInObject
	case l.Accept("["):
		l.Emit(lArrayStart)
		l.PushState(stateInArray)
		return stateInArray
	case l.Accept("]"):
		l.Emit(lArrayEnd)
		return l.PopState()
	}
	return stateInArray
}

func ignoreWhiteSpace(l *lexer) {
	l.AcceptWhile(" \n\t") // ignore whitespaces
	l.Ignore()
}