ln.json/JSONParser.cs

322 lines
8.8 KiB
C#

using System;
using sharp.parser;
using Microsoft.Win32.SafeHandles;
using System.Globalization;
using System.Net.Mime;
using System.Collections.Generic;
namespace sharp.json
{
public class JSONParser : Parser<JSON>
{
delegate JSON ParseObjectDelegate(TokenQueue tokens);
Dictionary<TokenDefinition, ParseObjectDelegate> parserDelegates = new Dictionary<TokenDefinition, ParseObjectDelegate>();
public JSONParser()
:base(tokenDefinitions)
{
parserDelegates.Add(tString,parseString);
parserDelegates.Add(tNumber,parseNumber);
parserDelegates.Add(tObjectOpen,parseObject);
parserDelegates.Add(tArrayOpen,parseArray);
parserDelegates.Add(tTrue,parseTrue);
parserDelegates.Add(tFalse,parseFalse);
parserDelegates.Add(tNull,parseNull);
}
protected override JSON ParseTokens(Token[] tokens)
{
TokenQueue qtoken = new TokenQueue();
foreach (Token t in tokens){
if (t.Definition != tWhiteSpace){
qtoken.Enqueue(t);
}
}
return parseValue(qtoken);
}
private JSON parseValue(TokenQueue tokens){
foreach (TokenDefinition tdef in this.parserDelegates.Keys){
if (tdef == tokens.Peek().Definition){
return this.parserDelegates[tokens.Peek().Definition](tokens);
}
}
throw new Exception(String.Format("Parser got unexpected token: {0}", tokens.Peek().ToString()));
}
JSON parseString(TokenQueue tokens){
Token t = tokens.Expect(tString);
return new JSONString(t.Value.Substring(1, t.Value.Length - 2));
}
JSON parseNumber(TokenQueue tokens)
{
Token t = tokens.Expect(tNumber);
Double dv = double.Parse(t.Value,CultureInfo.InvariantCulture);
return new JSONNumber(dv);
}
JSON parseObject(TokenQueue tokens)
{
Token t = tokens.Expect(tObjectOpen);
JSONObject jo = new JSONObject();
if (tokens.Peek().Definition == tObjectClose){
tokens.Dequeue();
return jo;
}
do
{
JSONString js = (JSONString)parseString(tokens);
tokens.Expect(tColon);
JSON json = parseValue(tokens);
jo[js.String] = json;
t = tokens.Expect(tObjectClose, tComma);
if (t.Definition == tObjectClose){
break;
}
} while (true);
return jo;
}
JSON parseArray(TokenQueue tokens)
{
Token t = tokens.Expect(tArrayOpen);
JSONArray ja = new JSONArray();
if (tokens.Peek().Definition == tArrayClose)
{
tokens.Dequeue();
return ja;
}
do
{
JSON json = parseValue(tokens);
ja.Add(json);
t = tokens.Expect(tArrayClose, tComma);
if (t.Definition == tArrayClose)
{
break;
}
} while (true);
return ja;
}
JSON parseTrue(TokenQueue tokens)
{
if (tokens.Peek().Definition == tTrue){
Token t = tokens.Dequeue();
return JSONSpecial.True;
}
throw new Exception("Unexpected Token: " + tokens.Peek());
}
JSON parseFalse(TokenQueue tokens)
{
if (tokens.Peek().Definition == tFalse){
Token t = tokens.Dequeue();
return JSONSpecial.False;
}
throw new Exception("Unexpected Token: " + tokens.Peek());
}
JSON parseNull(TokenQueue tokens)
{
if (tokens.Peek().Definition == tNull){
Token t = tokens.Dequeue();
return JSONSpecial.Null;
}
throw new Exception("Unexpected Token: " + tokens.Peek());
}
static bool initializer = initialize();
static TokenDefinition[] tokenDefinitions;
static CharGroup eE = new CharGroup(new char[] { 'e', 'E' } );
static LexerPathSegment null_ll;
static LexerPathSegment null_l;
static LexerPathSegment null_u;
static LexerPathSegment null_n;
static LexerPathSegment true_e;
static LexerPathSegment true_u;
static LexerPathSegment true_r;
static LexerPathSegment true_t;
static LexerPathSegment false_e;
static LexerPathSegment false_s;
static LexerPathSegment false_l;
static LexerPathSegment false_a;
static LexerPathSegment false_f;
static LexerPathSegment ws;
static TokenDefinition tNumber;
static TokenDefinition tString;
static TokenDefinition tColon;
static TokenDefinition tComma;
static TokenDefinition tObjectOpen;
static TokenDefinition tObjectClose;
static TokenDefinition tArrayOpen;
static TokenDefinition tArrayClose;
static TokenDefinition tTrue;
static TokenDefinition tFalse;
static TokenDefinition tNull;
static TokenDefinition tWhiteSpace;
static private bool initialize(){
eE = new CharGroup(new char[] { 'e', 'E' });
null_ll = new LexerPathSegment('l', true);
null_l = new LexerPathSegment('l', null_ll);
null_u = new LexerPathSegment('u', null_l);
null_n = new LexerPathSegment('n', null_u);
true_e = new LexerPathSegment('e', true);
true_u = new LexerPathSegment('u', true_e);
true_r = new LexerPathSegment('r', true_u);
true_t = new LexerPathSegment('t', true_r);
false_e = new LexerPathSegment('e', true);
false_s = new LexerPathSegment('s', false_e);
false_l = new LexerPathSegment('l', false_s);
false_a = new LexerPathSegment('a', false_l);
false_f = new LexerPathSegment('f', false_a);
ws = new LexerPathSegment(CharGroup.WS, true);
ws.AddFollower(ws);
tNumber = new TokenDefinition("JSON.number", initializeNumberHead());
tString = new TokenDefinition("JSON.string", initializeStringHead());
tColon = new TokenDefinition("JSON.colon", new LexerPathSegment(':',true));
tComma = new TokenDefinition("JSON.comma", new LexerPathSegment(',',true));
tObjectOpen = new TokenDefinition("JSON.obj.open", new LexerPathSegment('{',true));
tObjectClose = new TokenDefinition("JSON.obj.close", new LexerPathSegment('}',true));
tArrayOpen = new TokenDefinition("JSON.array.open", new LexerPathSegment('[',true));
tArrayClose = new TokenDefinition("JSON.array.close", new LexerPathSegment(']',true));
tTrue = new TokenDefinition("JSON.true", true_t);
tFalse = new TokenDefinition("JSON.false", false_f);
tNull = new TokenDefinition("JSON.null", null_n);
tWhiteSpace = new TokenDefinition("JSON.WhiteSpace",ws);
tokenDefinitions = new TokenDefinition[]{
tWhiteSpace,
tNumber,
tString,
tColon,
tComma,
tObjectOpen,
tObjectClose,
tArrayOpen,
tArrayClose,
tTrue,
tFalse,
tNull
};
return true;
}
static private LexerPathSegment initializeStringHead(){
LexerPathSegment head = new LexerPathSegment('\"');
LexerPathSegment finish = new LexerPathSegment('\"',true);
LexerPathSegment backslash = new LexerPathSegment('\\');
LexerPathSegment control = new LexerPathSegment(new char[] { '\"','\\','/','b','f','n','r','t'} );
LexerPathSegment u4 = new LexerPathSegment(CharGroup.hexdigits);
LexerPathSegment u3 = new LexerPathSegment(CharGroup.hexdigits,u4);
LexerPathSegment u2 = new LexerPathSegment(CharGroup.hexdigits,u3);
LexerPathSegment u1 = new LexerPathSegment(CharGroup.hexdigits,u2);
LexerPathSegment ucontrol = new LexerPathSegment('u',u1);
CharGroup anyChar = new CharGroup((char)0x20, (char)0xff) - backslash.CharGroup - finish.CharGroup;
LexerPathSegment any = new LexerPathSegment(anyChar);
head.AddFollower(finish);
head.AddFollower(any);
head.AddFollower(backslash);
any.AddFollower(any);
any.AddFollower(backslash);
any.AddFollower(finish);
backslash.AddFollower(control);
backslash.AddFollower(ucontrol);
control.AddFollower(any);
control.AddFollower(backslash);
control.AddFollower(finish);
u4.AddFollower(any);
u4.AddFollower(backslash);
u4.AddFollower(finish);
return head;
}
static private LexerPathSegment initializeNumberHead()
{
LexerPathSegment head = new LexerPathSegment();
LexerPathSegment minus = new LexerPathSegment(CharGroup.minus);
LexerPathSegment zero = new LexerPathSegment('0',true);
LexerPathSegment d19 = new LexerPathSegment('1', '9', true);
LexerPathSegment digit_a = new LexerPathSegment(CharGroup.digit,true);
LexerPathSegment digit_b = new LexerPathSegment(CharGroup.digit,true);
LexerPathSegment digit_c = new LexerPathSegment(CharGroup.digit,true);
LexerPathSegment dot = new LexerPathSegment('.');
LexerPathSegment ee = new LexerPathSegment(eE);
LexerPathSegment eminus = new LexerPathSegment(CharGroup.minus);
LexerPathSegment plusminus = new LexerPathSegment(CharGroup.plusminus);
head.AddFollower(minus);
head.AddFollower(zero);
head.AddFollower(d19);
minus.AddFollower(zero);
minus.AddFollower(d19);
zero.AddFollower(dot);
zero.AddFollower(ee);
d19.AddFollower(digit_a);
d19.AddFollower(dot);
d19.AddFollower(ee);
digit_a.AddFollower(digit_a);
digit_a.AddFollower(dot);
digit_a.AddFollower(ee);
dot.AddFollower(digit_b);
digit_b.AddFollower(digit_b);
digit_b.AddFollower(ee);
ee.AddFollower(digit_c);
ee.AddFollower(plusminus);
plusminus.AddFollower(digit_c);
digit_c.AddFollower(digit_c);
return head;
}
}
}