aboutsummaryrefslogblamecommitdiff
path: root/example/json/main.go
blob: 745e5aa6e5bc8255d9869c0a1a7e9c7d393ae2bf (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
















                                          












                                                        








                                  







                                          






                                                 
                                    


                                    
                                                              

 


























                                                                                    
                                   


                                    
                                   

                             
                                   
































                                                              
         
                           





                                                   
// +build ignore

package main

import (
	"fmt"

	"github.com/neonxp/unilex"
)

func main() {
	testJson := `
	{
		"key1": "value1",
		"key2": {
			"key3" : "value 3"
		},
		"key4": 123.321,
		"key5": [
			1,
			2,
			[
				3,
				4,
				5,
				{
					"key6": "value6"
				}
			]
		]
	}`
	l := unilex.New(testJson)
	go l.Run(initJson)
	for ll := range l.Output {
		fmt.Println(ll)
	}
}

const (
	lObjectStart unilex.LexType = iota
	lObjectEnd
	lObjectKey
	lObjectValue
	lArrayStart
	lArrayEnd
	lString
	lNumber
)

func initJson(l *unilex.Lexer) unilex.StateFunc {
	ignoreWhiteSpace(l)
	switch {
	case l.Accept("{"):
		l.Emit(lObjectStart)
		return stateInObject
	case l.Peek() == unilex.EOF:
		return nil
	}
	return l.Errorf("Unknown token: %s", string(l.Peek()))
}

func stateInObject(l *unilex.Lexer) unilex.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 !unilex.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 unilex.ScanQuotedString(l, '"'):
		l.Emit(lString)
		ignoreWhiteSpace(l)
		l.Accept(",")
		l.Ignore()
		ignoreWhiteSpace(l)
		return stateInObject
	case unilex.ScanNumber(l):
		l.Emit(lNumber)
		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 *unilex.Lexer) unilex.StateFunc {
	ignoreWhiteSpace(l)
	l.Accept(",")
	ignoreWhiteSpace(l)
	switch {
	case unilex.ScanQuotedString(l, '"'):
		l.Emit(lString)
	case unilex.ScanNumber(l):
		l.Emit(lNumber)
	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 *unilex.Lexer) {
	l.AcceptWhile(" \n\t") //ignore whitespaces
	l.Ignore()
}