// /** // * File: JSONParser.cs // * Author: haraldwolff // * // * This file and it's content is copyrighted by the Author and / or copyright holder. // * Any use wihtout proper permission is illegal and may lead to legal actions. // * // * // **/ using System; using System.Collections.Generic; using ln.types; using ln.types.stream; using System.Text; using System.Globalization; namespace ln.json { public class JSONParser { static char[] chNull = new char[] { 'n', 'u', 'l', 'l' }; static char[] chTrue = new char[] { 't', 'r', 'u', 'e' }; static char[] chFalse = new char[] { 'f', 'a', 'l', 's', 'e' }; public static JSONValue Parse(String jsonSource) { CharStream chars = new CharStream(jsonSource); return ParseValue(chars); } /** * Für alle Parser Methoden welche als Parameter ein CharStream erhalten * gilt folgendes: * * - CharStream.Current zeitg auf das erste Zeichen, * welches interpretiert werden soll * - Bei Rücksprung zeigt CharStream.Current auf das erste zeichen, * welches nicht mehr zum aktuellen Wert gehört und kein Whitespace * ist * **/ static JSONValue ParseValue(CharStream chars) { chars.Skip(char.IsWhiteSpace); switch (chars.Current) { case '"': return parseString(chars); case 't': return parseTrue(chars); case 'f': return parseFalse(chars); case 'n': return parseNull(chars); case '[': return parseArray(chars); case '{': return parseObject(chars); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': return parseNumber(chars); default: throw new FormatException(String.Format("Unexpected character: {0} [ 0x{0:x4} ]", chars.Current)); } } static JSONString parseString(CharStream chars) { if (chars.Current != '"') throw new FormatException("Unexpected character"); StringBuilder stringBuilder = new StringBuilder(); chars.MoveNext(); while (chars.Current != '"') { stringBuilder.Append(chars.Current); if (chars.Current == '\\') { chars.MoveNext(); stringBuilder.Append(chars.Current); } chars.MoveNext(); } chars.TryNext(); chars.Skip(char.IsWhiteSpace); return new JSONString(JSONString.Unescape(stringBuilder.ToString())); } static JSONNumber parseNumber(CharStream chars) { StringBuilder sb = new StringBuilder(); if (chars.Current == '-') { sb.Append(chars.Current); chars.MoveNext(); } sb.Append(chars.Read(char.IsDigit)); if (chars.Current == '.') { sb.Append('.'); chars.MoveNext(); sb.Append(chars.Read(char.IsDigit)); } if ((chars.Current == 'e')|| (chars.Current == 'E')) { sb.Append('e'); if ((chars.Current == '-')|| (chars.Current == '+')) { sb.Append(chars.Current); chars.MoveNext(); } sb.Append(chars.Read(char.IsDigit)); } chars.Skip(char.IsWhiteSpace); return new JSONNumber(decimal.Parse(sb.ToString(),CultureInfo.InvariantCulture)); } static JSONArray parseArray(CharStream chars) { if (chars.Current != '[') throw new FormatException("Unexpected character"); JSONArray array = new JSONArray(); chars.MoveNext(); while (chars.Current != ']') { array.Add(ParseValue(chars)); if (chars.Current == ',') { chars.MoveNext(); chars.Skip(char.IsWhiteSpace); } } chars.TryNext(); chars.Skip(char.IsWhiteSpace); return array; } static JSONObject parseObject(CharStream chars) { if (chars.Current != '{') throw new FormatException("Unexpected character"); JSONObject o = new JSONObject(); chars.MoveNext(); chars.Skip(char.IsWhiteSpace); while (chars.Current != '}') { JSONString s = parseString(chars); if (chars.Current != ':') throw new FormatException("expected :"); chars.MoveNext(); o.Add(s.Value, ParseValue(chars)); if (chars.Current == ',') { chars.MoveNext(); chars.Skip(char.IsWhiteSpace); } } chars.TryNext(); chars.Skip(char.IsWhiteSpace); return o; } static JSONTrue parseTrue(CharStream chars) { char[] ch = new char[4]; for (int n = 0; n < ch.Length; n++) { ch[n] = chars.Current; chars.MoveNext(); } if (ch.AreEqual(chTrue)) { chars.Skip(char.IsWhiteSpace); return JSONTrue.Instance; } throw new FormatException(); } static JSONFalse parseFalse(CharStream chars) { char[] ch = new char[5]; for (int n = 0; n < ch.Length; n++) { ch[n] = chars.Current; chars.MoveNext(); } if (ch.AreEqual(chFalse)) { chars.Skip(char.IsWhiteSpace); return JSONFalse.Instance; } throw new FormatException(); } static JSONNull parseNull(CharStream chars) { char[] ch = new char[4]; for (int n=0;n