comparison Implab/Formats/JSON/JSONGrammar.cs @ 163:419aa51b04fd ref20160224

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