Created
November 7, 2012 12:20
-
-
Save lexich/4031186 to your computer and use it in GitHub Desktop.
Own realization SAX parser of JSON
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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