X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=json.tcl;h=9d382e673e4fdde740f6abaa72118afdc3f7cc22;hb=5d26694fefe30bc2d4340aba1b1f8b7c71f6183d;hp=746a8df43360eeee774cbee27ffa59759f445101;hpb=a001e5b2a382980d9f453c38d83db367e15c27a5;p=scpubgit%2FTenDotTcl.git diff --git a/json.tcl b/json.tcl index 746a8df..9d382e6 100644 --- a/json.tcl +++ b/json.tcl @@ -60,11 +60,10 @@ namespace eval ten::json { proc deparse {data} { switch -regexp [lindex $data 0] { - ^true|false|null$ { uplevel 1 return [lindex $data 0] } - ^num|str|obj|list$ {} + ^true|false|null$ { lindex $data 0 } + ^num|str|obj|list$ { eval $data } default { error [ concat "Invalid JSON type " [lindex $data 0 0] ] } } - return [ eval $data ] } } @@ -95,19 +94,118 @@ namespace eval ten::json { ^num|str|obj|list$ {} default { error [ concat "Invalid JSON type " [lindex $data 0 0] ] } } - return [ eval $data ] + eval $data } } proc tclify_json {data} { tclify::tclify $data } + + namespace eval parse { + + variable json + + proc eat_comma {} { + variable json + set json [string trimleft $json] + if {[string index $json 0] eq ","} { + set json [string range $json 1 end] + } + } + + proc eat_char {} { + variable json + set json [ string range $json 1 end ] + } + + proc parse_list {} { + variable json + eat_char + set tcl {list} + while {"$json" ne ""} { + if {[string index $json 0] eq "]"} { + eat_char + return $tcl + } + lappend tcl [ parse ] + eat_comma + } + error "Ran out of JSON. Confused now." + } + + proc parse_str {} { + variable json + # like Text::Balanced except ugly (borrowed from tcvJSON's code) + set reStr {(?:(?:\")(?:[^\\\"]*(?:\\.[^\\\"]*)*)(?:\"))} + if {![regexp $reStr $json string]} { + error [ concat "Invalid string: " [string range $json 0 32] + } + set json [string range $json [string length $string] end] + # chop off outer ""s and substitute backslashes + # This does more than the RFC-specified backslash sequences, + # but it does cover them all + list str [subst -nocommand -novariable [string range $string 1 end-1]] + } + + proc parse_num {} { + variable json + string is double -failindex last $json + if {$last == 0} { + error "Saw number but wasn't - $json" + } + set num [string range $json 0 [expr {$last - 1}]] + set json [string range $json $last end] + list num $num + } + + proc parse {} { + variable json + set json [string trimleft $json] + if {$json eq ""} { + return + } + switch -regexp [string index $json 0] { + {\{} { parse_obj } + {\[} { parse_list } + {\"} { parse_str } + + {[-0-9]} { parse_num } + + default { error "argh" } + } + } + } + + proc parse_json {json} { + set parse::json [ string trim $json ] + set result [ parse::parse ] + if {[string trimleft $parse::json] ne ""} { + error "Had JSON left over: $parse::json" + } + return $result + } } set ex_json { list {str foo} {num 0} {obj __remote_object__ {str 512}} {null} } +set jtext { + [ + "foo", + 0, + { + "__remote_object__": "512", + }, + null, + ] +} + puts [ ten::json::deparse_json $ex_json 2 ] dict for {k v} [ ten::json::tclify_json [ lindex [ ten::json::tclify_json $ex_json ] 2 ] ] { puts "$k: $v" } + +#puts [ ten::json::parse_json $jtext ] + +puts [ ten::json::parse_json {["foo",2345,["bar"]]} ]