aboutsummaryrefslogtreecommitdiff
path: root/internal/lexer/states.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/lexer/states.go')
-rw-r--r--internal/lexer/states.go110
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()
+}