Initial working version.
This commit is contained in:
+320
@@ -0,0 +1,320 @@
|
||||
package jaeson
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"gitea.cozeon.cloud/anand.ekka-ext/parser"
|
||||
"github.com/antlr/antlr4/runtime/Go/antlr"
|
||||
)
|
||||
|
||||
type stackElem struct {
|
||||
jsObj *JSONObject
|
||||
jsArr *JSONArray
|
||||
hasJsObj bool
|
||||
hasJsArr bool
|
||||
}
|
||||
|
||||
func (v *stackElem) Init() {
|
||||
v.hasJsObj = false
|
||||
v.hasJsArr = false
|
||||
}
|
||||
|
||||
func (v *stackElem) GetJsObj() *JSONObject {
|
||||
return v.jsObj
|
||||
}
|
||||
func (v *stackElem) GetJsArr() *JSONArray {
|
||||
return v.jsArr
|
||||
}
|
||||
|
||||
func (v *stackElem) GetHasJsObj() bool {
|
||||
return v.hasJsObj
|
||||
}
|
||||
func (v *stackElem) GetHasJsArr() bool {
|
||||
return v.hasJsArr
|
||||
}
|
||||
|
||||
func (v *stackElem) PutJSONObject(jsnObj *JSONObject) {
|
||||
v.hasJsObj = true
|
||||
v.hasJsArr = false
|
||||
v.jsObj = jsnObj
|
||||
}
|
||||
|
||||
func (v *stackElem) PutJSONArray(jsnArr *JSONArray) {
|
||||
v.hasJsObj = false
|
||||
v.hasJsArr = true
|
||||
v.jsArr = jsnArr
|
||||
}
|
||||
|
||||
type jsonListener struct {
|
||||
*parser.BaseJSONListener
|
||||
|
||||
topJsObj *JSONObject
|
||||
|
||||
currJsObj *JSONObject
|
||||
currJsArr *JSONArray
|
||||
currKey string
|
||||
|
||||
childJsObj *JSONObject
|
||||
childJsArr *JSONArray
|
||||
|
||||
foundKeyOfPair bool
|
||||
jsonStartFound bool
|
||||
topObjCreated bool
|
||||
arrStart bool
|
||||
|
||||
parentObjStack []*stackElem
|
||||
|
||||
stckElemPointer int
|
||||
|
||||
topJsArr *JSONArray
|
||||
topArrCreated bool
|
||||
}
|
||||
|
||||
func (s *jsonListener) GetLastElem() *stackElem {
|
||||
return s.parentObjStack[s.stckElemPointer-1]
|
||||
}
|
||||
|
||||
func (s *jsonListener) DeleteLastElem() {
|
||||
s.parentObjStack[s.stckElemPointer-1] = nil
|
||||
s.stckElemPointer -= 1
|
||||
}
|
||||
|
||||
func (s *jsonListener) AddJSONObjToStack(jsObj *JSONObject) {
|
||||
tmpStckElem := new(stackElem)
|
||||
tmpStckElem.Init()
|
||||
s.stckElemPointer += 1
|
||||
|
||||
if s.stckElemPointer > len(s.parentObjStack) {
|
||||
s.parentObjStack = append(s.parentObjStack, tmpStckElem)
|
||||
} else {
|
||||
s.parentObjStack[s.stckElemPointer-1] = tmpStckElem
|
||||
}
|
||||
|
||||
tmpStckElem.PutJSONObject(jsObj)
|
||||
}
|
||||
|
||||
func (s *jsonListener) AddJSONArrToStack(jsArr *JSONArray) {
|
||||
tmpStckElem := new(stackElem)
|
||||
tmpStckElem.Init()
|
||||
s.stckElemPointer += 1
|
||||
|
||||
if s.stckElemPointer > len(s.parentObjStack) {
|
||||
s.parentObjStack = append(s.parentObjStack, tmpStckElem)
|
||||
} else {
|
||||
s.parentObjStack[s.stckElemPointer-1] = tmpStckElem
|
||||
}
|
||||
|
||||
tmpStckElem.PutJSONArray(jsArr)
|
||||
}
|
||||
|
||||
//--------------- Json Enter-Exit ---------------//
|
||||
func (s *jsonListener) EnterJson(ctx *parser.JsonContext) {
|
||||
s.jsonStartFound = true
|
||||
s.topObjCreated = false
|
||||
s.stckElemPointer = 0
|
||||
}
|
||||
|
||||
func (s *jsonListener) ExitJson(ctx *parser.JsonContext) {
|
||||
// nothing needs to be implemented
|
||||
}
|
||||
|
||||
//--------------- Obj Enter-Exit ---------------//
|
||||
func (s *jsonListener) EnterObj(ctx *parser.ObjContext) {
|
||||
|
||||
if !s.topObjCreated && !s.topArrCreated {
|
||||
s.topJsObj = new(JSONObject)
|
||||
s.topJsObj.Init()
|
||||
s.currJsObj = s.topJsObj
|
||||
s.foundKeyOfPair = false
|
||||
|
||||
s.topObjCreated = true
|
||||
s.arrStart = false
|
||||
|
||||
//initialize stack
|
||||
s.parentObjStack = make([]*stackElem, 0)
|
||||
|
||||
//Add topJsObj to stack
|
||||
s.AddJSONObjToStack(s.topJsObj)
|
||||
|
||||
} else {
|
||||
|
||||
s.childJsObj = new(JSONObject)
|
||||
s.childJsObj.Init()
|
||||
|
||||
if s.arrStart {
|
||||
s.currJsArr.PutJSONObject(s.childJsObj)
|
||||
s.AddJSONArrToStack(s.currJsArr)
|
||||
s.currJsObj = s.childJsObj
|
||||
s.arrStart = false
|
||||
|
||||
} else {
|
||||
s.currJsObj.PutJSONObject(s.currKey, s.childJsObj)
|
||||
|
||||
// might need stack up or append curr object in a LIFO stack,
|
||||
// before takig on the new child object
|
||||
s.AddJSONObjToStack(s.currJsObj)
|
||||
|
||||
s.currJsObj = s.childJsObj
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *jsonListener) ExitObj(ctx *parser.ObjContext) {
|
||||
|
||||
tmpPrevStckElem := s.GetLastElem()
|
||||
|
||||
if tmpPrevStckElem != nil {
|
||||
if tmpPrevStckElem.GetHasJsObj() {
|
||||
s.currJsObj = tmpPrevStckElem.GetJsObj()
|
||||
s.arrStart = false
|
||||
|
||||
} else {
|
||||
s.currJsArr = tmpPrevStckElem.GetJsArr()
|
||||
s.arrStart = true
|
||||
}
|
||||
s.DeleteLastElem()
|
||||
|
||||
} //else {
|
||||
// nothing needs to be implemented
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
//--------------- Arr Enter-Exit ---------------//
|
||||
|
||||
// EnterArr is called when production arr is entered.
|
||||
func (s *jsonListener) EnterArr(ctx *parser.ArrContext) {
|
||||
|
||||
if !s.topObjCreated && !s.topArrCreated {
|
||||
|
||||
s.topJsArr = new(JSONArray)
|
||||
s.topJsArr.Init()
|
||||
s.currJsArr = s.topJsArr
|
||||
|
||||
s.topArrCreated = true
|
||||
s.arrStart = true
|
||||
|
||||
//initialize stack
|
||||
s.parentObjStack = make([]*stackElem, 0)
|
||||
|
||||
//Add topJsArr to stack
|
||||
s.AddJSONArrToStack(s.topJsArr)
|
||||
|
||||
} else {
|
||||
|
||||
if s.arrStart {
|
||||
|
||||
s.childJsArr = new(JSONArray)
|
||||
s.childJsArr.Init()
|
||||
|
||||
//add currJsArr to stack
|
||||
s.AddJSONArrToStack(s.currJsArr)
|
||||
s.currJsArr.PutJSONArray(s.childJsArr)
|
||||
s.currJsArr = s.childJsArr
|
||||
|
||||
} else {
|
||||
|
||||
s.currJsArr = new(JSONArray)
|
||||
s.currJsArr.Init()
|
||||
s.currJsObj.PutJSONArray(s.currKey, s.currJsArr)
|
||||
s.AddJSONObjToStack(s.currJsObj)
|
||||
}
|
||||
}
|
||||
s.arrStart = true
|
||||
}
|
||||
|
||||
// ExitArr is called when production arr is exited.
|
||||
func (s *jsonListener) ExitArr(ctx *parser.ArrContext) {
|
||||
s.arrStart = false
|
||||
|
||||
tmpPrevStckElem := s.GetLastElem()
|
||||
if tmpPrevStckElem.GetHasJsObj() {
|
||||
s.currJsObj = tmpPrevStckElem.GetJsObj()
|
||||
s.arrStart = false
|
||||
|
||||
} else {
|
||||
s.currJsArr = tmpPrevStckElem.GetJsArr()
|
||||
s.arrStart = true
|
||||
}
|
||||
s.DeleteLastElem()
|
||||
}
|
||||
|
||||
//--------------- Pair Enter-Exit ---------------//
|
||||
|
||||
func (s *jsonListener) EnterPair(ctx *parser.PairContext) {
|
||||
s.foundKeyOfPair = true
|
||||
s.currKey = ctx.STRING().GetSymbol().GetText()
|
||||
s.currKey = s.currKey[1 : len(s.currKey)-1]
|
||||
}
|
||||
|
||||
func (s *jsonListener) ExitPair(ctx *parser.PairContext) {
|
||||
s.foundKeyOfPair = false
|
||||
}
|
||||
|
||||
//--------------- Value Enter-Exit ---------------//
|
||||
|
||||
func (s *jsonListener) EnterValue(ctx *parser.ValueContext) {
|
||||
|
||||
if ctx.STRING() != nil {
|
||||
val0 := ctx.STRING().GetSymbol().GetText()
|
||||
val1 := val0[1 : len(val0)-1]
|
||||
|
||||
if s.arrStart {
|
||||
s.currJsArr.PutString(val1)
|
||||
} else {
|
||||
s.currJsObj.PutString(s.currKey, val1)
|
||||
}
|
||||
|
||||
}else if ctx.NUMBER() != nil {
|
||||
val0 := ctx.NUMBER().GetSymbol().GetText()
|
||||
vali, erri := strconv.ParseInt(val0, 10, 64)
|
||||
if erri != nil {
|
||||
valf, errf := strconv.ParseFloat(val0, 64)
|
||||
if errf == nil {
|
||||
s.currJsObj.PutFloat(s.currKey, valf)
|
||||
} else {
|
||||
// neither int nor float. then what is it ?
|
||||
}
|
||||
}else{
|
||||
s.currJsObj.PutInt(s.currKey, int(vali))
|
||||
}
|
||||
|
||||
//s.currJsObj.PutInt(s.currKey, val1)
|
||||
|
||||
}else if ctx.Obj() != nil {
|
||||
// nothing needs to be implemented
|
||||
|
||||
}else if ctx.BOOLEAN() != nil {
|
||||
|
||||
val0 := ctx.BOOLEAN().GetSymbol().GetText()
|
||||
val1, _ := strconv.ParseBool(val0)
|
||||
s.currJsObj.PutBool(s.currKey, val1)
|
||||
}
|
||||
s.foundKeyOfPair = false
|
||||
}
|
||||
|
||||
func (s *jsonListener) ExitValue(ctx *parser.ValueContext) {
|
||||
// nothing needs to be implemented
|
||||
}
|
||||
|
||||
func UnmarshalJSON(jsonstr string) (*JSONObject, *JSONArray) {
|
||||
|
||||
is := antlr.NewInputStream(jsonstr)
|
||||
|
||||
// Create the Lexer
|
||||
lexer := parser.NewJSONLexer(is)
|
||||
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
|
||||
|
||||
// Create the Parser
|
||||
p := parser.NewJSONParser(stream)
|
||||
|
||||
// Finally parse the expression
|
||||
var jsonLstnr *jsonListener = new(jsonListener)
|
||||
antlr.ParseTreeWalkerDefault.Walk(jsonLstnr, p.Json())
|
||||
|
||||
if jsonLstnr.topObjCreated {
|
||||
return jsonLstnr.topJsObj, nil
|
||||
|
||||
} else {
|
||||
return nil, jsonLstnr.topJsArr
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user