comparison Implab/JSON/JSONGrammar.cs @ 55:c0bf853aa04f

Added initial JSON support +JSONParser +JSONWriter
author cin
date Sun, 15 Jun 2014 19:39:11 +0400
parents
children d67b95eddaf4
comparison
equal deleted inserted replaced
51:2c332a9c64c0 55:c0bf853aa04f
1 using Implab.Parsing;
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6 using System.Threading.Tasks;
7
8 namespace Implab.JSON {
9 internal class JSONGrammar : Grammar<JSONGrammar> {
10 public enum TokenType : int{
11 None,
12 BeginObject,
13 EndObject,
14 BeginArray,
15 EndArray,
16 String,
17 Number,
18 Literal,
19 NameSeparator,
20 ValueSeparator,
21
22 StringBound,
23 EscapedChar,
24 UnescapedChar,
25 EscapedUnicode,
26
27 Minus,
28 Plus,
29 Sign,
30 Integer,
31 Dot,
32 Exp
33 }
34
35 readonly CDFADefinition m_jsonDFA;
36 readonly CDFADefinition m_stringDFA;
37
38 public JSONGrammar() {
39 DefineAlphabet(Enumerable.Range(0, 0x20).Select(x => (char)x));
40 var hexDigit = SymbolRangeToken('a','f').Or(SymbolRangeToken('A','F')).Or(SymbolRangeToken('0','9'));
41 var digit9 = SymbolRangeToken('1', '9');
42 var zero = SymbolToken('0');
43 var digit = zero.Or(digit9);
44 var dot = SymbolToken('.');
45 var minus = SymbolToken('-');
46 var sign = SymbolSetToken('-', '+');
47 var expSign = SymbolSetToken('e', 'E');
48 var letters = SymbolRangeToken('a', 'z');
49 var integer = zero.Or(digit9.Cat(digit.EClosure()));
50 var frac = dot.Cat(digit.Closure());
51 var exp = expSign.Cat(sign.Optional()).Cat(digit.Closure());
52 var quote = SymbolToken('"');
53 var backSlash = SymbolToken('\\');
54 var specialEscapeChars = SymbolSetToken('\\', '"', '/', 'b', 'f', 't', 'n', 'r');
55 var unicodeEspace = SymbolToken('u').Cat(hexDigit.Repeat(4));
56 var escape = backSlash.Cat(specialEscapeChars.Or(unicodeEspace));
57 var whitespace = SymbolSetToken('\n', '\r', '\t', ' ').EClosure();
58 var beginObject = whitespace.Cat(SymbolToken('{')).Cat(whitespace);
59 var endObject = whitespace.Cat(SymbolToken('}')).Cat(whitespace);
60 var beginArray = whitespace.Cat(SymbolToken('[')).Cat(whitespace);
61 var endArray = whitespace.Cat(SymbolToken(']')).Cat(whitespace);
62 var nameSep = whitespace.Cat(SymbolToken(':')).Cat(whitespace);
63 var valueSep = whitespace.Cat(SymbolToken(',')).Cat(whitespace);
64
65 var number = minus.Optional().Cat(integer).Cat(frac.Optional()).Cat(exp.Optional());
66 var literal = letters.Closure();
67 var unescaped = SymbolTokenExcept(Enumerable.Range(0, 0x20).Union(new int[] { '\\', '"' }).Select(x => (char)x));
68 var character = unescaped.Or(escape);
69 var str = quote.Cat(character.EClosure()).Cat(quote);
70
71
72 var jsonExpression =
73 number.Tag(TokenType.Number)
74 .Or(literal.Tag(TokenType.Literal))
75 .Or(quote.Tag(TokenType.StringBound))
76 .Or(beginObject.Tag(TokenType.BeginObject))
77 .Or(endObject.Tag(TokenType.EndObject))
78 .Or(beginArray.Tag(TokenType.BeginArray))
79 .Or(endArray.Tag(TokenType.EndArray))
80 .Or(nameSep.Tag(TokenType.NameSeparator))
81 .Or(valueSep.Tag(TokenType.ValueSeparator));
82
83
84 var jsonStringExpression =
85 quote.Tag(TokenType.StringBound)
86 .Or(backSlash.Cat(specialEscapeChars).Tag(TokenType.EscapedChar))
87 .Or(backSlash.Cat(unicodeEspace).Tag(TokenType.EscapedUnicode))
88 .Or(unescaped.Closure().Tag(TokenType.UnescapedChar));
89
90 var jsonNumberExpression =
91 minus.Tag(TokenType.Minus)
92 .Or(SymbolToken('+').Tag(TokenType.Plus))
93 .Or(digit.Closure().Tag(TokenType.Integer))
94 .Or(dot.Tag(TokenType.Dot))
95 .Or(expSign.Tag(TokenType.Exp));
96
97 m_jsonDFA = BuildDFA(jsonExpression);
98 m_stringDFA = BuildDFA(jsonStringExpression);
99 }
100
101 public CDFADefinition JsonDFA {
102 get {
103 return m_jsonDFA;
104 }
105 }
106
107 public CDFADefinition JsonStringDFA {
108 get {
109 return m_stringDFA;
110 }
111 }
112 }
113 }