Mercurial > pub > ImplabNet
annotate Implab/JSON/JSONGrammar.cs @ 160:5802131432e4 v2
fixed regression: race condition in Promise
DFA refactoring
author | cin |
---|---|
date | Thu, 18 Feb 2016 19:38:54 +0300 |
parents | 97fbbf816844 |
children |
rev | line source |
---|---|
55 | 1 using Implab.Parsing; |
2 using System.Linq; | |
3 | |
4 namespace Implab.JSON { | |
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
72
diff
changeset
|
5 class JSONGrammar : Grammar<JSONGrammar> { |
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
72
diff
changeset
|
6 public enum TokenType { |
55 | 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)); | |
72 | 81 |
55 | 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 } |