/* JSON parser */ var JsonTypeNull = 0;; var JsonTypeString = 1;; var JsonTypeNumber = 2;; var JsonTypeBool = 3;; var JsonTypeObject = 4;; var JsonTypeArray = 5;; struct JsonValue = [ JSONV_iType : I, JSONV_sValue : S, JSONV_fValue : F, JSONV_bValue : I, JSONV_object : [[S JsonValue] r1], JSONV_array : [JsonValue r1] ]mkJsonValue;; struct JsonData = [ JSOND_sContent : S, JSOND_ipos : I ]mkJsonData;; proto parseJsonValue = fun [JsonData] JsonValue;; fun getCurJsonChar(jsdata)= nth_char jsdata.JSOND_sContent jsdata.JSOND_ipos;; fun skipJsonWhitespace(jsdata)= let strlen jsdata.JSOND_sContent -> lenght in while ((jsdata.JSOND_ipos < lenght) && (isSpace (getCurJsonChar jsdata))) do set jsdata.JSOND_ipos = jsdata.JSOND_ipos + 1; jsdata.JSOND_ipos;; fun readNextJsonChar(jsdata)= nth_char jsdata.JSOND_sContent jsdata.JSOND_ipos + 1;; fun getNextJsonChar(jsdata)= let getCurJsonChar jsdata -> c in ( set jsdata.JSOND_ipos = jsdata.JSOND_ipos + 1; c; );; fun getNextJsonCharWithSkip(jsdata)= skipJsonWhitespace jsdata; getNextJsonChar jsdata;; fun exportJson(jsvalue)= let "" -> result in ( if (jsvalue.JSONV_iType == JsonTypeString) then set result = strcatn "\""::(protectParam strtoutf8 jsvalue.JSONV_sValue)::"\""::nil else if (jsvalue.JSONV_iType == JsonTypeNumber) then set result = getShortFloatToString jsvalue.JSONV_fValue else if (jsvalue.JSONV_iType == JsonTypeObject) then ( set result = "{"; let jsvalue.JSONV_object -> l in let 0 -> pos in while (l != nil) do ( let hd l -> [key element] in ( if (pos == 0) then nil else set result = strcat result ","; set result = strcat result strcatn "\""::key::"\": "::(exportJson element)::nil; ); set l = tl l; set pos = pos + 1; ); set result = strcat result "}"; ) else if (jsvalue.JSONV_iType == JsonTypeArray) then ( set result = "["; let jsvalue.JSONV_array -> l in let 0 -> pos in while (l != nil) do ( let hd l -> element in ( if (pos == 0) then nil else set result = strcat result ","; set result = strcat result (exportJson element); ); set l = tl l; set pos = pos + 1; ); set result = strcat result "]"; ) else if (jsvalue.JSONV_iType == JsonTypeBool) then set result = if jsvalue.JSONV_bValue then "true" else "false" else if (jsvalue.JSONV_iType == JsonTypeNull) then set result = "null" else nil; result; );; fun parseJsonString(jsdata)= //addLogMessage "parseJsonString"; let "" -> value in ( let -1 -> c in let strlen jsdata.JSOND_sContent -> lenght in while ((jsdata.JSOND_ipos < lenght) && ((set c = getNextJsonChar jsdata) != 34)) do //" ( if (c == 92) then // \ ( // Handle escape characters let getNextJsonChar jsdata -> escaped in if (escaped == 110) then //n set value = strcat value "\n" else if (escaped == 116) then //t set value = strcat value "\t" else if (escaped == 117) then //u unicode set value = strcat value "\\u" else set value = strcat value ctoa escaped; ) else set value = strcat value ctoa c; ); mkJsonValue [JsonTypeString utf8tostr value 0.0 0 nil nil]; );; fun parseJsonNumber(jsdata, c)= //addLogMessage "parseJsonNumber"; let ctoa c -> value in ( let strlen jsdata.JSOND_sContent -> lenght in while ((jsdata.JSOND_ipos < lenght) && ((isDigit (getCurJsonChar jsdata)) || (getCurJsonChar jsdata) == 46)) do ( let getNextJsonChar jsdata -> c in set value = strcat value ctoa c; ); mkJsonValue [JsonTypeNumber "" (atof value) 0 nil nil]; );; fun parseJsonObject(jsdata)= //addLogMessage "parseJsonObject"; let nil -> jobject in // [S JsonValue] r1 let 0 -> error in ( let -1 -> c in let strlen jsdata.JSOND_sContent -> lenght in while (!error && (jsdata.JSOND_ipos < lenght) && ((set c = getNextJsonCharWithSkip jsdata) != 125)) do //} ( if (c == 34) then //" ( // Parse key let parseJsonString jsdata -> key in ( //addLogMessage strcat "key > " key.JSONV_sValue; // Expect colon if ((getNextJsonCharWithSkip jsdata) == 58) then nil else //: ( addLogMessage strcat "JsonParser error: Expected colon in object. At pos: " itoa (jsdata.JSOND_ipos); //addLogMessage itoa getCurJsonChar jsdata; set error = 1; ); // Parse value let parseJsonValue jsdata -> value in set jobject = lcat jobject [key.JSONV_sValue value]::nil; ); // Check for more items or end of object skipJsonWhitespace jsdata; if ((getCurJsonChar jsdata) == 44) then //, ( getNextJsonCharWithSkip jsdata; ) else if ((getCurJsonChar jsdata) != 125) then //} ( addLogMessage strcat "JsonParser error: Expected comma or end of object. At pos: " itoa (jsdata.JSOND_ipos); //addLogMessage itoa getCurJsonChar jsdata; set error = 1; ) else nil; 0; ) else ( addLogMessage strcat "JsonParser error: Expected string key in object. At pos: " itoa (jsdata.JSOND_ipos); //addLogMessage itoa c; set error = 1; ); ); mkJsonValue [JsonTypeObject "" 0.0 0 jobject nil]; );; fun parseJsonArray(jsdata)= //addLogMessage "parseJsonArray"; let nil -> jarray in // [S JsonValue] r1 let 0 -> error in ( let -1 -> c in let strlen jsdata.JSOND_sContent -> lenght in while (!error && (jsdata.JSOND_ipos < lenght) && (set c = getCurJsonChar jsdata) != 93) do //] ( let parseJsonValue jsdata -> element in set jarray = lcat jarray element::nil; // Check for more items or end of array skipJsonWhitespace jsdata; if ((getCurJsonChar jsdata) == 44) then //, ( getNextJsonCharWithSkip jsdata; ) else if ((getCurJsonChar jsdata) != 93) then //] ( addLogMessage strcat "JsonParser error: Expected comma or end of array. At pos: " itoa (jsdata.JSOND_ipos); //addLogMessage substr jsdata.JSOND_sContent jsdata.JSOND_ipos 50; set error = 1; ) else nil; ); getNextJsonCharWithSkip jsdata; mkJsonValue [JsonTypeArray "" 0.0 0 nil jarray]; );; fun parseJsonValue(jsdata)= //addLogMessage "parseJsonValue"; let getNextJsonCharWithSkip jsdata -> c in if (c == 34) then //" parseJsonString jsdata else if (isDigit c || c == 45) then //- parseJsonNumber jsdata c else if (c == 123) then //{ parseJsonObject jsdata else if (c == 91) then //[ parseJsonArray jsdata else if (isAlpha c) then let ctoa c -> word in ( // Parse true, false, or null while (isAlpha (getCurJsonChar jsdata)) do ( set word = strcat word ctoa (getNextJsonChar jsdata); ); if (!strcmpi word "true") then mkJsonValue [JsonTypeBool "" 0.0 1 nil nil] else if (!strcmpi word "false") then mkJsonValue [JsonTypeBool "" 0.0 0 nil nil] else if (!strcmpi word "null") then mkJsonValue [JsonTypeNull "" 0.0 0 nil nil] else ( addLogMessage strcat "JsonParser error: Invalid keyword in JSON. Word found: " word; nil; ); ) else ( addLogMessage strcat "JsonParser error: Unexpected character in JSON. At pos: " itoa (jsdata.JSOND_ipos); //addLogMessage itoa c; nil; );; fun getJsonObject(jvalue)= if ((jvalue.JSONV_iType) != JsonTypeObject) then nil else jvalue.JSONV_object;; fun getJsonObjectValue(jvalue, name)= if ((jvalue.JSONV_iType) != JsonTypeObject) then nil else switchstr jvalue.JSONV_object name;; fun getJsonArray(jvalue)= if ((jvalue.JSONV_iType) != JsonTypeArray) then nil else jvalue.JSONV_array;; fun getJsonString(jvalue)= if ((jvalue.JSONV_iType) != JsonTypeString) then nil else jvalue.JSONV_sValue;; fun getJsonBoolean(jvalue)= if ((jvalue.JSONV_iType) != JsonTypeBool) then nil else jvalue.JSONV_bValue;; fun getJsonFloat(jvalue)= if ((jvalue.JSONV_iType) != JsonTypeNumber) then nil else jvalue.JSONV_fValue;; fun getJsonInt(jvalue)= if ((jvalue.JSONV_iType) != JsonTypeNumber) then nil else ftoi jvalue.JSONV_fValue;; fun isJsonNull(jvalue)= if ((jvalue.JSONV_iType) != JsonTypeNull) then 0 else 1;; // lvalues [S JsonValue] r1 fun makeJsonObject(lvalues)= mkJsonValue [JsonTypeObject "" 0.0 0 lvalues nil];; fun makeJsonArray(larray)= mkJsonValue [JsonTypeArray "" 0.0 0 nil larray];; fun makeJsonString(value)= mkJsonValue [JsonTypeString value 0.0 0 nil nil];; fun makeJsonNumF(value)= mkJsonValue [JsonTypeNumber "" value 0 nil nil];; fun makeJsonNum(value)= mkJsonValue [JsonTypeNumber "" (itof value) 0 nil nil];; fun makeJsonBool(value)= mkJsonValue [JsonTypeBool "" 0.0 value nil nil];; fun makeJsonNull(value)= mkJsonValue [JsonTypeNull "" 0.0 0 nil nil];; fun parseJson(s)= let mkJsonData [s 0] -> jsdata in ( parseJsonValue jsdata; );;