##// END OF EJS Templates
refactoring
cin -
r70:0349189d2564 default
parent child
Show More
@@ -1,264 +1,280
1 using Implab;
1 using Implab;
2 using Implab.Parsing;
2 using Implab.Parsing;
3 using System;
3 using System;
4 using System.Collections.Generic;
4 using System.Collections.Generic;
5 using System.Diagnostics;
5 using System.Diagnostics;
6 using System.IO;
6 using System.IO;
7 using System.Linq;
7 using System.Linq;
8 using System.Text;
8 using System.Text;
9 using System.Threading.Tasks;
9 using System.Threading.Tasks;
10
10
11 namespace Implab.JSON {
11 namespace Implab.JSON {
12 /// <summary>
12 /// <summary>
13 /// internal
13 /// internal
14 /// </summary>
14 /// </summary>
15 public struct JSONParserContext {
15 public struct JSONParserContext {
16 public string memberName;
16 public string memberName;
17 public JSONElementContext elementContext;
17 public JSONElementContext elementContext;
18 }
18 }
19
19
20 /// <summary>
20 /// <summary>
21 /// Pull парсер JSON данных.
21 /// Pull парсер JSON данных.
22 /// </summary>
22 /// </summary>
23 /// <remarks>
24 /// Следует отметить отдельную интерпретацию свойства <see cref="Level"/>,
25 /// оно означает текущий уровень вложенности объектов, однако закрывающий
26 /// элемент объекта и массива имеет уровень меньше, чем сам объект.
27 /// <code>
28 /// { // Level = 1
29 /// "name" : "Peter", // Level = 1
30 /// "address" : { // Level = 2
31 /// city : "Stern" // Level = 2
32 /// } // Level = 1
33 /// } // Level = 0
34 /// </code>
35 /// </remarks>
23 public class JSONParser : DFAutomaton<JSONParserContext>, IDisposable {
36 public class JSONParser : DFAutomaton<JSONParserContext>, IDisposable {
24
37
25 enum MemberContext {
38 enum MemberContext {
26 MemberName,
39 MemberName,
27 MemberValue
40 MemberValue
28 }
41 }
29
42
30 static readonly EnumAlphabet<JsonTokenType> _alphabet = EnumAlphabet<JsonTokenType>.FullAlphabet;
43 static readonly EnumAlphabet<JsonTokenType> _alphabet = EnumAlphabet<JsonTokenType>.FullAlphabet;
31 static readonly DFAStateDescriptior[] _jsonDFA;
44 static readonly DFAStateDescriptior[] _jsonDFA;
32 static readonly DFAStateDescriptior[] _objectDFA;
45 static readonly DFAStateDescriptior[] _objectDFA;
33 static readonly DFAStateDescriptior[] _arrayDFA;
46 static readonly DFAStateDescriptior[] _arrayDFA;
34
47
35 static JSONParser() {
48 static JSONParser() {
36 var jsonExpression = Token.New(JsonTokenType.BeginObject, JsonTokenType.BeginArray).Tag(0);
49 var jsonExpression = Token.New(JsonTokenType.BeginObject, JsonTokenType.BeginArray).Tag(0);
37
50
38 var valueExpression = Token.New(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String);
51 var valueExpression = Token.New(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String);
39 var memberExpression = Token.New(JsonTokenType.String).Cat(Token.New(JsonTokenType.NameSeparator)).Cat(valueExpression);
52 var memberExpression = Token.New(JsonTokenType.String).Cat(Token.New(JsonTokenType.NameSeparator)).Cat(valueExpression);
40 var objectExpression = memberExpression
53 var objectExpression = memberExpression
41 .Cat(
54 .Cat(
42 Token.New(JsonTokenType.ValueSeparator)
55 Token.New(JsonTokenType.ValueSeparator)
43 .Cat(memberExpression)
56 .Cat(memberExpression)
44 .EClosure()
57 .EClosure()
45 )
58 )
46 .Optional()
59 .Optional()
47 .Cat(Token.New(JsonTokenType.EndObject))
60 .Cat(Token.New(JsonTokenType.EndObject))
48 .Tag(0);
61 .Tag(0);
49 var arrayExpression = valueExpression
62 var arrayExpression = valueExpression
50 .Cat(
63 .Cat(
51 Token.New(JsonTokenType.ValueSeparator)
64 Token.New(JsonTokenType.ValueSeparator)
52 .Cat(valueExpression)
65 .Cat(valueExpression)
53 .EClosure()
66 .EClosure()
54 )
67 )
55 .Optional()
68 .Optional()
56 .Cat(Token.New(JsonTokenType.EndArray))
69 .Cat(Token.New(JsonTokenType.EndArray))
57 .Tag(0);
70 .Tag(0);
58
71
59 _jsonDFA = BuildDFA(jsonExpression).States;
72 _jsonDFA = BuildDFA(jsonExpression).States;
60 _objectDFA = BuildDFA(objectExpression).States;
73 _objectDFA = BuildDFA(objectExpression).States;
61 _arrayDFA = BuildDFA(arrayExpression).States;
74 _arrayDFA = BuildDFA(arrayExpression).States;
62 }
75 }
63
76
64 static EDFADefinition<JsonTokenType> BuildDFA(Token expr) {
77 static EDFADefinition<JsonTokenType> BuildDFA(Token expr) {
65 var builder = new DFABuilder();
78 var builder = new DFABuilder();
66 var dfa = new EDFADefinition<JsonTokenType>(_alphabet);
79 var dfa = new EDFADefinition<JsonTokenType>(_alphabet);
67 expr.Accept(builder);
80 expr.Accept(builder);
68
81
69 builder.BuildDFA(dfa);
82 builder.BuildDFA(dfa);
70 return dfa;
83 return dfa;
71 }
84 }
72
85
73 JSONScanner m_scanner;
86 JSONScanner m_scanner;
74 MemberContext m_memberContext;
87 MemberContext m_memberContext;
75
88
76 JSONElementType m_elementType;
89 JSONElementType m_elementType;
77 object m_elementValue;
90 object m_elementValue;
78
91
79 /// <summary>
92 /// <summary>
80 /// Создает новый парсер на основе строки, содержащей JSON
93 /// Создает новый парсер на основе строки, содержащей JSON
81 /// </summary>
94 /// </summary>
82 /// <param name="text"></param>
95 /// <param name="text"></param>
83 public JSONParser(string text)
96 public JSONParser(string text)
84 : base(_jsonDFA, INITIAL_STATE, new JSONParserContext { elementContext = JSONElementContext.None, memberName = String.Empty }) {
97 : base(_jsonDFA, INITIAL_STATE, new JSONParserContext { elementContext = JSONElementContext.None, memberName = String.Empty }) {
85 Safe.ArgumentNotEmpty(text, "text");
98 Safe.ArgumentNotEmpty(text, "text");
86 m_scanner = new JSONScanner();
99 m_scanner = new JSONScanner();
87 m_scanner.Feed(text.ToCharArray());
100 m_scanner.Feed(text.ToCharArray());
88 }
101 }
89
102
90 /// <summary>
103 /// <summary>
91 /// Создает новый экземпляр парсера, на основе текстового потока.
104 /// Создает новый экземпляр парсера, на основе текстового потока.
92 /// </summary>
105 /// </summary>
93 /// <param name="reader">Текстовый поток.</param>
106 /// <param name="reader">Текстовый поток.</param>
94 /// <param name="dispose">Признак того, что парсер должен конролировать время жизни входного потока.</param>
107 /// <param name="dispose">Признак того, что парсер должен конролировать время жизни входного потока.</param>
95 public JSONParser(TextReader reader, bool dispose)
108 public JSONParser(TextReader reader, bool dispose)
96 : base(_jsonDFA, INITIAL_STATE, new JSONParserContext { elementContext = JSONElementContext.None, memberName = String.Empty }) {
109 : base(_jsonDFA, INITIAL_STATE, new JSONParserContext { elementContext = JSONElementContext.None, memberName = String.Empty }) {
97 Safe.ArgumentNotNull(reader, "reader");
110 Safe.ArgumentNotNull(reader, "reader");
98 m_scanner = new JSONScanner();
111 m_scanner = new JSONScanner();
99 m_scanner.Feed(reader, dispose);
112 m_scanner.Feed(reader, dispose);
100 }
113 }
101
114
102 /// <summary>
115 /// <summary>
103 /// Тип текущего элемента на котором стоит парсер.
116 /// Тип текущего элемента на котором стоит парсер.
104 /// </summary>
117 /// </summary>
105 public JSONElementType ElementType {
118 public JSONElementType ElementType {
106 get { return m_elementType; }
119 get { return m_elementType; }
107 }
120 }
108
121
109 /// <summary>
122 /// <summary>
110 /// Имя элемента - имя свойства родительского контейнера. Для элементов массивов и корневого всегда
123 /// Имя элемента - имя свойства родительского контейнера. Для элементов массивов и корневого всегда
111 /// пустая строка.
124 /// пустая строка.
112 /// </summary>
125 /// </summary>
113 public string ElementName {
126 public string ElementName {
114 get { return m_context.info.memberName; }
127 get { return m_context.info.memberName; }
115 }
128 }
116
129
117 /// <summary>
130 /// <summary>
118 /// Значение элемента. Только для элементов типа <see cref="JSONElementType.Value"/>, для остальных <c>null</c>
131 /// Значение элемента. Только для элементов типа <see cref="JSONElementType.Value"/>, для остальных <c>null</c>
119 /// </summary>
132 /// </summary>
120 public object ElementValue {
133 public object ElementValue {
121 get { return m_elementValue; }
134 get { return m_elementValue; }
122 }
135 }
123
136
124 /// <summary>
137 /// <summary>
125 /// Читает слеюудущий объект из потока
138 /// Читает слеюудущий объект из потока
126 /// </summary>
139 /// </summary>
127 /// <returns><c>true</c> - операция чтения прошла успешно, <c>false</c> - конец данных</returns>
140 /// <returns><c>true</c> - операция чтения прошла успешно, <c>false</c> - конец данных</returns>
128 public bool Read() {
141 public bool Read() {
129 if (m_context.current == UNREACHEBLE_STATE)
142 if (m_context.current == UNREACHEBLE_STATE)
130 throw new InvalidOperationException("The parser is in invalid state");
143 throw new InvalidOperationException("The parser is in invalid state");
131 object tokenValue;
144 object tokenValue;
132 JsonTokenType tokenType;
145 JsonTokenType tokenType;
133 m_context.info.memberName = String.Empty;
146 m_context.info.memberName = String.Empty;
134 while (m_scanner.ReadToken(out tokenValue, out tokenType)) {
147 while (m_scanner.ReadToken(out tokenValue, out tokenType)) {
135 Move((int)tokenType);
148 Move((int)tokenType);
136 if (m_context.current == UNREACHEBLE_STATE)
149 if (m_context.current == UNREACHEBLE_STATE)
137 UnexpectedToken(tokenValue, tokenType);
150 UnexpectedToken(tokenValue, tokenType);
138 switch (tokenType) {
151 switch (tokenType) {
139 case JsonTokenType.BeginObject:
152 case JsonTokenType.BeginObject:
140 Switch(
153 Switch(
141 _objectDFA,
154 _objectDFA,
142 INITIAL_STATE,
155 INITIAL_STATE,
143 new JSONParserContext {
156 new JSONParserContext {
144 memberName = m_context.info.memberName,
157 memberName = m_context.info.memberName,
145 elementContext = JSONElementContext.Object
158 elementContext = JSONElementContext.Object
146 }
159 }
147 );
160 );
148 m_elementValue = null;
161 m_elementValue = null;
149 m_memberContext = MemberContext.MemberName;
162 m_memberContext = MemberContext.MemberName;
150 m_elementType = JSONElementType.BeginObject;
163 m_elementType = JSONElementType.BeginObject;
151 return true;
164 return true;
152 case JsonTokenType.EndObject:
165 case JsonTokenType.EndObject:
153 Restore();
166 Restore();
154 m_elementValue = null;
167 m_elementValue = null;
155 m_elementType = JSONElementType.EndObject;
168 m_elementType = JSONElementType.EndObject;
156 return true;
169 return true;
157 case JsonTokenType.BeginArray:
170 case JsonTokenType.BeginArray:
158 Switch(
171 Switch(
159 _arrayDFA,
172 _arrayDFA,
160 INITIAL_STATE,
173 INITIAL_STATE,
161 new JSONParserContext {
174 new JSONParserContext {
162 memberName = m_context.info.memberName,
175 memberName = m_context.info.memberName,
163 elementContext = JSONElementContext.Array
176 elementContext = JSONElementContext.Array
164 }
177 }
165 );
178 );
166 m_elementValue = null;
179 m_elementValue = null;
167 m_memberContext = MemberContext.MemberValue;
180 m_memberContext = MemberContext.MemberValue;
168 m_elementType = JSONElementType.BeginArray;
181 m_elementType = JSONElementType.BeginArray;
169 return true;
182 return true;
170 case JsonTokenType.EndArray:
183 case JsonTokenType.EndArray:
171 Restore();
184 Restore();
172 m_elementValue = null;
185 m_elementValue = null;
173 m_elementType = JSONElementType.EndArray;
186 m_elementType = JSONElementType.EndArray;
174 return true;
187 return true;
175 case JsonTokenType.String:
188 case JsonTokenType.String:
176 if (m_memberContext == MemberContext.MemberName) {
189 if (m_memberContext == MemberContext.MemberName) {
177 m_context.info.memberName = (string)tokenValue;
190 m_context.info.memberName = (string)tokenValue;
178 break;
191 break;
179 } else {
192 } else {
180 m_elementType = JSONElementType.Value;
193 m_elementType = JSONElementType.Value;
181 m_elementValue = tokenValue;
194 m_elementValue = tokenValue;
182 return true;
195 return true;
183 }
196 }
184 case JsonTokenType.Number:
197 case JsonTokenType.Number:
185 m_elementType = JSONElementType.Value;
198 m_elementType = JSONElementType.Value;
186 m_elementValue = tokenValue;
199 m_elementValue = tokenValue;
187 return true;
200 return true;
188 case JsonTokenType.Literal:
201 case JsonTokenType.Literal:
189 m_elementType = JSONElementType.Value;
202 m_elementType = JSONElementType.Value;
190 m_elementValue = ParseLiteral((string)tokenValue);
203 m_elementValue = ParseLiteral((string)tokenValue);
191 return true;
204 return true;
192 case JsonTokenType.NameSeparator:
205 case JsonTokenType.NameSeparator:
193 m_memberContext = MemberContext.MemberValue;
206 m_memberContext = MemberContext.MemberValue;
194 break;
207 break;
195 case JsonTokenType.ValueSeparator:
208 case JsonTokenType.ValueSeparator:
196 m_memberContext = m_context.info.elementContext == JSONElementContext.Object ? MemberContext.MemberName : MemberContext.MemberValue;
209 m_memberContext = m_context.info.elementContext == JSONElementContext.Object ? MemberContext.MemberName : MemberContext.MemberValue;
197 break;
210 break;
198 default:
211 default:
199 UnexpectedToken(tokenValue, tokenType);
212 UnexpectedToken(tokenValue, tokenType);
200 break;
213 break;
201 }
214 }
202 }
215 }
203 if (m_context.info.elementContext != JSONElementContext.None)
216 if (m_context.info.elementContext != JSONElementContext.None)
204 throw new ParserException("Unexpedted end of data");
217 throw new ParserException("Unexpedted end of data");
205 return false;
218 return false;
206 }
219 }
207
220
208 object ParseLiteral(string literal) {
221 object ParseLiteral(string literal) {
209 switch (literal) {
222 switch (literal) {
210 case "null":
223 case "null":
211 return null;
224 return null;
212 case "false":
225 case "false":
213 return false;
226 return false;
214 case "true":
227 case "true":
215 return true;
228 return true;
216 default:
229 default:
217 UnexpectedToken(literal, JsonTokenType.Literal);
230 UnexpectedToken(literal, JsonTokenType.Literal);
218 return null; // avoid compliler error
231 return null; // avoid compliler error
219 }
232 }
220 }
233 }
221
234
222 void UnexpectedToken(object value, JsonTokenType tokenType) {
235 void UnexpectedToken(object value, JsonTokenType tokenType) {
223 throw new ParserException(String.Format("Unexpected token {0}: '{1}'", tokenType, value));
236 throw new ParserException(String.Format("Unexpected token {0}: '{1}'", tokenType, value));
224 }
237 }
225
238
226
239
227 /// <summary>
240 /// <summary>
228 /// Признак конца потока
241 /// Признак конца потока
229 /// </summary>
242 /// </summary>
230 public bool EOF {
243 public bool EOF {
231 get {
244 get {
232 return m_scanner.EOF;
245 return m_scanner.EOF;
233 }
246 }
234 }
247 }
235
248
236 protected virtual void Dispose(bool disposing) {
249 protected virtual void Dispose(bool disposing) {
237 if (disposing) {
250 if (disposing) {
238 m_scanner.Dispose();
251 m_scanner.Dispose();
239 }
252 }
240 }
253 }
241
254
242 /// <summary>
255 /// <summary>
243 /// Освобождает парсер и связанный с ним сканнер.
256 /// Освобождает парсер и связанный с ним сканнер.
244 /// </summary>
257 /// </summary>
245 public void Dispose() {
258 public void Dispose() {
246 Dispose(true);
259 Dispose(true);
247 GC.SuppressFinalize(this);
260 GC.SuppressFinalize(this);
248 }
261 }
249
262
250 ~JSONParser() {
263 ~JSONParser() {
251 Dispose(false);
264 Dispose(false);
252 }
265 }
253
266
254 public void Skip() {
267 /// <summary>
268 /// Переходит в конец текущего объекта.
269 /// </summary>
270 public void SeekElementEnd() {
255 var level = Level-1;
271 var level = Level - 1;
256
272
257 Debug.Assert(level >= 0);
273 Debug.Assert(level >= 0);
258
274
259 while (Level != level)
275 while (Level != level)
260 Read();
276 Read();
261 }
277 }
262 }
278 }
263
279
264 }
280 }
General Comments 0
You need to be logged in to leave comments. Login now