Skip to content

Instantly share code, notes, and snippets.

@lexich
Created November 7, 2012 12:20
Show Gist options
  • Save lexich/4031186 to your computer and use it in GitHub Desktop.
Save lexich/4031186 to your computer and use it in GitHub Desktop.
Own realization SAX parser of JSON
JSON2 =
OBJECT:"Object"
ARRAY:"Array"
nextToken: (buf,i)->
token = undefined
isWord = false
isNum = false
isFloat = false
str = ""
while i < buf.length
ch = buf.charCodeAt(i)
++i
switch ch
when 123, 125, 58, 91, 93, 44 #'{' '}' ':' '[' ']' ','
return [String.fromCharCode(ch),str,i]
when 34 #"
isWord = not isWord
unless isWord then return ["w",str,i]
else
if ch is 46 and isNum #.
unless isFloat
isFloat = true
else
throw new Error("more then one char '.' in number token")
if not isWord and ch >= 48 and ch <= 57 #[0..9]
isNum = true
if isWord or isNum
str += String.fromCharCode(ch)
if isNum and i + 1 < buf.length
ch = buf.charCodeAt(i+1)
if (ch < 48 or ch > 57) and ch != 46
return \
unless isFloat
['i',parseInt(str),i]
else
["f",parseFloat(str),i]
["","",i]
processValue: (obj,key,value,type)->
if type is @OBJECT
if key? and value? and obj?
obj[key] = value
else
throw new Error("Invalid params for [#{type}]: key:'#{key}' value:'#{value}' obj:'#{obj}'")
else if type is @ARRAY
if value? and obj?
obj.push value
else
throw new Error("Invalid params for [#{type}]: value:'#{value}' obj:'#{obj}'")
else
throw new Error("Unknown type")
key = null
value = null
[obj,key,value,type]
_parse: (buf,obj,i, type)->
key = null
value = null
try
while i < buf.length
[token,v,i] = @nextToken(buf,i)
switch token
when "{"
[i,value] = @_parse(buf,{},i,@OBJECT)
when "["
[i,value] = @_parse(buf,[],i, @ARRAY)
when "}","]"
[obj,key,value,type] = @processValue(obj,key,value,type)
return [i,obj]
when ","
[obj,key,value,type] = @processValue(obj,key,value,type)
when ":"
key = value
value = null
when "w", "i", "f"
value = v
catch e
e.buf = buf
e.i = i
throw e
[i,value]
parse: (buf)->
try
@_parse(buf,{},0,@OBJECT)[1]
catch e
throw new Error("msg:#{e.message} text:#{e.buf.slice(0,e.i).to}")
DATA = """
{
"one":[0,"1",0,"3","4","9"],
"two":"three",
"four":{
1:"one",
"five":1.0,
"six":3
}
}
"""
res = JSON2.parse DATA.toString()
if res.one.length == 6 then console.log("PASS") else console.error("FAIL")
if res.one[0] == 0 then console.log("PASS") else console.error("FAIL")
if res.one[1] == "1" then console.log("PASS") else console.error("FAIL")
if res.two == "three" then console.log("PASS") else console.error("FAIL")
if res.four["1"]=="one" then console.log("PASS") else console.error("FAIL")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment