diff options
Diffstat (limited to 'parser/states.go')
-rw-r--r-- | parser/states.go | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/parser/states.go b/parser/states.go new file mode 100644 index 0000000..92c80dc --- /dev/null +++ b/parser/states.go @@ -0,0 +1,110 @@ +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() +} |