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