From 76a7f461ebbde70ea0e3d4f9b79c08139acaee7c Mon Sep 17 00:00:00 2001 From: NeonXP Date: Tue, 27 Dec 2022 02:37:02 +0300 Subject: Completely rewrited --- internal/lexer/states.go | 110 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 internal/lexer/states.go (limited to 'internal/lexer/states.go') 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() +} -- cgit v1.2.3