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