2019-08-07 23:02:00 +02:00
|
|
|
|
// /**
|
|
|
|
|
// * 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;
|
2017-11-03 13:13:09 +01:00
|
|
|
|
using System.Collections.Generic;
|
2019-08-07 23:02:00 +02:00
|
|
|
|
using ln.types;
|
|
|
|
|
using ln.types.stream;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
namespace ln.json
|
2017-11-03 13:13:09 +01:00
|
|
|
|
{
|
2019-08-07 23:02:00 +02:00
|
|
|
|
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<ch.Length;n++)
|
|
|
|
|
{
|
|
|
|
|
ch[n] = chars.Current;
|
|
|
|
|
chars.MoveNext();
|
|
|
|
|
}
|
|
|
|
|
if (ch.AreEqual(chNull))
|
|
|
|
|
{
|
|
|
|
|
chars.Skip(char.IsWhiteSpace);
|
|
|
|
|
return JSONNull.Instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new FormatException();
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-11-03 13:13:09 +01:00
|
|
|
|
}
|