##// END OF EJS Templates
refactoring complete, JSONParser rewritten
cin -
r180:c32688129f14 ref20160224
parent child
Show More
@@ -1,17 +1,19
1 syntax: glob
1 syntax: glob
2 Implab.Test/bin/
2 Implab.Test/bin/
3 *.user
3 *.user
4 Implab.Test/obj/
4 Implab.Test/obj/
5 *.userprefs
5 *.userprefs
6 Implab/bin/
6 Implab/bin/
7 Implab/obj/
7 Implab/obj/
8 TestResults/
8 TestResults/
9 Implab.Fx/obj/
9 Implab.Fx/obj/
10 Implab.Fx/bin/
10 Implab.Fx/bin/
11 Implab.Fx.Test/bin/
11 Implab.Fx.Test/bin/
12 Implab.Fx.Test/obj/
12 Implab.Fx.Test/obj/
13 _ReSharper.Implab/
13 _ReSharper.Implab/
14 Implab.Diagnostics.Interactive/bin/
14 Implab.Diagnostics.Interactive/bin/
15 Implab.Diagnostics.Interactive/obj/
15 Implab.Diagnostics.Interactive/obj/
16 MonoPlay/bin/
16 MonoPlay/bin/
17 MonoPlay/obj/
17 MonoPlay/obj/
18 Implab.Test/Implab.Format.Test/bin/
19 Implab.Test/Implab.Format.Test/obj/
@@ -1,313 +1,313
1 using Implab;
1 using Implab;
2 using System;
2 using System;
3 using System.Collections.Generic;
3 using System.Collections.Generic;
4 using System.Linq;
4 using System.Linq;
5
5
6 namespace Implab.Automaton {
6 namespace Implab.Automaton {
7 public class DFATable : IDFATableBuilder {
7 public class DFATable : IDFATableBuilder {
8 int m_stateCount;
8 int m_stateCount;
9 int m_symbolCount;
9 int m_symbolCount;
10 int m_initialState;
10 int m_initialState;
11
11
12 readonly HashSet<int> m_finalStates = new HashSet<int>();
12 readonly HashSet<int> m_finalStates = new HashSet<int>();
13 readonly HashSet<AutomatonTransition> m_transitions = new HashSet<AutomatonTransition>();
13 readonly HashSet<AutomatonTransition> m_transitions = new HashSet<AutomatonTransition>();
14
14
15
15
16 #region IDFADefinition implementation
16 #region IDFADefinition implementation
17
17
18 public bool IsFinalState(int s) {
18 public bool IsFinalState(int s) {
19 Safe.ArgumentInRange(s, 0, m_stateCount, "s");
19 Safe.ArgumentInRange(s, 0, m_stateCount, "s");
20
20
21 return m_finalStates.Contains(s);
21 return m_finalStates.Contains(s);
22 }
22 }
23
23
24 public IEnumerable<int> FinalStates {
24 public IEnumerable<int> FinalStates {
25 get {
25 get {
26 return m_finalStates;
26 return m_finalStates;
27 }
27 }
28 }
28 }
29
29
30 public int StateCount {
30 public int StateCount {
31 get { return m_stateCount; }
31 get { return m_stateCount; }
32 }
32 }
33
33
34 public int AlphabetSize {
34 public int AlphabetSize {
35 get { return m_symbolCount; }
35 get { return m_symbolCount; }
36 }
36 }
37
37
38 public int InitialState {
38 public int InitialState {
39 get { return m_initialState; }
39 get { return m_initialState; }
40 }
40 }
41
41
42 #endregion
42 #endregion
43
43
44 public void SetInitialState(int s) {
44 public void SetInitialState(int s) {
45 Safe.ArgumentAssert(s >= 0, "s");
45 Safe.ArgumentAssert(s >= 0, "s");
46 m_initialState = s;
46 m_initialState = s;
47 }
47 }
48
48
49 public void MarkFinalState(int state) {
49 public void MarkFinalState(int state) {
50 m_finalStates.Add(state);
50 m_finalStates.Add(state);
51 }
51 }
52
52
53 public void Add(AutomatonTransition item) {
53 public void Add(AutomatonTransition item) {
54 Safe.ArgumentAssert(item.s1 >= 0, "item");
54 Safe.ArgumentAssert(item.s1 >= 0, "item");
55 Safe.ArgumentAssert(item.s2 >= 0, "item");
55 Safe.ArgumentAssert(item.s2 >= 0, "item");
56 Safe.ArgumentAssert(item.edge >= 0, "item");
56 Safe.ArgumentAssert(item.edge >= 0, "item");
57
57
58 m_stateCount = Math.Max(m_stateCount, Math.Max(item.s1, item.s2) + 1);
58 m_stateCount = Math.Max(m_stateCount, Math.Max(item.s1, item.s2) + 1);
59 m_symbolCount = Math.Max(m_symbolCount, item.edge);
59 m_symbolCount = Math.Max(m_symbolCount, item.edge);
60
60
61 m_transitions.Add(item);
61 m_transitions.Add(item);
62 }
62 }
63
63
64 public void Clear() {
64 public void Clear() {
65 m_stateCount = 0;
65 m_stateCount = 0;
66 m_symbolCount = 0;
66 m_symbolCount = 0;
67 m_finalStates.Clear();
67 m_finalStates.Clear();
68 m_transitions.Clear();
68 m_transitions.Clear();
69 }
69 }
70
70
71 public bool Contains(AutomatonTransition item) {
71 public bool Contains(AutomatonTransition item) {
72 return m_transitions.Contains(item);
72 return m_transitions.Contains(item);
73 }
73 }
74
74
75 public void CopyTo(AutomatonTransition[] array, int arrayIndex) {
75 public void CopyTo(AutomatonTransition[] array, int arrayIndex) {
76 m_transitions.CopyTo(array, arrayIndex);
76 m_transitions.CopyTo(array, arrayIndex);
77 }
77 }
78
78
79 public bool Remove(AutomatonTransition item) {
79 public bool Remove(AutomatonTransition item) {
80 m_transitions.Remove(item);
80 return m_transitions.Remove(item);
81 }
81 }
82
82
83 public int Count {
83 public int Count {
84 get {
84 get {
85 return m_transitions.Count;
85 return m_transitions.Count;
86 }
86 }
87 }
87 }
88
88
89 public bool IsReadOnly {
89 public bool IsReadOnly {
90 get {
90 get {
91 return false;
91 return false;
92 }
92 }
93 }
93 }
94
94
95 public IEnumerator<AutomatonTransition> GetEnumerator() {
95 public IEnumerator<AutomatonTransition> GetEnumerator() {
96 return m_transitions.GetEnumerator();
96 return m_transitions.GetEnumerator();
97 }
97 }
98
98
99 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
99 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
100 return GetEnumerator();
100 return GetEnumerator();
101 }
101 }
102
102
103 public int[,] CreateTransitionTable() {
103 public int[,] CreateTransitionTable() {
104 var table = new int[StateCount,AlphabetSize];
104 var table = new int[StateCount,AlphabetSize];
105
105
106 for (int i = 0; i < StateCount; i++)
106 for (int i = 0; i < StateCount; i++)
107 for (int j = 0; i < AlphabetSize; j++)
107 for (int j = 0; i < AlphabetSize; j++)
108 table[i, j] = AutomatonConst.UNREACHABLE_STATE;
108 table[i, j] = AutomatonConst.UNREACHABLE_STATE;
109
109
110 foreach (var t in this)
110 foreach (var t in this)
111 table[t.s1,t.edge] = t.s2;
111 table[t.s1,t.edge] = t.s2;
112
112
113 return table;
113 return table;
114 }
114 }
115
115
116 public bool[] CreateFinalStateTable() {
116 public bool[] CreateFinalStateTable() {
117 var table = new bool[StateCount];
117 var table = new bool[StateCount];
118
118
119 foreach (var s in FinalStates)
119 foreach (var s in FinalStates)
120 table[s] = true;
120 table[s] = true;
121
121
122 return table;
122 return table;
123 }
123 }
124
124
125 /// <summary>Формирует множества конечных состояний перед началом работы алгоритма минимизации.</summary>
125 /// <summary>Формирует множества конечных состояний перед началом работы алгоритма минимизации.</summary>
126 /// <remarks>
126 /// <remarks>
127 /// В процессе построения минимального автомата требуется разделить множество состояний,
127 /// В процессе построения минимального автомата требуется разделить множество состояний,
128 /// на два подмножества - конечные состояния и все остальные, после чего эти подмножества
128 /// на два подмножества - конечные состояния и все остальные, после чего эти подмножества
129 /// будут резделены на более мелкие. Иногда требуется гарантировать различия конечных сосотяний,
129 /// будут резделены на более мелкие. Иногда требуется гарантировать различия конечных сосотяний,
130 /// для этого необходимо переопределить даннцю фукнцию, для получения множеств конечных состояний.
130 /// для этого необходимо переопределить даннцю фукнцию, для получения множеств конечных состояний.
131 /// </remarks>
131 /// </remarks>
132 /// <returns>The final states.</returns>
132 /// <returns>The final states.</returns>
133 protected virtual IEnumerable<HashSet<int>> GroupFinalStates() {
133 protected virtual IEnumerable<HashSet<int>> GroupFinalStates() {
134 return new HashSet<int>[] { m_finalStates };
134 return new HashSet<int>[] { m_finalStates };
135 }
135 }
136
136
137 protected void Optimize(
137 protected void Optimize(
138 IDFATableBuilder optimalDFA,
138 IDFATableBuilder optimalDFA,
139 IDictionary<int,int> alphabetMap,
139 IDictionary<int,int> alphabetMap,
140 IDictionary<int,int> stateMap
140 IDictionary<int,int> stateMap
141 ) {
141 ) {
142 Safe.ArgumentNotNull(optimalDFA, "dfa");
142 Safe.ArgumentNotNull(optimalDFA, "dfa");
143 Safe.ArgumentNotNull(alphabetMap, "alphabetMap");
143 Safe.ArgumentNotNull(alphabetMap, "alphabetMap");
144 Safe.ArgumentNotNull(stateMap, "stateMap");
144 Safe.ArgumentNotNull(stateMap, "stateMap");
145
145
146
146
147 var setComparer = new CustomEqualityComparer<HashSet<int>>(
147 var setComparer = new CustomEqualityComparer<HashSet<int>>(
148 (x, y) => x.SetEquals(y),
148 (x, y) => x.SetEquals(y),
149 s => s.Sum(x => x.GetHashCode())
149 s => s.Sum(x => x.GetHashCode())
150 );
150 );
151
151
152 var optimalStates = new HashSet<HashSet<int>>(setComparer);
152 var optimalStates = new HashSet<HashSet<int>>(setComparer);
153 var queue = new HashSet<HashSet<int>>(setComparer);
153 var queue = new HashSet<HashSet<int>>(setComparer);
154
154
155 // получаем конечные состояния, сгруппированные по маркерам
155 // получаем конечные состояния, сгруппированные по маркерам
156 optimalStates.UnionWith(
156 optimalStates.UnionWith(
157 GroupFinalStates()
157 GroupFinalStates()
158 );
158 );
159
159
160 var state = new HashSet<int>(
160 var state = new HashSet<int>(
161 Enumerable
161 Enumerable
162 .Range(0, m_stateCount - 1)
162 .Range(0, m_stateCount - 1)
163 .Where(i => !m_finalStates.Contains(i))
163 .Where(i => !m_finalStates.Contains(i))
164 );
164 );
165
165
166 optimalStates.Add(state);
166 optimalStates.Add(state);
167 queue.Add(state);
167 queue.Add(state);
168
168
169 var rmap = m_transitions
169 var rmap = m_transitions
170 .GroupBy(t => t.s2)
170 .GroupBy(t => t.s2)
171 .ToLookup(
171 .ToDictionary(
172 g => g.Key, // s2
172 g => g.Key, // s2
173 g => g.ToLookup(t => t.edge, t => t.s1)
173 g => g.GroupBy(t => t.edge, t => t.s1).ToDictionary(p => p.Key)
174 );
174 );
175
175
176 while (queue.Count > 0) {
176 while (queue.Count > 0) {
177 var stateA = queue.First();
177 var stateA = queue.First();
178 queue.Remove(stateA);
178 queue.Remove(stateA);
179
179
180 for (int c = 0; c < m_symbolCount; c++) {
180 for (int c = 0; c < m_symbolCount; c++) {
181 var stateX = new HashSet<int>();
181 var stateX = new HashSet<int>();
182 foreach(var a in stateA)
182 foreach(var a in stateA)
183 stateX.UnionWith(rmap[a][c]); // all states from wich 'c' leads to 'a'
183 stateX.UnionWith(rmap[a][c]); // all states from wich the symbol 'c' leads to the state 'a'
184
184
185 foreach (var stateY in optimalStates.ToArray()) {
185 foreach (var stateY in optimalStates.ToArray()) {
186 if (stateX.Overlaps(stateY) && !stateY.IsSubsetOf(stateX)) {
186 if (stateX.Overlaps(stateY) && !stateY.IsSubsetOf(stateX)) {
187 var stateR1 = new HashSet<int>(stateY);
187 var stateR1 = new HashSet<int>(stateY);
188 var stateR2 = new HashSet<int>(stateY);
188 var stateR2 = new HashSet<int>(stateY);
189
189
190 stateR1.IntersectWith(stateX);
190 stateR1.IntersectWith(stateX);
191 stateR2.ExceptWith(stateX);
191 stateR2.ExceptWith(stateX);
192
192
193 optimalStates.Remove(stateY);
193 optimalStates.Remove(stateY);
194 optimalStates.Add(stateR1);
194 optimalStates.Add(stateR1);
195 optimalStates.Add(stateR2);
195 optimalStates.Add(stateR2);
196
196
197 if (queue.Contains(stateY)) {
197 if (queue.Contains(stateY)) {
198 queue.Remove(stateY);
198 queue.Remove(stateY);
199 queue.Add(stateR1);
199 queue.Add(stateR1);
200 queue.Add(stateR2);
200 queue.Add(stateR2);
201 } else {
201 } else {
202 queue.Add(stateR1.Count <= stateR2.Count ? stateR1 : stateR2);
202 queue.Add(stateR1.Count <= stateR2.Count ? stateR1 : stateR2);
203 }
203 }
204 }
204 }
205 }
205 }
206 }
206 }
207 }
207 }
208
208
209 // карта получения оптимального состояния по соотвествующему ему простому состоянию
209 // карта получения оптимального состояния по соотвествующему ему простому состоянию
210 var nextState = 0;
210 var nextState = 0;
211 foreach (var item in optimalStates) {
211 foreach (var item in optimalStates) {
212 var id = nextState++;
212 var id = nextState++;
213 foreach (var s in item)
213 foreach (var s in item)
214 stateMap[s] = id;
214 stateMap[s] = id;
215 }
215 }
216
216
217 // получаем минимальный алфавит
217 // получаем минимальный алфавит
218 // входные символы не различимы, если Move(s,a1) == Move(s,a2), для любого s
218 // входные символы не различимы, если Move(s,a1) == Move(s,a2), для любого s
219 // для этого используем алгоритм кластеризации, сначала
219 // для этого используем алгоритм кластеризации, сначала
220 // считаем, что все символы не различимы
220 // считаем, что все символы не различимы
221
221
222 var minClasses = new HashSet<HashSet<int>>(setComparer);
222 var minClasses = new HashSet<HashSet<int>>(setComparer);
223 var alphaQueue = new Queue<HashSet<int>>();
223 var alphaQueue = new Queue<HashSet<int>>();
224 alphaQueue.Enqueue(new HashSet<int>(Enumerable.Range(0,AlphabetSize)));
224 alphaQueue.Enqueue(new HashSet<int>(Enumerable.Range(0,AlphabetSize)));
225
225
226 // для всех состояний, будем проверять каждый класс на различимость,
226 // для всех состояний, будем проверять каждый класс на различимость,
227 // т.е. символы различимы, если они приводят к разным состояниям
227 // т.е. символы различимы, если они приводят к разным состояниям
228 for (int s = 0 ; s < optimalStates.Count; s++) {
228 for (int s = 0 ; s < optimalStates.Count; s++) {
229 var newQueue = new Queue<HashSet<int>>();
229 var newQueue = new Queue<HashSet<int>>();
230
230
231 foreach (var A in alphaQueue) {
231 foreach (var A in alphaQueue) {
232 // классы из одного символа делить бесполезно, переводим их сразу в
232 // классы из одного символа делить бесполезно, переводим их сразу в
233 // результирующий алфавит
233 // результирующий алфавит
234 if (A.Count == 1) {
234 if (A.Count == 1) {
235 minClasses.Add(A);
235 minClasses.Add(A);
236 continue;
236 continue;
237 }
237 }
238
238
239 // различаем классы символов, которые переводят в различные оптимальные состояния
239 // различаем классы символов, которые переводят в различные оптимальные состояния
240 // optimalState -> alphaClass
240 // optimalState -> alphaClass
241 var classes = new Dictionary<int, HashSet<int>>();
241 var classes = new Dictionary<int, HashSet<int>>();
242
242
243 foreach (var term in A) {
243 foreach (var term in A) {
244 // ищем все переходы класса по символу term
244 // ищем все переходы класса по символу term
245 var res = m_transitions.Where(t => stateMap[t.s1] == s && t.edge == term).Select(t => stateMap[t.s2]).ToArray();
245 var res = m_transitions.Where(t => stateMap[t.s1] == s && t.edge == term).Select(t => stateMap[t.s2]).ToArray();
246
246
247 var s2 = res.Length > 0 ? res[0] : -1;
247 var s2 = res.Length > 0 ? res[0] : -1;
248
248
249 HashSet<int> a2;
249 HashSet<int> a2;
250 if (!classes.TryGetValue(s2, out a2)) {
250 if (!classes.TryGetValue(s2, out a2)) {
251 a2 = new HashSet<int>();
251 a2 = new HashSet<int>();
252 newQueue.Enqueue(a2);
252 newQueue.Enqueue(a2);
253 classes[s2] = a2;
253 classes[s2] = a2;
254 }
254 }
255 a2.Add(term);
255 a2.Add(term);
256 }
256 }
257 }
257 }
258
258
259 if (newQueue.Count == 0)
259 if (newQueue.Count == 0)
260 break;
260 break;
261 alphaQueue = newQueue;
261 alphaQueue = newQueue;
262 }
262 }
263
263
264 // после окончания работы алгоритма в очереди останутся минимальные различимые классы
264 // после окончания работы алгоритма в очереди останутся минимальные различимые классы
265 // входных символов
265 // входных символов
266 foreach (var A in alphaQueue)
266 foreach (var A in alphaQueue)
267 minClasses.Add(A);
267 minClasses.Add(A);
268
268
269 // построение отображения алфавитов входных символов.
269 // построение отображения алфавитов входных символов.
270 // поскольку символ DFAConst.UNCLASSIFIED_INPUT может иметь
270 // поскольку символ DFAConst.UNCLASSIFIED_INPUT может иметь
271 // специальное значение, тогда сохраним минимальный класс,
271 // специальное значение, тогда сохраним минимальный класс,
272 // содержащий этот символ на томже месте.
272 // содержащий этот символ на томже месте.
273
273
274 var nextCls = 0;
274 var nextCls = 0;
275 foreach (var item in minClasses) {
275 foreach (var item in minClasses) {
276 if (nextCls == AutomatonConst.UNCLASSIFIED_INPUT)
276 if (nextCls == AutomatonConst.UNCLASSIFIED_INPUT)
277 nextCls++;
277 nextCls++;
278
278
279 // сохраняем DFAConst.UNCLASSIFIED_INPUT
279 // сохраняем DFAConst.UNCLASSIFIED_INPUT
280 var cls = item.Contains(AutomatonConst.UNCLASSIFIED_INPUT) ? AutomatonConst.UNCLASSIFIED_INPUT : nextCls;
280 var cls = item.Contains(AutomatonConst.UNCLASSIFIED_INPUT) ? AutomatonConst.UNCLASSIFIED_INPUT : nextCls;
281
281
282 foreach (var a in item)
282 foreach (var a in item)
283 alphabetMap[a] = cls;
283 alphabetMap[a] = cls;
284
284
285 nextCls++;
285 nextCls++;
286 }
286 }
287
287
288 // построение автомата
288 // построение автомата
289 optimalDFA.SetInitialState(stateMap[m_initialState]);
289 optimalDFA.SetInitialState(stateMap[m_initialState]);
290
290
291 foreach (var sf in m_finalStates.Select(s => stateMap[s]).Distinct())
291 foreach (var sf in m_finalStates.Select(s => stateMap[s]).Distinct())
292 optimalDFA.MarkFinalState(sf);
292 optimalDFA.MarkFinalState(sf);
293
293
294 foreach (var t in m_transitions.Select(t => new AutomatonTransition(stateMap[t.s1],stateMap[t.s2],alphabetMap[t.edge])).Distinct())
294 foreach (var t in m_transitions.Select(t => new AutomatonTransition(stateMap[t.s1],stateMap[t.s2],alphabetMap[t.edge])).Distinct())
295 optimalDFA.Add(t);
295 optimalDFA.Add(t);
296 }
296 }
297
297
298 protected void PrintDFA<TInput, TState>(IAlphabet<TInput> inputAlphabet, IAlphabet<TState> stateAlphabet) {
298 protected void PrintDFA<TInput, TState>(IAlphabet<TInput> inputAlphabet, IAlphabet<TState> stateAlphabet) {
299 Safe.ArgumentNotNull(inputAlphabet, "inputAlphabet");
299 Safe.ArgumentNotNull(inputAlphabet, "inputAlphabet");
300 Safe.ArgumentNotNull(stateAlphabet, "stateAlphabet");
300 Safe.ArgumentNotNull(stateAlphabet, "stateAlphabet");
301
301
302 foreach(var t in m_transitions)
302 foreach(var t in m_transitions)
303 Console.WriteLine(
303 Console.WriteLine(
304 "[{0}] -{{{1}}}-> [{2}]{3}",
304 "[{0}] -{{{1}}}-> [{2}]{3}",
305 String.Join(",", stateAlphabet.GetSymbols(t.s1)),
305 String.Join(",", stateAlphabet.GetSymbols(t.s1)),
306 String.Join("", inputAlphabet.GetSymbols(t.edge)),
306 String.Join("", inputAlphabet.GetSymbols(t.edge)),
307 String.Join(",", stateAlphabet.GetSymbols(t.s2)),
307 String.Join(",", stateAlphabet.GetSymbols(t.s2)),
308 m_finalStates.Contains(t.s2) ? "$" : ""
308 m_finalStates.Contains(t.s2) ? "$" : ""
309 );
309 );
310 }
310 }
311
311
312 }
312 }
313 }
313 }
@@ -1,70 +1,66
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Diagnostics;
3 using System.Diagnostics;
4 using System.Globalization;
4 using System.Globalization;
5 using System.Linq;
5 using System.Linq;
6 using System.Diagnostics.CodeAnalysis;
6 using System.Diagnostics.CodeAnalysis;
7
7
8 namespace Implab.Automaton {
8 namespace Implab.Automaton {
9 /// <summary>
9 /// <summary>
10 /// Алфавит символами которого являются элементы перечислений.
10 /// Алфавит символами которого являются элементы перечислений.
11 /// </summary>
11 /// </summary>
12 /// <typeparam name="T">Тип перечислений</typeparam>
12 /// <typeparam name="T">Тип перечислений</typeparam>
13 public class EnumAlphabet<T> : IndexedAlphabetBase<T> where T : struct, IConvertible {
13 public class EnumAlphabet<T> : IndexedAlphabetBase<T> where T : struct, IConvertible {
14 [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
14 [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
15 static readonly Lazy<T[]> _symbols = new Lazy<T[]>(GetSymbols);
15 static readonly Lazy<T[]> _symbols = new Lazy<T[]>(GetSymbols);
16
16
17 [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
17 [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
18 static readonly Lazy<EnumAlphabet<T>> _fullAlphabet = new Lazy<EnumAlphabet<T>>(CreateEnumAlphabet);
18 static readonly Lazy<EnumAlphabet<T>> _fullAlphabet = new Lazy<EnumAlphabet<T>>(CreateEnumAlphabet);
19
19
20 static EnumAlphabet<T> CreateEnumAlphabet() {
20 static EnumAlphabet<T> CreateEnumAlphabet() {
21 var symbols = _symbols.Value;
21 var symbols = _symbols.Value;
22
22
23 if (
23 if (
24 symbols[symbols.Length - 1].ToInt32(CultureInfo.InvariantCulture) >= symbols.Length
24 symbols[symbols.Length - 1].ToInt32(CultureInfo.InvariantCulture) >= symbols.Length
25 || symbols[0].ToInt32(CultureInfo.InvariantCulture) != 0
25 || symbols[0].ToInt32(CultureInfo.InvariantCulture) != 0
26 )
26 )
27 throw new InvalidOperationException("The specified enumeration must be zero-based and continuously numbered");
27 throw new InvalidOperationException("The specified enumeration must be zero-based and continuously numbered");
28
28
29 return new EnumAlphabet<T>(symbols.Select(x => x.ToInt32(CultureInfo.InvariantCulture)).ToArray());
29 return new EnumAlphabet<T>(symbols.Select(x => x.ToInt32(CultureInfo.InvariantCulture)).ToArray());
30 }
30 }
31
31
32 static T[] GetSymbols() {
32 static T[] GetSymbols() {
33 if (!typeof(T).IsEnum)
33 if (!typeof(T).IsEnum)
34 throw new InvalidOperationException("Invalid generic parameter, enumeration is required");
34 throw new InvalidOperationException("Invalid generic parameter, enumeration is required");
35
35
36 if (Enum.GetUnderlyingType(typeof(T)) != typeof(Int32))
36 if (Enum.GetUnderlyingType(typeof(T)) != typeof(Int32))
37 throw new InvalidOperationException("Only enums based on Int32 are supported");
37 throw new InvalidOperationException("Only enums based on Int32 are supported");
38
38
39 return ((T[])Enum.GetValues(typeof(T)))
39 return ((T[])Enum.GetValues(typeof(T)))
40 .OrderBy(x => x.ToInt32(CultureInfo.InvariantCulture))
40 .OrderBy(x => x.ToInt32(CultureInfo.InvariantCulture))
41 .ToArray();
41 .ToArray();
42 }
42 }
43
43
44 public static EnumAlphabet<T> FullAlphabet {
44 public static EnumAlphabet<T> FullAlphabet {
45 get {
45 get {
46 return _fullAlphabet.Value;
46 return _fullAlphabet.Value;
47 }
47 }
48 }
48 }
49
49
50
50
51 public EnumAlphabet()
51 public EnumAlphabet()
52 : base(_symbols.Value.Length) {
52 : base(_symbols.Value.Length) {
53 }
53 }
54
54
55 public EnumAlphabet(int[] map)
55 public EnumAlphabet(int[] map)
56 : base(map) {
56 : base(map) {
57 Debug.Assert(map.Length == _symbols.Value.Length);
57 Debug.Assert(map.Length == _symbols.Value.Length);
58 }
58 }
59
59
60
60
61 public override int GetSymbolIndex(T symbol) {
61 public override int GetSymbolIndex(T symbol) {
62 return symbol.ToInt32(CultureInfo.InvariantCulture);
62 return symbol.ToInt32(CultureInfo.InvariantCulture);
63 }
63 }
64
64
65 public override IEnumerable<T> InputSymbols {
66 get { return _symbols.Value; }
67 }
68
69 }
65 }
70 }
66 }
@@ -1,50 +1,50
1 using Implab;
1 using Implab;
2 using System;
2 using System;
3 using System.Collections.Generic;
3 using System.Collections.Generic;
4 using System.Diagnostics;
4 using System.Diagnostics;
5 using System.Linq;
5 using System.Linq;
6
6
7 namespace Implab.Automaton {
7 namespace Implab.Automaton {
8 /// <summary>
8 /// <summary>
9 /// Indexed alphabet is the finite set of symbols where each symbol has a zero-based unique index.
9 /// Indexed alphabet is the finite set of symbols where each symbol has a zero-based unique index.
10 /// </summary>
10 /// </summary>
11 /// <remarks>
11 /// <remarks>
12 /// Indexed alphabets are usefull in bulting efficient translations from source alphabet
12 /// Indexed alphabets are usefull in bulting efficient translations from source alphabet
13 /// to the input alphabet of the automaton. It's assumed that the index to the symbol match
13 /// to the input alphabet of the automaton. It's assumed that the index to the symbol match
14 /// is well known and documented.
14 /// is well known and documented.
15 /// </remarks>
15 /// </remarks>
16 public abstract class IndexedAlphabetBase<T> : MapAlphabet<T> {
16 public abstract class IndexedAlphabetBase<T> : MapAlphabet<T> {
17
17
18 protected IndexedAlphabetBase() :base(true, null) {
18 protected IndexedAlphabetBase() :base(true, null) {
19 }
19 }
20
20
21 public abstract int GetSymbolIndex(T symbol);
21 public abstract int GetSymbolIndex(T symbol);
22
22
23 /// <summary>
23 /// <summary>
24 /// Gets the translation map from the index of the symbol to it's class this is usefull for the optimized input symbols transtaion.
24 /// Gets the translation map from the index of the symbol to it's class this is usefull for the optimized input symbols transtaion.
25 /// </summary>
25 /// </summary>
26 /// <remarks>
26 /// <remarks>
27 /// The map is continous and start from the symbol with zero code. The last symbol
27 /// The map is continous and start from the symbol with zero code. The last symbol
28 /// in the map is the last classified symbol in the alphabet, i.e. the map can be
28 /// in the map is the last classified symbol in the alphabet, i.e. the map can be
29 /// shorter then the whole alphabet.
29 /// shorter then the whole alphabet.
30 /// </remarks>
30 /// </remarks>
31 /// <returns>The translation map.</returns>
31 /// <returns>The translation map.</returns>
32 public int[] GetTranslationMap() {
32 public int[] GetTranslationMap() {
33 Dictionary<int,int> map = new Dictionary<int, int>();
33 var map = new Dictionary<int, int>();
34
34
35 int max;
35 int max = 0;
36 foreach (var p in Mappings) {
36 foreach (var p in Mappings) {
37 var index = GetSymbolIndex(p.Key);
37 var index = GetSymbolIndex(p.Key);
38 max = Math.Max(max, index);
38 max = Math.Max(max, index);
39 map[index] = p.Value;
39 map[index] = p.Value;
40 }
40 }
41
41
42 var result = new int[max + 1];
42 var result = new int[max + 1];
43
43
44 for (int i = 0; i < result.Length; i++)
44 for (int i = 0; i < result.Length; i++)
45 map.TryGetValue(i, out result[i]);
45 map.TryGetValue(i, out result[i]);
46
46
47 return result;
47 return result;
48 }
48 }
49 }
49 }
50 }
50 }
@@ -1,83 +1,82
1 using System.Collections.Generic;
1 using System.Collections.Generic;
2 using System.Linq;
2 using System.Linq;
3
3
4 namespace Implab.Automaton.RegularExpressions {
4 namespace Implab.Automaton.RegularExpressions {
5 public class RegularDFA<TInput, TTag> : DFATable, ITaggedDFABuilder<TTag> {
5 public class RegularDFA<TInput, TTag> : DFATable, ITaggedDFABuilder<TTag> {
6
6
7 readonly Dictionary<int,TTag[]> m_tags = new Dictionary<int, TTag[]>();
7 readonly Dictionary<int,TTag[]> m_tags = new Dictionary<int, TTag[]>();
8 readonly IAlphabet<TInput> m_alphabet;
8 readonly IAlphabet<TInput> m_alphabet;
9
9
10 public RegularDFA(IAlphabet<TInput> alphabet) {
10 public RegularDFA(IAlphabet<TInput> alphabet) {
11 Safe.ArgumentNotNull(alphabet, "aplhabet");
11 Safe.ArgumentNotNull(alphabet, "aplhabet");
12
12
13 m_alphabet = alphabet;
13 m_alphabet = alphabet;
14 }
14 }
15
15
16
16
17 public IAlphabet<TInput> InputAlphabet {
17 public IAlphabet<TInput> InputAlphabet {
18 get {
18 get {
19 return m_alphabet;
19 return m_alphabet;
20 }
20 }
21 }
21 }
22
22
23 public void MarkFinalState(int s, TTag[] tags) {
23 public void MarkFinalState(int s, TTag[] tags) {
24 MarkFinalState(s);
24 MarkFinalState(s);
25 SetStateTag(s, tags);
25 SetStateTag(s, tags);
26 }
26 }
27
27
28 public void SetStateTag(int s, TTag[] tags) {
28 public void SetStateTag(int s, TTag[] tags) {
29 Safe.ArgumentNotNull(tags, "tags");
29 Safe.ArgumentNotNull(tags, "tags");
30 m_tags[s] = tags;
30 m_tags[s] = tags;
31 }
31 }
32
32
33 public TTag[] GetStateTag(int s) {
33 public TTag[] GetStateTag(int s) {
34 TTag[] tags;
34 TTag[] tags;
35 return m_tags.TryGetValue(s, out tags) ? tags : new TTag[0];
35 return m_tags.TryGetValue(s, out tags) ? tags : new TTag[0];
36 }
36 }
37
37
38 public TTag[][] CreateTagTable() {
38 public TTag[][] CreateTagTable() {
39 var table = new TTag[StateCount][];
39 var table = new TTag[StateCount][];
40
40
41 foreach (var pair in m_tags)
41 foreach (var pair in m_tags)
42 table[pair.Key] = pair.Value;
42 table[pair.Key] = pair.Value;
43
43
44 return table;
44 return table;
45 }
45 }
46
46
47 /// <summary>
47 /// <summary>
48 /// Optimize the specified alphabet.
48 /// Optimize the specified alphabet.
49 /// </summary>
49 /// </summary>
50 /// <param name="alphabet">Пустой алфавит, который будет зполнен в процессе оптимизации.</param>
50 /// <param name="alphabet">Пустой алфавит, который будет зполнен в процессе оптимизации.</param>
51 public RegularDFA<TInput,TTag> Optimize(IAlphabetBuilder<TInput> alphabet) {
51 public RegularDFA<TInput,TTag> Optimize(IAlphabetBuilder<TInput> alphabet) {
52 Safe.ArgumentNotNull(alphabet, "alphabet");
52 Safe.ArgumentNotNull(alphabet, "alphabet");
53
53
54 var dfa = new RegularDFA<TInput, TTag>(alphabet);
54 var dfa = new RegularDFA<TInput, TTag>(alphabet);
55
55
56 var states = new DummyAlphabet(StateCount);
57 var alphaMap = new Dictionary<int,int>();
56 var alphaMap = new Dictionary<int,int>();
58 var stateMap = new Dictionary<int,int>();
57 var stateMap = new Dictionary<int,int>();
59
58
60 Optimize(dfa, alphaMap, stateMap);
59 Optimize(dfa, alphaMap, stateMap);
61
60
62 // mark tags in the new DFA
61 // mark tags in the new DFA
63 foreach (var g in m_tags.Where(x => x.Key < StateCount).GroupBy(x => stateMap[x.Key], x => x.Value ))
62 foreach (var g in m_tags.Where(x => x.Key < StateCount).GroupBy(x => stateMap[x.Key], x => x.Value ))
64 dfa.SetStateTag(g.Key, g.SelectMany(x => x).ToArray());
63 dfa.SetStateTag(g.Key, g.SelectMany(x => x).ToArray());
65
64
66 // make the alphabet for the new DFA
65 // make the alphabet for the new DFA
67 foreach (var pair in alphaMap)
66 foreach (var pair in alphaMap)
68 alphabet.DefineClass(m_alphabet.GetSymbols(pair.Key), pair.Value);
67 alphabet.DefineClass(m_alphabet.GetSymbols(pair.Key), pair.Value);
69
68
70 return dfa;
69 return dfa;
71 }
70 }
72
71
73 protected override IEnumerable<HashSet<int>> GroupFinalStates() {
72 protected override IEnumerable<HashSet<int>> GroupFinalStates() {
74 var arrayComparer = new CustomEqualityComparer<TTag[]>(
73 var arrayComparer = new CustomEqualityComparer<TTag[]>(
75 (x,y) => x.Length == y.Length && x.All(it => y.Contains(it)),
74 (x,y) => x.Length == y.Length && x.All(it => y.Contains(it)),
76 x => x.Sum(it => x.GetHashCode())
75 x => x.Sum(it => x.GetHashCode())
77 );
76 );
78 return FinalStates.GroupBy(x => m_tags[x], arrayComparer).Select(g => new HashSet<int>(g));
77 return FinalStates.GroupBy(x => m_tags[x], arrayComparer).Select(g => new HashSet<int>(g));
79 }
78 }
80
79
81 }
80 }
82 }
81 }
83
82
@@ -1,44 +1,63
1 using System;
1 using System;
2 using System.Threading;
2 using System.Threading;
3
3
4 namespace Implab.Components {
4 namespace Implab.Components {
5 /// <summary>
6 /// Creates an instace on-demand and allows it to be garbage collected.
7 /// </summary>
8 /// <remarks>
9 /// Usefull when dealing with memory-intensive objects which are frequently used.
10 /// This class is similar to <see cref="ObjectPool{T}"/> except is a singleton.
11 /// </remarks>
5 public class LazyAndWeak<T> where T : class {
12 public class LazyAndWeak<T> where T : class {
6
13
7 readonly Func<T> m_factory;
14 readonly Func<T> m_factory;
8 readonly object m_lock;
15 readonly object m_lock;
9 WeakReference m_reference;
16 WeakReference m_reference;
10
17
11
18
12 public LazyAndWeak(Func<T> factory, bool useLock) {
19 public LazyAndWeak(Func<T> factory, bool useLock) {
13 Safe.ArgumentNotNull(factory, "factory");
20 Safe.ArgumentNotNull(factory, "factory");
14 m_factory = factory;
21 m_factory = factory;
15 m_lock = useLock ? new object() : null;
22 m_lock = useLock ? new object() : null;
16 }
23 }
17
24
18 public LazyAndWeak(Func<T> factory) : this(factory, false) {
25 public LazyAndWeak(Func<T> factory) : this(factory, false) {
19 }
26 }
20
27
21 public T Value {
28 public T Value {
22 get {
29 get {
23 while (true) {
30 while (true) {
24 var weak = m_reference;
31 var weak = m_reference;
25 T value;
32 T value;
26 if (weak != null) {
33 if (weak != null) {
27 value = weak.Target as T;
34 value = weak.Target as T;
28 if (value != null)
35 if (value != null)
29 return value;
36 return value;
30 }
37 }
31
38
32 if (m_lock == null) {
39 if (m_lock == null) {
33 value = m_factory();
40 value = m_factory();
34
41
35 if (Interlocked.CompareExchange(ref m_reference, new WeakReference(value), weak) == weak)
42 if (Interlocked.CompareExchange(ref m_reference, new WeakReference(value), weak) == weak)
36 return value;
43 return value;
37 } else {
44 } else {
45 lock (m_lock) {
46 // double check
47 if (weak != null) {
48 value = weak.Target as T;
49 if (value != null)
50 return value;
51 }
52 // we are safe to write
53 value = m_factory();
54 m_reference = new WeakReference(value);
55 return value;
56 }
38 }
57 }
39 }
58 }
40 }
59 }
41 }
60 }
42 }
61 }
43 }
62 }
44
63
@@ -1,58 +1,58
1 using System;
1 using System;
2 using Implab.Parsing;
2 using Implab.Formats;
3
3
4 namespace Implab.Components {
4 namespace Implab.Components {
5 public class RunnableComponent : Disposable, IRunnable, IInitializable {
5 public class RunnableComponent : Disposable, IRunnable, IInitializable {
6
6
7
7
8
8
9
9
10
10
11 IPromise m_pending;
11 IPromise m_pending;
12 Exception m_lastError;
12 Exception m_lastError;
13
13
14 protected RunnableComponent(bool initialized) {
14 protected RunnableComponent(bool initialized) {
15
15
16 }
16 }
17
17
18 #region IInitializable implementation
18 #region IInitializable implementation
19
19
20 public void Init() {
20 public void Init() {
21
21
22 }
22 }
23
23
24 #endregion
24 #endregion
25
25
26 #region IRunnable implementation
26 #region IRunnable implementation
27
27
28 public IPromise Start() {
28 public IPromise Start() {
29 throw new NotImplementedException();
29 throw new NotImplementedException();
30 }
30 }
31
31
32 protected virtual IPromise OnStart() {
32 protected virtual IPromise OnStart() {
33 return Promise.SUCCESS;
33 return Promise.SUCCESS;
34 }
34 }
35
35
36 protected virtual void Run() {
36 protected virtual void Run() {
37 }
37 }
38
38
39 public IPromise Stop() {
39 public IPromise Stop() {
40 throw new NotImplementedException();
40 throw new NotImplementedException();
41 }
41 }
42
42
43 public ExecutionState State {
43 public ExecutionState State {
44 get {
44 get {
45 throw new NotImplementedException();
45 throw new NotImplementedException();
46 }
46 }
47 }
47 }
48
48
49 public Exception LastError {
49 public Exception LastError {
50 get {
50 get {
51 throw new NotImplementedException();
51 throw new NotImplementedException();
52 }
52 }
53 }
53 }
54
54
55 #endregion
55 #endregion
56 }
56 }
57 }
57 }
58
58
@@ -1,10 +1,11
1 namespace Implab.Formats.JSON {
1 namespace Implab.Formats.JSON {
2 /// <summary>
2 /// <summary>
3 /// internal
3 /// internal
4 /// </summary>
4 /// </summary>
5 enum JSONElementContext {
5 enum JSONElementContext {
6 None,
6 None,
7 Object,
7 Object,
8 Array
8 Array,
9 Closed
9 }
10 }
10 }
11 }
@@ -1,111 +1,119
1 using System.Linq;
1 using System.Linq;
2 using Implab.Automaton.RegularExpressions;
2 using Implab.Automaton.RegularExpressions;
3 using System;
3 using System;
4 using Implab.Automaton;
4 using Implab.Automaton;
5 using Implab.Components;
5
6
6 namespace Implab.Formats.JSON {
7 namespace Implab.Formats.JSON {
7 class JSONGrammar : Grammar<char> {
8 class JSONGrammar : Grammar<char> {
8 public enum TokenType {
9 public enum TokenType {
9 None,
10 None,
10 BeginObject,
11 BeginObject,
11 EndObject,
12 EndObject,
12 BeginArray,
13 BeginArray,
13 EndArray,
14 EndArray,
14 String,
15 String,
15 Number,
16 Number,
16 Literal,
17 Literal,
17 NameSeparator,
18 NameSeparator,
18 ValueSeparator,
19 ValueSeparator,
19
20
20 StringBound,
21 StringBound,
21 EscapedChar,
22 EscapedChar,
22 UnescapedChar,
23 UnescapedChar,
23 EscapedUnicode
24 EscapedUnicode
24 }
25 }
25
26
26 static Lazy<JSONGrammar> _instance = new Lazy<JSONGrammar>();
27 static LazyAndWeak<JSONGrammar> _instance = new LazyAndWeak<JSONGrammar>(() => new JSONGrammar());
27
28
28 public static JSONGrammar Instance {
29 public static JSONGrammar Instance {
29 get { return _instance.Value; }
30 get { return _instance.Value; }
30 }
31 }
31
32
32 readonly ScannerContext<TokenType> m_jsonExpression;
33 readonly ScannerContext<TokenType> m_jsonExpression;
33 readonly ScannerContext<TokenType> m_stringExpression;
34 readonly ScannerContext<TokenType> m_stringExpression;
35 readonly CharAlphabet m_defaultAlphabet = new CharAlphabet();
34
36
35 public JSONGrammar() {
37 public JSONGrammar() {
36 DefineAlphabet(Enumerable.Range(0, 0x20).Select(x => (char)x));
38 DefineAlphabet(Enumerable.Range(0, 0x20).Select(x => (char)x));
37 var hexDigit = SymbolRangeToken('a','f').Or(SymbolRangeToken('A','F')).Or(SymbolRangeToken('0','9'));
39 var hexDigit = SymbolRangeToken('a','f').Or(SymbolRangeToken('A','F')).Or(SymbolRangeToken('0','9'));
38 var digit9 = SymbolRangeToken('1', '9');
40 var digit9 = SymbolRangeToken('1', '9');
39 var zero = SymbolToken('0');
41 var zero = SymbolToken('0');
40 var digit = zero.Or(digit9);
42 var digit = zero.Or(digit9);
41 var dot = SymbolToken('.');
43 var dot = SymbolToken('.');
42 var minus = SymbolToken('-');
44 var minus = SymbolToken('-');
43 var sign = SymbolSetToken('-', '+');
45 var sign = SymbolSetToken('-', '+');
44 var expSign = SymbolSetToken('e', 'E');
46 var expSign = SymbolSetToken('e', 'E');
45 var letters = SymbolRangeToken('a', 'z');
47 var letters = SymbolRangeToken('a', 'z');
46 var integer = zero.Or(digit9.Cat(digit.EClosure()));
48 var integer = zero.Or(digit9.Cat(digit.EClosure()));
47 var frac = dot.Cat(digit.Closure());
49 var frac = dot.Cat(digit.Closure());
48 var exp = expSign.Cat(sign.Optional()).Cat(digit.Closure());
50 var exp = expSign.Cat(sign.Optional()).Cat(digit.Closure());
49 var quote = SymbolToken('"');
51 var quote = SymbolToken('"');
50 var backSlash = SymbolToken('\\');
52 var backSlash = SymbolToken('\\');
51 var specialEscapeChars = SymbolSetToken('\\', '"', '/', 'b', 'f', 't', 'n', 'r');
53 var specialEscapeChars = SymbolSetToken('\\', '"', '/', 'b', 'f', 't', 'n', 'r');
52 var unicodeEspace = SymbolToken('u').Cat(hexDigit.Repeat(4));
54 var unicodeEspace = SymbolToken('u').Cat(hexDigit.Repeat(4));
53 var whitespace = SymbolSetToken('\n', '\r', '\t', ' ').EClosure();
55 var whitespace = SymbolSetToken('\n', '\r', '\t', ' ').EClosure();
54 var beginObject = whitespace.Cat(SymbolToken('{')).Cat(whitespace);
56 var beginObject = whitespace.Cat(SymbolToken('{')).Cat(whitespace);
55 var endObject = whitespace.Cat(SymbolToken('}')).Cat(whitespace);
57 var endObject = whitespace.Cat(SymbolToken('}')).Cat(whitespace);
56 var beginArray = whitespace.Cat(SymbolToken('[')).Cat(whitespace);
58 var beginArray = whitespace.Cat(SymbolToken('[')).Cat(whitespace);
57 var endArray = whitespace.Cat(SymbolToken(']')).Cat(whitespace);
59 var endArray = whitespace.Cat(SymbolToken(']')).Cat(whitespace);
58 var nameSep = whitespace.Cat(SymbolToken(':')).Cat(whitespace);
60 var nameSep = whitespace.Cat(SymbolToken(':')).Cat(whitespace);
59 var valueSep = whitespace.Cat(SymbolToken(',')).Cat(whitespace);
61 var valueSep = whitespace.Cat(SymbolToken(',')).Cat(whitespace);
60
62
61 var number = minus.Optional().Cat(integer).Cat(frac.Optional()).Cat(exp.Optional());
63 var number = minus.Optional().Cat(integer).Cat(frac.Optional()).Cat(exp.Optional());
62 var literal = letters.Closure();
64 var literal = letters.Closure();
63 var unescaped = SymbolTokenExcept(Enumerable.Range(0, 0x20).Union(new int[] { '\\', '"' }).Select(x => (char)x));
65 var unescaped = SymbolTokenExcept(Enumerable.Range(0, 0x20).Union(new int[] { '\\', '"' }).Select(x => (char)x));
64
66
65 var jsonExpression =
67 var jsonExpression =
66 number.Tag(TokenType.Number)
68 number.Tag(TokenType.Number)
67 .Or(literal.Tag(TokenType.Literal))
69 .Or(literal.Tag(TokenType.Literal))
68 .Or(quote.Tag(TokenType.StringBound))
70 .Or(quote.Tag(TokenType.StringBound))
69 .Or(beginObject.Tag(TokenType.BeginObject))
71 .Or(beginObject.Tag(TokenType.BeginObject))
70 .Or(endObject.Tag(TokenType.EndObject))
72 .Or(endObject.Tag(TokenType.EndObject))
71 .Or(beginArray.Tag(TokenType.BeginArray))
73 .Or(beginArray.Tag(TokenType.BeginArray))
72 .Or(endArray.Tag(TokenType.EndArray))
74 .Or(endArray.Tag(TokenType.EndArray))
73 .Or(nameSep.Tag(TokenType.NameSeparator))
75 .Or(nameSep.Tag(TokenType.NameSeparator))
74 .Or(valueSep.Tag(TokenType.ValueSeparator));
76 .Or(valueSep.Tag(TokenType.ValueSeparator));
75
77
76
78
77 var jsonStringExpression =
79 var jsonStringExpression =
78 quote.Tag(TokenType.StringBound)
80 quote.Tag(TokenType.StringBound)
79 .Or(backSlash.Cat(specialEscapeChars).Tag(TokenType.EscapedChar))
81 .Or(backSlash.Cat(specialEscapeChars).Tag(TokenType.EscapedChar))
80 .Or(backSlash.Cat(unicodeEspace).Tag(TokenType.EscapedUnicode))
82 .Or(backSlash.Cat(unicodeEspace).Tag(TokenType.EscapedUnicode))
81 .Or(unescaped.Closure().Tag(TokenType.UnescapedChar));
83 .Or(unescaped.Closure().Tag(TokenType.UnescapedChar));
82
84
83
85
84 m_jsonExpression = BuildScannerContext<TokenType>(jsonExpression);
86 m_jsonExpression = BuildScannerContext<TokenType>(jsonExpression);
85 m_stringExpression = BuildScannerContext<TokenType>(jsonStringExpression);
87 m_stringExpression = BuildScannerContext<TokenType>(jsonStringExpression);
86
88
87
89
88 }
90 }
89
91
92 protected override IAlphabetBuilder<char> AlphabetBuilder {
93 get {
94 return m_defaultAlphabet;
95 }
96 }
97
90 public ScannerContext<TokenType> JsonExpression {
98 public ScannerContext<TokenType> JsonExpression {
91 get {
99 get {
92 return m_jsonExpression;
100 return m_jsonExpression;
93 }
101 }
94 }
102 }
95
103
96 public ScannerContext<TokenType> JsonStringExpression {
104 public ScannerContext<TokenType> JsonStringExpression {
97 get {
105 get {
98 return m_stringExpression;
106 return m_stringExpression;
99 }
107 }
100 }
108 }
101
109
102 Token SymbolRangeToken(char start, char stop) {
110 Token SymbolRangeToken(char start, char stop) {
103 return SymbolToken(Enumerable.Range(start,stop - start).Cast<char>());
111 return SymbolToken(Enumerable.Range(start,stop - start).Cast<char>());
104 }
112 }
105
113
106 protected override IAlphabetBuilder<char> CreateAlphabet() {
114 protected override IndexedAlphabetBase<char> CreateAlphabet() {
107 return new CharAlphabet();
115 return new CharAlphabet();
108 }
116 }
109
117
110 }
118 }
111 }
119 }
@@ -1,295 +1,293
1 using System;
1 using System;
2 using System.Diagnostics;
2 using System.Diagnostics;
3 using System.IO;
3 using System.IO;
4 using Implab.Automaton;
4 using Implab.Automaton;
5 using Implab.Automaton.RegularExpressions;
5 using Implab.Automaton.RegularExpressions;
6 using System.Linq;
6 using System.Linq;
7 using Implab.Components;
7 using Implab.Components;
8 using System.Collections.Generic;
8
9
9 namespace Implab.Formats.JSON {
10 namespace Implab.Formats.JSON {
10 /// <summary>
11 /// <summary>
11 /// internal
12 /// </summary>
13 public struct JSONParserContext {
14 public string memberName;
15 public JSONElementContext elementContext;
16 }
17
18 /// <summary>
19 /// Pull парсер JSON данных.
12 /// Pull парсер JSON данных.
20 /// </summary>
13 /// </summary>
21 /// <remarks>
14 /// <remarks>
22 /// Следует отметить отдельную интерпретацию свойства <see cref="Level"/>,
15 /// Следует отметить отдельную интерпретацию свойства <see cref="Level"/>,
23 /// оно означает текущий уровень вложенности объектов, однако закрывающий
16 /// оно означает текущий уровень вложенности объектов, однако закрывающий
24 /// элемент объекта и массива имеет уровень меньше, чем сам объект.
17 /// элемент объекта и массива имеет уровень меньше, чем сам объект.
25 /// <code>
18 /// <code>
26 /// { // Level = 1
19 /// { // Level = 1
27 /// "name" : "Peter", // Level = 1
20 /// "name" : "Peter", // Level = 1
28 /// "address" : { // Level = 2
21 /// "address" : { // Level = 2
29 /// city : "Stern" // Level = 2
22 /// city : "Stern" // Level = 2
30 /// } // Level = 1
23 /// } // Level = 1
31 /// } // Level = 0
24 /// } // Level = 0
32 /// </code>
25 /// </code>
33 /// </remarks>
26 /// </remarks>
34 public class JSONParser : Disposable {
27 public class JSONParser : Disposable {
35
28
36 enum MemberContext {
29 enum MemberContext {
37 MemberName,
30 MemberName,
38 MemberValue
31 MemberValue
39 }
32 }
40
33
41 #region Parser rules
34 #region Parser rules
42 struct ParserContext {
35 struct ParserContext {
43 readonly int[,] m_dfa;
36 readonly int[,] m_dfa;
44 int m_state;
37 int m_state;
45
38
46 readonly JSONElementContext m_elementContext;
39 readonly JSONElementContext m_elementContext;
47
40
48 public ParserContext(int[,] dfa, int state, JSONElementContext context) {
41 public ParserContext(int[,] dfa, int state, JSONElementContext context) {
49 m_dfa = dfa;
42 m_dfa = dfa;
50 m_state = state;
43 m_state = state;
51 m_elementContext = context;
44 m_elementContext = context;
52 }
45 }
53
46
54 public bool Move(JsonTokenType token) {
47 public bool Move(JsonTokenType token) {
55 var next = m_dfa[m_state, token];
48 var next = m_dfa[m_state, (int)token];
56 if (next == AutomatonConst.UNREACHABLE_STATE)
49 if (next == AutomatonConst.UNREACHABLE_STATE)
57 return false;
50 return false;
58 m_state = next;
51 m_state = next;
52 return true;
59 }
53 }
60
54
61 public JSONElementContext ElementContext {
55 public JSONElementContext ElementContext {
62 get { return m_elementContext; }
56 get { return m_elementContext; }
63 }
57 }
64 }
58 }
65
59
60 static readonly ParserContext _jsonContext;
61 static readonly ParserContext _objectContext;
62 static readonly ParserContext _arrayContext;
63
66 static JSONParser() {
64 static JSONParser() {
67
65
68
66 var valueExpression = MakeToken(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String);
69 var valueExpression = Token(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String);
67 var memberExpression = MakeToken(JsonTokenType.String).Cat(MakeToken(JsonTokenType.NameSeparator)).Cat(valueExpression);
70 var memberExpression = Token(JsonTokenType.String).Cat(Token(JsonTokenType.NameSeparator)).Cat(valueExpression);
71
68
72 var objectExpression = memberExpression
69 var objectExpression = memberExpression
73 .Cat(
70 .Cat(
74 Token(JsonTokenType.ValueSeparator)
71 MakeToken(JsonTokenType.ValueSeparator)
75 .Cat(memberExpression)
72 .Cat(memberExpression)
76 .EClosure()
73 .EClosure()
77 )
74 )
78 .Optional()
75 .Optional()
79 .Cat(Token(JsonTokenType.EndObject))
76 .Cat(MakeToken(JsonTokenType.EndObject))
80 .End();
77 .End();
81
78
82 var arrayExpression = valueExpression
79 var arrayExpression = valueExpression
83 .Cat(
80 .Cat(
84 Token(JsonTokenType.ValueSeparator)
81 MakeToken(JsonTokenType.ValueSeparator)
85 .Cat(valueExpression)
82 .Cat(valueExpression)
86 .EClosure()
83 .EClosure()
87 )
84 )
88 .Optional()
85 .Optional()
89 .Cat(Token(JsonTokenType.EndArray))
86 .Cat(MakeToken(JsonTokenType.EndArray))
90 .End();
87 .End();
91
88
92 var jsonExpression = valueExpression.End();
89 var jsonExpression = valueExpression.End();
93
90
94 _jsonDFA = CreateParserContext(jsonExpression, JSONElementContext.None);
91 _jsonContext = CreateParserContext(jsonExpression, JSONElementContext.None);
95 _objectDFA = CreateParserContext(objectExpression, JSONElementContext.Object);
92 _objectContext = CreateParserContext(objectExpression, JSONElementContext.Object);
96 _arrayDFA = CreateParserContext(arrayExpression, JSONElementContext.Array);
93 _arrayContext = CreateParserContext(arrayExpression, JSONElementContext.Array);
97 }
94 }
98
95
99 static Token Token(params JsonTokenType[] input) {
96 static Token MakeToken(params JsonTokenType[] input) {
100 return Token.New( input.Select(t => (int)t).ToArray() );
97 return Token.New( input.Select(t => (int)t).ToArray() );
101 }
98 }
102
99
103 static ParserContext CreateParserContext(Token expr, JSONElementContext context) {
100 static ParserContext CreateParserContext(Token expr, JSONElementContext context) {
104
101
105 var dfa = new DFATable();
102 var dfa = new DFATable();
106 var builder = new RegularExpressionVisitor(dfa);
103 var builder = new RegularExpressionVisitor(dfa);
107 expr.Accept(builder);
104 expr.Accept(builder);
108 builder.BuildDFA();
105 builder.BuildDFA();
109
106
110 return new ParserContext(dfa.CreateTransitionTable(), dfa.InitialState, context);
107 return new ParserContext(dfa.CreateTransitionTable(), dfa.InitialState, context);
111 }
108 }
112
109
113 #endregion
110 #endregion
114
111
115 JSONScanner m_scanner;
112 readonly JSONScanner m_scanner;
116 MemberContext m_memberContext;
113 MemberContext m_memberContext;
117
114
118 JSONElementType m_elementType;
115 JSONElementType m_elementType;
119 object m_elementValue;
116 object m_elementValue;
117 string m_memberName = String.Empty;
118
119 Stack<ParserContext> m_stack = new Stack<ParserContext>();
120 ParserContext m_context = _jsonContext;
120
121
121 /// <summary>
122 /// <summary>
122 /// Создает новый парсер на основе строки, содержащей JSON
123 /// Создает новый парсер на основе строки, содержащей JSON
123 /// </summary>
124 /// </summary>
124 /// <param name="text"></param>
125 /// <param name="text"></param>
125 public JSONParser(string text)
126 public JSONParser(string text) {
126 : base(_jsonDFA, INITIAL_STATE, new JSONParserContext { elementContext = JSONElementContext.None, memberName = String.Empty }) {
127 Safe.ArgumentNotEmpty(text, "text");
127 Safe.ArgumentNotEmpty(text, "text");
128 m_scanner = new JSONScanner();
128 m_scanner = new JSONScanner(text);
129 m_scanner.Feed(text.ToCharArray());
130 }
129 }
131
130
132 /// <summary>
131 /// <summary>
133 /// Создает новый экземпляр парсера, на основе текстового потока.
132 /// Создает новый экземпляр парсера, на основе текстового потока.
134 /// </summary>
133 /// </summary>
135 /// <param name="reader">Текстовый поток.</param>
134 /// <param name="reader">Текстовый поток.</param>
136 public JSONParser(TextReader reader)
135 public JSONParser(TextReader reader) {
137 : base(_jsonDFA, INITIAL_STATE, new JSONParserContext { elementContext = JSONElementContext.None, memberName = String.Empty }) {
138 Safe.ArgumentNotNull(reader, "reader");
136 Safe.ArgumentNotNull(reader, "reader");
139 m_scanner = new JSONScanner();
137 m_scanner = new JSONScanner(reader);
140 m_scanner.Feed(reader, dispose);
138 }
139
140 public int Level {
141 get { return m_stack.Count; }
141 }
142 }
142
143
143 /// <summary>
144 /// <summary>
144 /// Тип текущего элемента на котором стоит парсер.
145 /// Тип текущего элемента на котором стоит парсер.
145 /// </summary>
146 /// </summary>
146 public JSONElementType ElementType {
147 public JSONElementType ElementType {
147 get { return m_elementType; }
148 get { return m_elementType; }
148 }
149 }
149
150
150 /// <summary>
151 /// <summary>
151 /// Имя элемента - имя свойства родительского контейнера. Для элементов массивов и корневого всегда
152 /// Имя элемента - имя свойства родительского контейнера. Для элементов массивов и корневого всегда
152 /// пустая строка.
153 /// пустая строка.
153 /// </summary>
154 /// </summary>
154 public string ElementName {
155 public string ElementName {
155 get { return m_context.info.memberName; }
156 get { return m_memberName; }
156 }
157 }
157
158
158 /// <summary>
159 /// <summary>
159 /// Значение элемента. Только для элементов типа <see cref="JSONElementType.Value"/>, для остальных <c>null</c>
160 /// Значение элемента. Только для элементов типа <see cref="JSONElementType.Value"/>, для остальных <c>null</c>
160 /// </summary>
161 /// </summary>
161 public object ElementValue {
162 public object ElementValue {
162 get { return m_elementValue; }
163 get { return m_elementValue; }
163 }
164 }
164
165
165 /// <summary>
166 /// <summary>
166 /// Читает слеюудущий объект из потока
167 /// Читает слеюудущий объект из потока
167 /// </summary>
168 /// </summary>
168 /// <returns><c>true</c> - операция чтения прошла успешно, <c>false</c> - конец данных</returns>
169 /// <returns><c>true</c> - операция чтения прошла успешно, <c>false</c> - конец данных</returns>
169 public bool Read() {
170 public bool Read() {
170 if (m_context.current == UNREACHEBLE_STATE)
171 throw new InvalidOperationException("The parser is in invalid state");
172 object tokenValue;
171 object tokenValue;
173 JsonTokenType tokenType;
172 JsonTokenType tokenType;
174 m_context.info.memberName = String.Empty;
173
174 m_memberName = String.Empty;
175
175 while (m_scanner.ReadToken(out tokenValue, out tokenType)) {
176 while (m_scanner.ReadToken(out tokenValue, out tokenType)) {
176 Move((int)tokenType);
177 if(!m_context.Move(tokenType))
177 if (m_context.current == UNREACHEBLE_STATE)
178 UnexpectedToken(tokenValue, tokenType);
178 UnexpectedToken(tokenValue, tokenType);
179
179 switch (tokenType) {
180 switch (tokenType) {
180 case JsonTokenType.BeginObject:
181 case JsonTokenType.BeginObject:
181 Switch(
182 m_stack.Push(m_context);
182 _objectDFA,
183 m_context = _objectContext;
183 INITIAL_STATE,
184
184 new JSONParserContext {
185 memberName = m_context.info.memberName,
186 elementContext = JSONElementContext.Object
187 }
188 );
189 m_elementValue = null;
185 m_elementValue = null;
190 m_memberContext = MemberContext.MemberName;
186 m_memberContext = MemberContext.MemberName;
191 m_elementType = JSONElementType.BeginObject;
187 m_elementType = JSONElementType.BeginObject;
192 return true;
188 return true;
193 case JsonTokenType.EndObject:
189 case JsonTokenType.EndObject:
194 Restore();
190 if (m_stack.Count == 0)
191 UnexpectedToken(tokenValue, tokenType);
192 m_context = m_stack.Pop();
193
195 m_elementValue = null;
194 m_elementValue = null;
196 m_elementType = JSONElementType.EndObject;
195 m_elementType = JSONElementType.EndObject;
197 return true;
196 return true;
198 case JsonTokenType.BeginArray:
197 case JsonTokenType.BeginArray:
199 Switch(
198 m_stack.Push(m_context);
200 _arrayDFA,
199 m_context = _arrayContext;
201 INITIAL_STATE,
200
202 new JSONParserContext {
203 memberName = m_context.info.memberName,
204 elementContext = JSONElementContext.Array
205 }
206 );
207 m_elementValue = null;
201 m_elementValue = null;
208 m_memberContext = MemberContext.MemberValue;
202 m_memberContext = MemberContext.MemberValue;
209 m_elementType = JSONElementType.BeginArray;
203 m_elementType = JSONElementType.BeginArray;
210 return true;
204 return true;
211 case JsonTokenType.EndArray:
205 case JsonTokenType.EndArray:
212 Restore();
206 if (m_stack.Count == 0)
207 UnexpectedToken(tokenValue, tokenType);
208 m_context = m_stack.Pop();
209
213 m_elementValue = null;
210 m_elementValue = null;
214 m_elementType = JSONElementType.EndArray;
211 m_elementType = JSONElementType.EndArray;
215 return true;
212 return true;
216 case JsonTokenType.String:
213 case JsonTokenType.String:
217 if (m_memberContext == MemberContext.MemberName) {
214 if (m_memberContext == MemberContext.MemberName) {
218 m_context.info.memberName = (string)tokenValue;
215 m_memberName = (string)tokenValue;
219 break;
216 break;
220 }
217 }
221 m_elementType = JSONElementType.Value;
218 m_elementType = JSONElementType.Value;
222 m_elementValue = tokenValue;
219 m_elementValue = tokenValue;
223 return true;
220 return true;
224 case JsonTokenType.Number:
221 case JsonTokenType.Number:
225 m_elementType = JSONElementType.Value;
222 m_elementType = JSONElementType.Value;
226 m_elementValue = tokenValue;
223 m_elementValue = tokenValue;
227 return true;
224 return true;
228 case JsonTokenType.Literal:
225 case JsonTokenType.Literal:
229 m_elementType = JSONElementType.Value;
226 m_elementType = JSONElementType.Value;
230 m_elementValue = ParseLiteral((string)tokenValue);
227 m_elementValue = ParseLiteral((string)tokenValue);
231 return true;
228 return true;
232 case JsonTokenType.NameSeparator:
229 case JsonTokenType.NameSeparator:
233 m_memberContext = MemberContext.MemberValue;
230 m_memberContext = MemberContext.MemberValue;
234 break;
231 break;
235 case JsonTokenType.ValueSeparator:
232 case JsonTokenType.ValueSeparator:
236 m_memberContext = m_context.info.elementContext == JSONElementContext.Object ? MemberContext.MemberName : MemberContext.MemberValue;
233 m_memberContext = m_context.ElementContext == JSONElementContext.Object ? MemberContext.MemberName : MemberContext.MemberValue;
237 break;
234 break;
238 default:
235 default:
239 UnexpectedToken(tokenValue, tokenType);
236 UnexpectedToken(tokenValue, tokenType);
240 break;
237 break;
241 }
238 }
242 }
239 }
243 if (m_context.info.elementContext != JSONElementContext.None)
240 if (m_context.ElementContext != JSONElementContext.None)
244 throw new ParserException("Unexpedted end of data");
241 throw new ParserException("Unexpedted end of data");
242
243 EOF = true;
244
245 return false;
245 return false;
246 }
246 }
247
247
248 object ParseLiteral(string literal) {
248 object ParseLiteral(string literal) {
249 switch (literal) {
249 switch (literal) {
250 case "null":
250 case "null":
251 return null;
251 return null;
252 case "false":
252 case "false":
253 return false;
253 return false;
254 case "true":
254 case "true":
255 return true;
255 return true;
256 default:
256 default:
257 UnexpectedToken(literal, JsonTokenType.Literal);
257 UnexpectedToken(literal, JsonTokenType.Literal);
258 return null; // avoid compliler error
258 return null; // avoid compliler error
259 }
259 }
260 }
260 }
261
261
262 void UnexpectedToken(object value, JsonTokenType tokenType) {
262 void UnexpectedToken(object value, JsonTokenType tokenType) {
263 throw new ParserException(String.Format("Unexpected token {0}: '{1}'", tokenType, value));
263 throw new ParserException(String.Format("Unexpected token {0}: '{1}'", tokenType, value));
264 }
264 }
265
265
266
266
267 /// <summary>
267 /// <summary>
268 /// Признак конца потока
268 /// Признак конца потока
269 /// </summary>
269 /// </summary>
270 public bool EOF {
270 public bool EOF {
271 get {
271 get;
272 return m_scanner.EOF;
272 private set;
273 }
274 }
273 }
275
274
276 protected override void Dispose(bool disposing) {
275 protected override void Dispose(bool disposing) {
277 if (disposing) {
276 if (disposing)
278 m_scanner.Dispose();
277 Safe.Dispose(m_scanner);
279 }
280 }
278 }
281
279
282 /// <summary>
280 /// <summary>
283 /// Переходит в конец текущего объекта.
281 /// Переходит в конец текущего объекта.
284 /// </summary>
282 /// </summary>
285 public void SeekElementEnd() {
283 public void SeekElementEnd() {
286 var level = Level - 1;
284 var level = Level - 1;
287
285
288 Debug.Assert(level >= 0);
286 Debug.Assert(level >= 0);
289
287
290 while (Level != level)
288 while (Level != level)
291 Read();
289 Read();
292 }
290 }
293 }
291 }
294
292
295 }
293 }
@@ -1,104 +1,107
1 using System;
1 using System;
2 using System.Globalization;
2 using System.Globalization;
3 using Implab.Automaton;
3 using Implab.Automaton;
4 using System.Text;
4 using System.Text;
5 using Implab.Components;
5 using Implab.Components;
6 using System.IO;
6 using System.IO;
7
7
8 namespace Implab.Formats.JSON {
8 namespace Implab.Formats.JSON {
9 /// <summary>
9 /// <summary>
10 /// Сканнер (лексер), разбивающий поток символов на токены JSON.
10 /// Сканнер (лексер), разбивающий поток символов на токены JSON.
11 /// </summary>
11 /// </summary>
12 public class JSONScanner : Disposable {
12 public class JSONScanner : Disposable {
13 readonly StringBuilder m_builder = new StringBuilder();
13 readonly StringBuilder m_builder = new StringBuilder();
14
14
15 readonly ScannerContext<JSONGrammar.TokenType> m_jsonContext = JSONGrammar.Instance.JsonExpression;
15 readonly ScannerContext<JSONGrammar.TokenType> m_jsonContext = JSONGrammar.Instance.JsonExpression;
16 readonly ScannerContext<JSONGrammar.TokenType> m_stringContext = JSONGrammar.Instance.JsonStringExpression;
16 readonly ScannerContext<JSONGrammar.TokenType> m_stringContext = JSONGrammar.Instance.JsonStringExpression;
17
17
18
18
19 readonly TextScanner m_scanner;
19 readonly TextScanner m_scanner;
20
20
21 /// <summary>
21 /// <summary>
22 /// Создает новый экземпляр сканнера
22 /// Создает новый экземпляр сканнера
23 /// </summary>
23 /// </summary>
24 public JSONScanner(string text) {
24 public JSONScanner(string text) {
25 Safe.ArgumentNotEmpty(text, "text");
25 Safe.ArgumentNotEmpty(text, "text");
26
26
27 m_scanner = new StringScanner(text);
27 m_scanner = new StringScanner(text);
28 }
28 }
29
29
30 public JSONScanner(TextReader reader, int bufferMax, int chunkSize) {
30 public JSONScanner(TextReader reader, int bufferMax, int chunkSize) {
31 Safe.ArgumentNotNull(reader, "reader");
31 Safe.ArgumentNotNull(reader, "reader");
32
32
33 m_scanner = new ReaderScanner(reader, bufferMax, chunkSize);
33 m_scanner = new ReaderScanner(reader, bufferMax, chunkSize);
34 }
34 }
35
35
36 public JSONScanner(TextReader reader) : this(reader, 1024*1024, 1024){
37 }
38
36 /// <summary>
39 /// <summary>
37 /// Читает следующий лексический элемент из входных данных.
40 /// Читает следующий лексический элемент из входных данных.
38 /// </summary>
41 /// </summary>
39 /// <param name="tokenValue">Возвращает значение прочитанного токена.</param>
42 /// <param name="tokenValue">Возвращает значение прочитанного токена.</param>
40 /// <param name="tokenType">Возвращает тип прочитанного токена.</param>
43 /// <param name="tokenType">Возвращает тип прочитанного токена.</param>
41 /// <returns><c>true</c> - чтение произведено успешно. <c>false</c> - достигнут конец входных данных</returns>
44 /// <returns><c>true</c> - чтение произведено успешно. <c>false</c> - достигнут конец входных данных</returns>
42 /// <remarks>В случе если токен не распознается, возникает исключение. Значения токенов обрабатываются, т.е.
45 /// <remarks>В случе если токен не распознается, возникает исключение. Значения токенов обрабатываются, т.е.
43 /// в строках обрабатываются экранированные символы, числа становтся типа double.</remarks>
46 /// в строках обрабатываются экранированные символы, числа становтся типа double.</remarks>
44 public bool ReadToken(out object tokenValue, out JsonTokenType tokenType) {
47 public bool ReadToken(out object tokenValue, out JsonTokenType tokenType) {
45 JSONGrammar.TokenType[] tag;
48 JSONGrammar.TokenType[] tag;
46 if (m_jsonContext.Execute(m_scanner, out tag)) {
49 if (m_jsonContext.Execute(m_scanner, out tag)) {
47 switch (tag[0]) {
50 switch (tag[0]) {
48 case JSONGrammar.TokenType.StringBound:
51 case JSONGrammar.TokenType.StringBound:
49 tokenValue = ReadString();
52 tokenValue = ReadString();
50 tokenType = JsonTokenType.String;
53 tokenType = JsonTokenType.String;
51 break;
54 break;
52 case JSONGrammar.TokenType.Number:
55 case JSONGrammar.TokenType.Number:
53 tokenValue = Double.Parse(m_scanner.GetTokenValue(), CultureInfo.InvariantCulture);
56 tokenValue = Double.Parse(m_scanner.GetTokenValue(), CultureInfo.InvariantCulture);
54 tokenType = JsonTokenType.Number;
57 tokenType = JsonTokenType.Number;
55 break;
58 break;
56 default:
59 default:
57 tokenType = (JsonTokenType)tag[0];
60 tokenType = (JsonTokenType)tag[0];
58 tokenValue = m_scanner.GetTokenValue();
61 tokenValue = m_scanner.GetTokenValue();
59 break;
62 break;
60 }
63 }
61 return true;
64 return true;
62 }
65 }
63 tokenValue = null;
66 tokenValue = null;
64 tokenType = JsonTokenType.None;
67 tokenType = JsonTokenType.None;
65 return false;
68 return false;
66 }
69 }
67
70
68 string ReadString() {
71 string ReadString() {
69 int pos = 0;
72 int pos = 0;
70 var buf = new char[6]; // the buffer for unescaping chars
73 var buf = new char[6]; // the buffer for unescaping chars
71
74
72 JSONGrammar.TokenType[] tag;
75 JSONGrammar.TokenType[] tag;
73 m_builder.Clear();
76 m_builder.Clear();
74
77
75 while (m_stringContext.Execute(m_scanner, out tag)) {
78 while (m_stringContext.Execute(m_scanner, out tag)) {
76 switch (tag[0]) {
79 switch (tag[0]) {
77 case JSONGrammar.TokenType.StringBound:
80 case JSONGrammar.TokenType.StringBound:
78 return m_builder.ToString();
81 return m_builder.ToString();
79 case JSONGrammar.TokenType.UnescapedChar:
82 case JSONGrammar.TokenType.UnescapedChar:
80 m_scanner.CopyTokenTo(m_builder);
83 m_scanner.CopyTokenTo(m_builder);
81 break;
84 break;
82 case JSONGrammar.TokenType.EscapedUnicode: // \xXXXX - unicode escape sequence
85 case JSONGrammar.TokenType.EscapedUnicode: // \xXXXX - unicode escape sequence
83 m_scanner.CopyTokenTo(buf, 0);
86 m_scanner.CopyTokenTo(buf, 0);
84 m_builder.Append(StringTranslator.TranslateHexUnicode(buf, 2));
87 m_builder.Append(StringTranslator.TranslateHexUnicode(buf, 2));
85 pos++;
88 pos++;
86 break;
89 break;
87 case JSONGrammar.TokenType.EscapedChar: // \t - escape sequence
90 case JSONGrammar.TokenType.EscapedChar: // \t - escape sequence
88 m_scanner.CopyTokenTo(buf, 0);
91 m_scanner.CopyTokenTo(buf, 0);
89 m_builder.Append(StringTranslator.TranslateEscapedChar(buf[1]));
92 m_builder.Append(StringTranslator.TranslateEscapedChar(buf[1]));
90 break;
93 break;
91 }
94 }
92
95
93 }
96 }
94
97
95 throw new ParserException("Unexpected end of data");
98 throw new ParserException("Unexpected end of data");
96 }
99 }
97
100
98 protected override void Dispose(bool disposing) {
101 protected override void Dispose(bool disposing) {
99 if (disposing)
102 if (disposing)
100 Safe.Dispose(m_scanner);
103 Safe.Dispose(m_scanner);
101 base.Dispose(disposing);
104 base.Dispose(disposing);
102 }
105 }
103 }
106 }
104 }
107 }
@@ -1,319 +1,319
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.IO;
3 using System.IO;
4 using System.Globalization;
4 using System.Globalization;
5 using System.Diagnostics;
5 using System.Diagnostics;
6
6
7 namespace Implab.JSON {
7 namespace Implab.Formats.JSON {
8 public class JSONWriter {
8 public class JSONWriter {
9 struct Context {
9 struct Context {
10 public bool needComma;
10 public bool needComma;
11 public JSONElementContext element;
11 public JSONElementContext element;
12 }
12 }
13 Stack<Context> m_contextStack = new Stack<Context>();
13 Stack<Context> m_contextStack = new Stack<Context>();
14 Context m_context;
14 Context m_context;
15
15
16 const int BUFFER_SIZE = 64;
16 const int BUFFER_SIZE = 64;
17
17
18 TextWriter m_writer;
18 TextWriter m_writer;
19 readonly bool m_indent = true;
19 readonly bool m_indent = true;
20 readonly int m_indentSize = 4;
20 readonly int m_indentSize = 4;
21 readonly char[] m_buffer = new char[BUFFER_SIZE];
21 readonly char[] m_buffer = new char[BUFFER_SIZE];
22 int m_bufferPos;
22 int m_bufferPos;
23
23
24 static readonly char [] _hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
24 static readonly char [] _hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
25 static readonly char [] _escapeBKS,
25 static readonly char [] _escapeBKS,
26 _escapeFWD,
26 _escapeFWD,
27 _escapeCR,
27 _escapeCR,
28 _escapeNL,
28 _escapeNL,
29 _escapeTAB,
29 _escapeTAB,
30 _escapeBSLASH,
30 _escapeBSLASH,
31 _escapeQ;
31 _escapeQ;
32
32
33 static JSONWriter() {
33 static JSONWriter() {
34 _escapeBKS = "\\b".ToCharArray();
34 _escapeBKS = "\\b".ToCharArray();
35 _escapeFWD = "\\f".ToCharArray();
35 _escapeFWD = "\\f".ToCharArray();
36 _escapeCR = "\\r".ToCharArray();
36 _escapeCR = "\\r".ToCharArray();
37 _escapeNL = "\\n".ToCharArray();
37 _escapeNL = "\\n".ToCharArray();
38 _escapeTAB = "\\t".ToCharArray();
38 _escapeTAB = "\\t".ToCharArray();
39 _escapeBSLASH = "\\\\".ToCharArray();
39 _escapeBSLASH = "\\\\".ToCharArray();
40 _escapeQ = "\\\"".ToCharArray();
40 _escapeQ = "\\\"".ToCharArray();
41 }
41 }
42
42
43 public JSONWriter(TextWriter writer) {
43 public JSONWriter(TextWriter writer) {
44 Safe.ArgumentNotNull(writer, "writer");
44 Safe.ArgumentNotNull(writer, "writer");
45 m_writer = writer;
45 m_writer = writer;
46 }
46 }
47
47
48 public JSONWriter(TextWriter writer, bool indent) {
48 public JSONWriter(TextWriter writer, bool indent) {
49 Safe.ArgumentNotNull(writer, "writer");
49 Safe.ArgumentNotNull(writer, "writer");
50
50
51 m_writer = writer;
51 m_writer = writer;
52 m_indent = indent;
52 m_indent = indent;
53 }
53 }
54
54
55 void WriteIndent() {
55 void WriteIndent() {
56 if (m_indent) {
56 if (m_indent) {
57 var indent = new char[m_contextStack.Count * m_indentSize + 1];
57 var indent = new char[m_contextStack.Count * m_indentSize + 1];
58 indent[0] = '\n';
58 indent[0] = '\n';
59 for (int i = 1; i < indent.Length; i++)
59 for (int i = 1; i < indent.Length; i++)
60 indent[i] = ' ';
60 indent[i] = ' ';
61 m_writer.Write(new String(indent));
61 m_writer.Write(new String(indent));
62 } else {
62 } else {
63 m_writer.Write(' ');
63 m_writer.Write(' ');
64 }
64 }
65 }
65 }
66
66
67 void WriteMemberName(string name) {
67 void WriteMemberName(string name) {
68 Safe.ArgumentNotEmpty(name, "name");
68 Safe.ArgumentNotEmpty(name, "name");
69 if (m_context.element != JSONElementContext.Object)
69 if (m_context.element != JSONElementContext.Object)
70 OperationNotApplicable("WriteMember");
70 OperationNotApplicable("WriteMember");
71 if (m_context.needComma)
71 if (m_context.needComma)
72 m_writer.Write(",");
72 m_writer.Write(",");
73
73
74 WriteIndent();
74 WriteIndent();
75 m_context.needComma = true;
75 m_context.needComma = true;
76 Write(name);
76 Write(name);
77 m_writer.Write(" : ");
77 m_writer.Write(" : ");
78 }
78 }
79
79
80 public void WriteValue(string name, string value) {
80 public void WriteValue(string name, string value) {
81 WriteMemberName(name);
81 WriteMemberName(name);
82 Write(value);
82 Write(value);
83 }
83 }
84
84
85 public void WriteValue(string name, bool value) {
85 public void WriteValue(string name, bool value) {
86 WriteMemberName(name);
86 WriteMemberName(name);
87 Write(value);
87 Write(value);
88 }
88 }
89
89
90 public void WriteValue(string name, double value) {
90 public void WriteValue(string name, double value) {
91 WriteMemberName(name);
91 WriteMemberName(name);
92 Write(value);
92 Write(value);
93 }
93 }
94
94
95 public void WriteValue(string value) {
95 public void WriteValue(string value) {
96 if (m_context.element == JSONElementContext.Array) {
96 if (m_context.element == JSONElementContext.Array) {
97
97
98 if (m_context.needComma)
98 if (m_context.needComma)
99 m_writer.Write(",");
99 m_writer.Write(",");
100 WriteIndent();
100 WriteIndent();
101 m_context.needComma = true;
101 m_context.needComma = true;
102
102
103 Write(value);
103 Write(value);
104 } else if (m_context.element == JSONElementContext.None) {
104 } else if (m_context.element == JSONElementContext.None) {
105 Write(value);
105 Write(value);
106 m_context.element = JSONElementContext.Closed;
106 m_context.element = JSONElementContext.Closed;
107 } else {
107 } else {
108 OperationNotApplicable("WriteValue");
108 OperationNotApplicable("WriteValue");
109 }
109 }
110 }
110 }
111
111
112 public void WriteValue(bool value) {
112 public void WriteValue(bool value) {
113 if (m_context.element == JSONElementContext.Array) {
113 if (m_context.element == JSONElementContext.Array) {
114
114
115 if (m_context.needComma)
115 if (m_context.needComma)
116 m_writer.Write(",");
116 m_writer.Write(",");
117 WriteIndent();
117 WriteIndent();
118 m_context.needComma = true;
118 m_context.needComma = true;
119
119
120 Write(value);
120 Write(value);
121 } else if (m_context.element == JSONElementContext.None) {
121 } else if (m_context.element == JSONElementContext.None) {
122 Write(value);
122 Write(value);
123 m_context.element = JSONElementContext.Closed;
123 m_context.element = JSONElementContext.Closed;
124 } else {
124 } else {
125 OperationNotApplicable("WriteValue");
125 OperationNotApplicable("WriteValue");
126 }
126 }
127 }
127 }
128
128
129 public void WriteValue(double value) {
129 public void WriteValue(double value) {
130 if (m_context.element == JSONElementContext.Array) {
130 if (m_context.element == JSONElementContext.Array) {
131
131
132 if (m_context.needComma)
132 if (m_context.needComma)
133 m_writer.Write(",");
133 m_writer.Write(",");
134 WriteIndent();
134 WriteIndent();
135 m_context.needComma = true;
135 m_context.needComma = true;
136
136
137 Write(value);
137 Write(value);
138 } else if (m_context.element == JSONElementContext.None) {
138 } else if (m_context.element == JSONElementContext.None) {
139 Write(value);
139 Write(value);
140 m_context.element = JSONElementContext.Closed;
140 m_context.element = JSONElementContext.Closed;
141 } else {
141 } else {
142 OperationNotApplicable("WriteValue");
142 OperationNotApplicable("WriteValue");
143 }
143 }
144 }
144 }
145
145
146 public void BeginObject() {
146 public void BeginObject() {
147 if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array)
147 if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array)
148 OperationNotApplicable("BeginObject");
148 OperationNotApplicable("BeginObject");
149 if (m_context.needComma)
149 if (m_context.needComma)
150 m_writer.Write(",");
150 m_writer.Write(",");
151
151
152 WriteIndent();
152 WriteIndent();
153
153
154 m_context.needComma = true;
154 m_context.needComma = true;
155
155
156 m_contextStack.Push(m_context);
156 m_contextStack.Push(m_context);
157
157
158 m_context = new Context { element = JSONElementContext.Object, needComma = false };
158 m_context = new Context { element = JSONElementContext.Object, needComma = false };
159 m_writer.Write("{");
159 m_writer.Write("{");
160 }
160 }
161
161
162 public void BeginObject(string name) {
162 public void BeginObject(string name) {
163 WriteMemberName(name);
163 WriteMemberName(name);
164
164
165 m_contextStack.Push(m_context);
165 m_contextStack.Push(m_context);
166
166
167 m_context = new Context { element = JSONElementContext.Object, needComma = false };
167 m_context = new Context { element = JSONElementContext.Object, needComma = false };
168 m_writer.Write("{");
168 m_writer.Write("{");
169 }
169 }
170
170
171 public void EndObject() {
171 public void EndObject() {
172 if (m_context.element != JSONElementContext.Object)
172 if (m_context.element != JSONElementContext.Object)
173 OperationNotApplicable("EndObject");
173 OperationNotApplicable("EndObject");
174
174
175 m_context = m_contextStack.Pop();
175 m_context = m_contextStack.Pop();
176 if (m_contextStack.Count == 0)
176 if (m_contextStack.Count == 0)
177 m_context.element = JSONElementContext.Closed;
177 m_context.element = JSONElementContext.Closed;
178 WriteIndent();
178 WriteIndent();
179 m_writer.Write("}");
179 m_writer.Write("}");
180 }
180 }
181
181
182 public void BeginArray() {
182 public void BeginArray() {
183 if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array)
183 if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array)
184 throw new InvalidOperationException();
184 throw new InvalidOperationException();
185 if (m_context.needComma) {
185 if (m_context.needComma) {
186 m_writer.Write(",");
186 m_writer.Write(",");
187
187
188 }
188 }
189 m_context.needComma = true;
189 m_context.needComma = true;
190
190
191 WriteIndent();
191 WriteIndent();
192 m_contextStack.Push(m_context);
192 m_contextStack.Push(m_context);
193 m_context = new Context { element = JSONElementContext.Array, needComma = false };
193 m_context = new Context { element = JSONElementContext.Array, needComma = false };
194 m_writer.Write("[");
194 m_writer.Write("[");
195 }
195 }
196
196
197 public void BeginArray(string name) {
197 public void BeginArray(string name) {
198 WriteMemberName(name);
198 WriteMemberName(name);
199
199
200 m_contextStack.Push(m_context);
200 m_contextStack.Push(m_context);
201
201
202 m_context = new Context { element = JSONElementContext.Array, needComma = false };
202 m_context = new Context { element = JSONElementContext.Array, needComma = false };
203 m_writer.Write("[");
203 m_writer.Write("[");
204 }
204 }
205
205
206 public void EndArray() {
206 public void EndArray() {
207 if (m_context.element != JSONElementContext.Array)
207 if (m_context.element != JSONElementContext.Array)
208 OperationNotApplicable("EndArray");
208 OperationNotApplicable("EndArray");
209
209
210 m_context = m_contextStack.Pop();
210 m_context = m_contextStack.Pop();
211 if (m_contextStack.Count == 0)
211 if (m_contextStack.Count == 0)
212 m_context.element = JSONElementContext.Closed;
212 m_context.element = JSONElementContext.Closed;
213 WriteIndent();
213 WriteIndent();
214 m_writer.Write("]");
214 m_writer.Write("]");
215 }
215 }
216
216
217 void Write(bool value) {
217 void Write(bool value) {
218 m_writer.Write(value ? "true" : "false");
218 m_writer.Write(value ? "true" : "false");
219 }
219 }
220
220
221 void FlushBuffer() {
221 void FlushBuffer() {
222 if (m_bufferPos > 0) {
222 if (m_bufferPos > 0) {
223 m_writer.Write(m_buffer, 0, m_bufferPos);
223 m_writer.Write(m_buffer, 0, m_bufferPos);
224 m_bufferPos = 0;
224 m_bufferPos = 0;
225 }
225 }
226 }
226 }
227
227
228 void Write(string value) {
228 void Write(string value) {
229 if (value == null) {
229 if (value == null) {
230 m_writer.Write("null");
230 m_writer.Write("null");
231 return;
231 return;
232 }
232 }
233
233
234 Debug.Assert(m_bufferPos == 0);
234 Debug.Assert(m_bufferPos == 0);
235
235
236 var chars = value.ToCharArray();
236 var chars = value.ToCharArray();
237 m_buffer[m_bufferPos++] = '"';
237 m_buffer[m_bufferPos++] = '"';
238
238
239 // Analysis disable once ForCanBeConvertedToForeach
239 // Analysis disable once ForCanBeConvertedToForeach
240 for (int i = 0; i < chars.Length; i++) {
240 for (int i = 0; i < chars.Length; i++) {
241 var ch = chars[i];
241 var ch = chars[i];
242
242
243 char[] escapeSeq;
243 char[] escapeSeq;
244
244
245 switch (ch) {
245 switch (ch) {
246 case '\b':
246 case '\b':
247 escapeSeq = _escapeBKS;
247 escapeSeq = _escapeBKS;
248 break;
248 break;
249 case '\f':
249 case '\f':
250 escapeSeq = _escapeFWD;
250 escapeSeq = _escapeFWD;
251 break;
251 break;
252 case '\r':
252 case '\r':
253 escapeSeq = _escapeCR;
253 escapeSeq = _escapeCR;
254 break;
254 break;
255 case '\n':
255 case '\n':
256 escapeSeq = _escapeNL;
256 escapeSeq = _escapeNL;
257 break;
257 break;
258 case '\t':
258 case '\t':
259 escapeSeq = _escapeTAB;
259 escapeSeq = _escapeTAB;
260 break;
260 break;
261 case '\\':
261 case '\\':
262 escapeSeq = _escapeBSLASH;
262 escapeSeq = _escapeBSLASH;
263 break;
263 break;
264 case '"':
264 case '"':
265 escapeSeq = _escapeQ;
265 escapeSeq = _escapeQ;
266 break;
266 break;
267 default:
267 default:
268 if (ch < 0x20) {
268 if (ch < 0x20) {
269 if (m_bufferPos + 6 > BUFFER_SIZE)
269 if (m_bufferPos + 6 > BUFFER_SIZE)
270 FlushBuffer();
270 FlushBuffer();
271
271
272 m_buffer[m_bufferPos++] = '\\';
272 m_buffer[m_bufferPos++] = '\\';
273 m_buffer[m_bufferPos++] = 'u';
273 m_buffer[m_bufferPos++] = 'u';
274 m_buffer[m_bufferPos++] = '0';
274 m_buffer[m_bufferPos++] = '0';
275 m_buffer[m_bufferPos++] = '0';
275 m_buffer[m_bufferPos++] = '0';
276 m_buffer[m_bufferPos++] = _hex[ch >> 4 & 0xf];
276 m_buffer[m_bufferPos++] = _hex[ch >> 4 & 0xf];
277 m_buffer[m_bufferPos++] = _hex[ch & 0xf];
277 m_buffer[m_bufferPos++] = _hex[ch & 0xf];
278
278
279 } else {
279 } else {
280 if (m_bufferPos >= BUFFER_SIZE)
280 if (m_bufferPos >= BUFFER_SIZE)
281 FlushBuffer();
281 FlushBuffer();
282 m_buffer[m_bufferPos++] = ch;
282 m_buffer[m_bufferPos++] = ch;
283 }
283 }
284 continue;
284 continue;
285 }
285 }
286
286
287 if (m_bufferPos + escapeSeq.Length > BUFFER_SIZE)
287 if (m_bufferPos + escapeSeq.Length > BUFFER_SIZE)
288 FlushBuffer();
288 FlushBuffer();
289
289
290 Array.Copy(escapeSeq, 0, m_buffer, m_bufferPos, escapeSeq.Length);
290 Array.Copy(escapeSeq, 0, m_buffer, m_bufferPos, escapeSeq.Length);
291 m_bufferPos += escapeSeq.Length;
291 m_bufferPos += escapeSeq.Length;
292
292
293 }
293 }
294
294
295 if (m_bufferPos >= BUFFER_SIZE)
295 if (m_bufferPos >= BUFFER_SIZE)
296 FlushBuffer();
296 FlushBuffer();
297
297
298 m_buffer[m_bufferPos++] = '"';
298 m_buffer[m_bufferPos++] = '"';
299
299
300 FlushBuffer();
300 FlushBuffer();
301 }
301 }
302
302
303 void Write(double value) {
303 void Write(double value) {
304 if (double.IsNaN(value))
304 if (double.IsNaN(value))
305 Write("NaN");
305 Write("NaN");
306 else if (double.IsNegativeInfinity(value))
306 else if (double.IsNegativeInfinity(value))
307 Write("-Infinity");
307 Write("-Infinity");
308 else if (double.IsPositiveInfinity(value))
308 else if (double.IsPositiveInfinity(value))
309 Write("Infinity");
309 Write("Infinity");
310 else
310 else
311 m_writer.Write(value.ToString(CultureInfo.InvariantCulture));
311 m_writer.Write(value.ToString(CultureInfo.InvariantCulture));
312 }
312 }
313
313
314 void OperationNotApplicable(string opName) {
314 void OperationNotApplicable(string opName) {
315 throw new InvalidOperationException(String.Format("The operation '{0}' isn't applicable in the context of '{1}'", opName, m_context.element ));
315 throw new InvalidOperationException(String.Format("The operation '{0}' isn't applicable in the context of '{1}'", opName, m_context.element ));
316 }
316 }
317
317
318 }
318 }
319 }
319 }
@@ -1,343 +1,335
1 using Implab;
1 using Implab;
2 using Implab.Parsing;
3 using System;
2 using System;
4 using System.Collections.Generic;
3 using System.Collections.Generic;
5 using System.Globalization;
4 using System.Globalization;
6 using System.IO;
5 using System.IO;
7 using System.Linq;
8 using System.Text;
9 using System.Threading.Tasks;
10 using System.Xml;
6 using System.Xml;
11
7
12 namespace Implab.JSON {
8 namespace Implab.Formats.JSON {
13 public class JSONXmlReader : XmlReader {
9 public class JSONXmlReader : XmlReader {
14
10
15 enum ValueContext {
11 enum ValueContext {
16 Undefined,
12 Undefined,
17 ElementStart,
13 ElementStart,
18 ElementValue,
14 ElementValue,
19 ElementEnd,
15 ElementEnd,
20 ElementEmpty
16 ElementEmpty
21 }
17 }
22
18
23 struct LocalNameContext {
19 struct LocalNameContext {
24 public string localName;
20 public string localName;
25 public bool isArray;
21 public bool isArray;
26 }
22 }
27
23
28 JSONParser m_parser;
24 JSONParser m_parser;
29 ValueContext m_valueContext;
25 ValueContext m_valueContext;
30 ReadState m_state = ReadState.Initial;
26 ReadState m_state = ReadState.Initial;
31 Stack<LocalNameContext> m_localNameStack = new Stack<LocalNameContext>();
27 Stack<LocalNameContext> m_localNameStack = new Stack<LocalNameContext>();
32 LocalNameContext m_localName;
28 LocalNameContext m_localName;
33 int m_depthCorrection = 0;
29 int m_depthCorrection;
34
30
35 readonly string m_rootName;
31 readonly string m_rootName;
36 readonly string m_prefix;
32 readonly string m_prefix;
37 readonly string m_namespaceUri;
33 readonly string m_namespaceUri;
38 readonly bool m_flattenArrays;
34 readonly bool m_flattenArrays;
39 readonly string m_arrayItemName;
35 readonly string m_arrayItemName;
40 readonly XmlNameTable m_nameTable;
36 readonly XmlNameTable m_nameTable;
41
37
42 JSONXmlReader(JSONParser parser, JSONXmlReaderOptions options) {
38 JSONXmlReader(JSONParser parser, JSONXmlReaderOptions options) {
43 m_parser = parser;
39 m_parser = parser;
44
40
45 if (options != null) {
41 if (options != null) {
46 m_prefix = options.NodesPrefix ?? String.Empty;
42 m_prefix = options.NodesPrefix ?? String.Empty;
47 m_namespaceUri = options.NamespaceURI ?? String.Empty;
43 m_namespaceUri = options.NamespaceURI ?? String.Empty;
48 m_rootName = options.RootName ?? "json";
44 m_rootName = options.RootName ?? "json";
49 m_flattenArrays = options.FlattenArrays;
45 m_flattenArrays = options.FlattenArrays;
50 m_arrayItemName = options.ArrayItemName ?? "item";
46 m_arrayItemName = options.ArrayItemName ?? "item";
51 m_nameTable = options.NameTable ?? new NameTable();
47 m_nameTable = options.NameTable ?? new NameTable();
52 } else {
48 } else {
53 m_prefix = String.Empty;
49 m_prefix = String.Empty;
54 m_namespaceUri = String.Empty;
50 m_namespaceUri = String.Empty;
55 m_rootName = "json";
51 m_rootName = "json";
56 m_flattenArrays = false;
52 m_flattenArrays = false;
57 m_arrayItemName = "item";
53 m_arrayItemName = "item";
58 m_nameTable = new NameTable();
54 m_nameTable = new NameTable();
59 }
55 }
60 }
56 }
61
57
62 /// <summary>
58 /// <summary>
63 /// Always 0, JSON doesn't support attributes
59 /// Always 0, JSON doesn't support attributes
64 /// </summary>
60 /// </summary>
65 public override int AttributeCount {
61 public override int AttributeCount {
66 get { return 0; }
62 get { return 0; }
67 }
63 }
68
64
69 public override string BaseURI {
65 public override string BaseURI {
70 get { return String.Empty; }
66 get { return String.Empty; }
71 }
67 }
72
68
73 public override int Depth {
69 public override int Depth {
74 get {
70 get {
75 return m_localNameStack.Count + m_depthCorrection;
71 return m_localNameStack.Count + m_depthCorrection;
76 }
72 }
77 }
73 }
78
74
79 public override bool EOF {
75 public override bool EOF {
80 get { return m_parser.EOF; }
76 get { return m_parser.EOF; }
81 }
77 }
82
78
83 /// <summary>
79 /// <summary>
84 /// Always throws an exception
80 /// Always throws an exception
85 /// </summary>
81 /// </summary>
86 /// <param name="i"></param>
82 /// <param name="i"></param>
87 /// <returns></returns>
83 /// <returns></returns>
88 public override string GetAttribute(int i) {
84 public override string GetAttribute(int i) {
89 throw new ArgumentOutOfRangeException();
85 throw new ArgumentOutOfRangeException();
90 }
86 }
91
87
92 /// <summary>
88 /// <summary>
93 /// Always returns empty string
89 /// Always returns empty string
94 /// </summary>
90 /// </summary>
95 /// <param name="name"></param>
91 /// <param name="name"></param>
96 /// <param name="namespaceURI"></param>
92 /// <param name="namespaceURI"></param>
97 /// <returns></returns>
93 /// <returns></returns>
98 public override string GetAttribute(string name, string namespaceURI) {
94 public override string GetAttribute(string name, string namespaceURI) {
99 return String.Empty;
95 return String.Empty;
100 }
96 }
101
97
102 /// <summary>
98 /// <summary>
103 /// Always returns empty string
99 /// Always returns empty string
104 /// </summary>
100 /// </summary>
105 /// <param name="name"></param>
101 /// <param name="name"></param>
106 /// <returns></returns>
102 /// <returns></returns>
107 public override string GetAttribute(string name) {
103 public override string GetAttribute(string name) {
108 return String.Empty;
104 return String.Empty;
109 }
105 }
110
106
111 public override bool IsEmptyElement {
107 public override bool IsEmptyElement {
112 get { return m_parser.ElementType == JSONElementType.Value && m_valueContext == ValueContext.ElementEmpty; }
108 get { return m_parser.ElementType == JSONElementType.Value && m_valueContext == ValueContext.ElementEmpty; }
113 }
109 }
114
110
115 public override string LocalName {
111 public override string LocalName {
116 get { return m_localName.localName; }
112 get { return m_localName.localName; }
117 }
113 }
118
114
119 public override string LookupNamespace(string prefix) {
115 public override string LookupNamespace(string prefix) {
120 if (String.IsNullOrEmpty(prefix) || prefix == m_prefix)
116 if (String.IsNullOrEmpty(prefix) || prefix == m_prefix)
121 return m_namespaceUri;
117 return m_namespaceUri;
122 else
118
123 return String.Empty;
119 return String.Empty;
124 }
120 }
125
121
126 public override bool MoveToAttribute(string name, string ns) {
122 public override bool MoveToAttribute(string name, string ns) {
127 return false;
123 return false;
128 }
124 }
129
125
130 public override bool MoveToAttribute(string name) {
126 public override bool MoveToAttribute(string name) {
131 return false;
127 return false;
132 }
128 }
133
129
134 public override bool MoveToElement() {
130 public override bool MoveToElement() {
135 return false;
131 return false;
136 }
132 }
137
133
138 public override bool MoveToFirstAttribute() {
134 public override bool MoveToFirstAttribute() {
139 return false;
135 return false;
140 }
136 }
141
137
142 public override bool MoveToNextAttribute() {
138 public override bool MoveToNextAttribute() {
143 return false;
139 return false;
144 }
140 }
145
141
146 public override XmlNameTable NameTable {
142 public override XmlNameTable NameTable {
147 get { return m_nameTable; }
143 get { return m_nameTable; }
148 }
144 }
149
145
150 public override string NamespaceURI {
146 public override string NamespaceURI {
151 get { return m_namespaceUri; }
147 get { return m_namespaceUri; }
152 }
148 }
153
149
154 public override XmlNodeType NodeType {
150 public override XmlNodeType NodeType {
155 get {
151 get {
156 switch (m_parser.ElementType) {
152 switch (m_parser.ElementType) {
157 case JSONElementType.BeginObject:
153 case JSONElementType.BeginObject:
158 case JSONElementType.BeginArray:
154 case JSONElementType.BeginArray:
159 return XmlNodeType.Element;
155 return XmlNodeType.Element;
160 case JSONElementType.EndObject:
156 case JSONElementType.EndObject:
161 case JSONElementType.EndArray:
157 case JSONElementType.EndArray:
162 return XmlNodeType.EndElement;
158 return XmlNodeType.EndElement;
163 case JSONElementType.Value:
159 case JSONElementType.Value:
164 switch (m_valueContext) {
160 switch (m_valueContext) {
165 case ValueContext.ElementStart:
161 case ValueContext.ElementStart:
166 case ValueContext.ElementEmpty:
162 case ValueContext.ElementEmpty:
167 return XmlNodeType.Element;
163 return XmlNodeType.Element;
168 case ValueContext.ElementValue:
164 case ValueContext.ElementValue:
169 return XmlNodeType.Text;
165 return XmlNodeType.Text;
170 case ValueContext.ElementEnd:
166 case ValueContext.ElementEnd:
171 return XmlNodeType.EndElement;
167 return XmlNodeType.EndElement;
172 default:
168 default:
173 throw new InvalidOperationException();
169 throw new InvalidOperationException();
174 }
170 }
175 default:
171 default:
176 throw new InvalidOperationException();
172 throw new InvalidOperationException();
177 }
173 }
178 }
174 }
179 }
175 }
180
176
181 public override string Prefix {
177 public override string Prefix {
182 get { return m_prefix; }
178 get { return m_prefix; }
183 }
179 }
184
180
185 public override bool Read() {
181 public override bool Read() {
186 if (m_state != System.Xml.ReadState.Interactive && m_state != System.Xml.ReadState.Initial)
182 if (m_state != ReadState.Interactive && m_state != ReadState.Initial)
187 return false;
183 return false;
188
184
189 if (m_state == ReadState.Initial)
185 if (m_state == ReadState.Initial)
190 m_state = System.Xml.ReadState.Interactive;
186 m_state = ReadState.Interactive;
191
187
192 try {
188 try {
193 switch (m_parser.ElementType) {
189 switch (m_parser.ElementType) {
194 case JSONElementType.Value:
190 case JSONElementType.Value:
195 switch (m_valueContext) {
191 switch (m_valueContext) {
196 case ValueContext.ElementStart:
192 case ValueContext.ElementStart:
197 SetLocalName(String.Empty);
193 SetLocalName(String.Empty);
198 m_valueContext = ValueContext.ElementValue;
194 m_valueContext = ValueContext.ElementValue;
199 return true;
195 return true;
200 case ValueContext.ElementValue:
196 case ValueContext.ElementValue:
201 RestoreLocalName();
197 RestoreLocalName();
202 m_valueContext = ValueContext.ElementEnd;
198 m_valueContext = ValueContext.ElementEnd;
203 return true;
199 return true;
204 case ValueContext.ElementEmpty:
200 case ValueContext.ElementEmpty:
205 case ValueContext.ElementEnd:
201 case ValueContext.ElementEnd:
206 RestoreLocalName();
202 RestoreLocalName();
207 break;
203 break;
208 }
204 }
209 break;
205 break;
210 case JSONElementType.EndArray:
206 case JSONElementType.EndArray:
211 case JSONElementType.EndObject:
207 case JSONElementType.EndObject:
212 RestoreLocalName();
208 RestoreLocalName();
213 break;
209 break;
214 }
210 }
215 string itemName = m_parser.ElementType == JSONElementType.None ? m_rootName : m_flattenArrays ? m_localName.localName : m_arrayItemName;
211 string itemName = m_parser.ElementType == JSONElementType.None ? m_rootName : m_flattenArrays ? m_localName.localName : m_arrayItemName;
216 while (m_parser.Read()) {
212 while (m_parser.Read()) {
217 if (!String.IsNullOrEmpty(m_parser.ElementName))
213 if (!String.IsNullOrEmpty(m_parser.ElementName))
218 itemName = m_parser.ElementName;
214 itemName = m_parser.ElementName;
219
215
220 switch (m_parser.ElementType) {
216 switch (m_parser.ElementType) {
221 case JSONElementType.BeginArray:
217 case JSONElementType.BeginArray:
222 if (m_flattenArrays && !m_localName.isArray) {
218 if (m_flattenArrays && !m_localName.isArray) {
223 m_depthCorrection--;
219 m_depthCorrection--;
224 SetLocalName(itemName, true);
220 SetLocalName(itemName, true);
225 continue;
221 continue;
226 } else {
227 SetLocalName(itemName, true);
228 }
222 }
223 SetLocalName(itemName, true);
229 break;
224 break;
230 case JSONElementType.BeginObject:
225 case JSONElementType.BeginObject:
231 SetLocalName(itemName);
226 SetLocalName(itemName);
232 break;
227 break;
233 case JSONElementType.EndArray:
228 case JSONElementType.EndArray:
234 if (m_flattenArrays && !m_localNameStack.Peek().isArray) {
229 if (m_flattenArrays && !m_localNameStack.Peek().isArray) {
235 RestoreLocalName();
230 RestoreLocalName();
236 m_depthCorrection++;
231 m_depthCorrection++;
237 continue;
232 continue;
238 }
233 }
239 break;
234 break;
240 case JSONElementType.EndObject:
235 case JSONElementType.EndObject:
241 break;
236 break;
242 case JSONElementType.Value:
237 case JSONElementType.Value:
243 SetLocalName(itemName);
238 SetLocalName(itemName);
244 m_valueContext = m_parser.ElementValue == null ? ValueContext.ElementEmpty : ValueContext.ElementStart;
239 m_valueContext = m_parser.ElementValue == null ? ValueContext.ElementEmpty : ValueContext.ElementStart;
245 break;
240 break;
246 default:
247 break;
248 }
241 }
249 return true;
242 return true;
250 }
243 }
251
244
252 m_state = System.Xml.ReadState.EndOfFile;
245 m_state = ReadState.EndOfFile;
253 return false;
246 return false;
254 } catch {
247 } catch {
255 m_state = System.Xml.ReadState.Error;
248 m_state = ReadState.Error;
256 throw;
249 throw;
257 }
250 }
258 }
251 }
259
252
260 public override bool ReadAttributeValue() {
253 public override bool ReadAttributeValue() {
261 return false;
254 return false;
262 }
255 }
263
256
264 public override ReadState ReadState {
257 public override ReadState ReadState {
265 get { return m_state; }
258 get { return m_state; }
266 }
259 }
267
260
268 public override void ResolveEntity() {
261 public override void ResolveEntity() {
269 // do nothing
262 // do nothing
270 }
263 }
271
264
272 public override string Value {
265 public override string Value {
273 get {
266 get {
274 if (m_parser.ElementValue == null)
267 if (m_parser.ElementValue == null)
275 return String.Empty;
268 return String.Empty;
276 if (Convert.GetTypeCode(m_parser.ElementValue) == TypeCode.Double)
269 if (Convert.GetTypeCode(m_parser.ElementValue) == TypeCode.Double)
277 return ((double)m_parser.ElementValue).ToString(CultureInfo.InvariantCulture);
270 return ((double)m_parser.ElementValue).ToString(CultureInfo.InvariantCulture);
278 else
271 return m_parser.ElementValue.ToString();
279 return m_parser.ElementValue.ToString();
280 }
272 }
281 }
273 }
282
274
283 void SetLocalName(string name) {
275 void SetLocalName(string name) {
284 m_localNameStack.Push(m_localName);
276 m_localNameStack.Push(m_localName);
285 m_localName.localName = name;
277 m_localName.localName = name;
286 m_localName.isArray = false;
278 m_localName.isArray = false;
287 }
279 }
288
280
289 void SetLocalName(string name, bool isArray) {
281 void SetLocalName(string name, bool isArray) {
290 m_localNameStack.Push(m_localName);
282 m_localNameStack.Push(m_localName);
291 m_localName.localName = name;
283 m_localName.localName = name;
292 m_localName.isArray = isArray;
284 m_localName.isArray = isArray;
293 }
285 }
294
286
295 void RestoreLocalName() {
287 void RestoreLocalName() {
296 m_localName = m_localNameStack.Pop();
288 m_localName = m_localNameStack.Pop();
297 }
289 }
298
290
299 public override void Close() {
291 public override void Close() {
300
292
301 }
293 }
302
294
303 protected override void Dispose(bool disposing) {
295 protected override void Dispose(bool disposing) {
304 #if MONO
296 #if MONO
305 disposing = true;
297 disposing = true;
306 #endif
298 #endif
307 if (disposing) {
299 if (disposing) {
308 m_parser.Dispose();
300 m_parser.Dispose();
309 }
301 }
310 base.Dispose(disposing);
302 base.Dispose(disposing);
311 }
303 }
312
304
313 public static JSONXmlReader Create(string file, JSONXmlReaderOptions options) {
305 public static JSONXmlReader Create(string file, JSONXmlReaderOptions options) {
314 return Create(File.OpenText(file), options);
306 return Create(File.OpenText(file), options);
315 }
307 }
316
308
317 /// <summary>
309 /// <summary>
318 /// Creates the XmlReader for the specified text stream with JSON data.
310 /// Creates the XmlReader for the specified text stream with JSON data.
319 /// </summary>
311 /// </summary>
320 /// <param name="reader">Text reader.</param>
312 /// <param name="reader">Text reader.</param>
321 /// <param name="options">Options.</param>
313 /// <param name="options">Options.</param>
322 /// <remarks>
314 /// <remarks>
323 /// The reader will be disposed when the XmlReader is disposed.
315 /// The reader will be disposed when the XmlReader is disposed.
324 /// </remarks>
316 /// </remarks>
325 public static JSONXmlReader Create(TextReader reader, JSONXmlReaderOptions options) {
317 public static JSONXmlReader Create(TextReader reader, JSONXmlReaderOptions options) {
326 return new JSONXmlReader(new JSONParser(reader, true), options);
318 return new JSONXmlReader(new JSONParser(reader), options);
327 }
319 }
328
320
329 /// <summary>
321 /// <summary>
330 /// Creates the XmlReader for the specified stream with JSON data.
322 /// Creates the XmlReader for the specified stream with JSON data.
331 /// </summary>
323 /// </summary>
332 /// <param name="stream">Stream.</param>
324 /// <param name="stream">Stream.</param>
333 /// <param name="options">Options.</param>
325 /// <param name="options">Options.</param>
334 /// <remarks>
326 /// <remarks>
335 /// The stream will be disposed when the XmlReader is disposed.
327 /// The stream will be disposed when the XmlReader is disposed.
336 /// </remarks>
328 /// </remarks>
337 public static JSONXmlReader Create(Stream stream, JSONXmlReaderOptions options) {
329 public static JSONXmlReader Create(Stream stream, JSONXmlReaderOptions options) {
338 Safe.ArgumentNotNull(stream, "stream");
330 Safe.ArgumentNotNull(stream, "stream");
339 // HACK don't dispose StreaReader to keep stream opened
331 // HACK don't dispose StreaReader to keep stream opened
340 return Create(new StreamReader(stream), options);
332 return Create(new StreamReader(stream), options);
341 }
333 }
342 }
334 }
343 }
335 }
@@ -1,65 +1,62
1 using System;
1
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Xml;
2 using System.Xml;
6
3
7 namespace Implab.JSON {
4 namespace Implab.Formats.JSON {
8 /// <summary>
5 /// <summary>
9 /// Набор необязательных параметров для <see cref="JSONXmlReader"/>, позволяющий управлять процессом
6 /// Набор необязательных параметров для <see cref="JSONXmlReader"/>, позволяющий управлять процессом
10 /// интерпретации <c>JSON</c> документа.
7 /// интерпретации <c>JSON</c> документа.
11 /// </summary>
8 /// </summary>
12 public class JSONXmlReaderOptions {
9 public class JSONXmlReaderOptions {
13 /// <summary>
10 /// <summary>
14 /// Пространство имен в котором будут располагаться читаемые элементы документа
11 /// Пространство имен в котором будут располагаться читаемые элементы документа
15 /// </summary>
12 /// </summary>
16 public string NamespaceURI {
13 public string NamespaceURI {
17 get;
14 get;
18 set;
15 set;
19 }
16 }
20
17
21 /// <summary>
18 /// <summary>
22 /// Интерпретировать массивы как множественные элементы (убирает один уровень вложенности), иначе массив
19 /// Интерпретировать массивы как множественные элементы (убирает один уровень вложенности), иначе массив
23 /// представляется в виде узла, дочерними элементами которого являются элементы массива, имена дочерних элементов
20 /// представляется в виде узла, дочерними элементами которого являются элементы массива, имена дочерних элементов
24 /// определяются свойством <see cref="ArrayItemName"/>. По умолчанию <c>false</c>.
21 /// определяются свойством <see cref="ArrayItemName"/>. По умолчанию <c>false</c>.
25 /// </summary>
22 /// </summary>
26 public bool FlattenArrays {
23 public bool FlattenArrays {
27 get;
24 get;
28 set;
25 set;
29 }
26 }
30
27
31 /// <summary>
28 /// <summary>
32 /// Префикс, для узлов документа
29 /// Префикс, для узлов документа
33 /// </summary>
30 /// </summary>
34 public string NodesPrefix {
31 public string NodesPrefix {
35 get;
32 get;
36 set;
33 set;
37 }
34 }
38
35
39 /// <summary>
36 /// <summary>
40 /// Имя корневого элемента в xml документе
37 /// Имя корневого элемента в xml документе
41 /// </summary>
38 /// </summary>
42 public string RootName {
39 public string RootName {
43 get;
40 get;
44 set;
41 set;
45 }
42 }
46
43
47 /// <summary>
44 /// <summary>
48 /// Имя элемента для массивов, если не включена опция <see cref="FlattenArrays"/>.
45 /// Имя элемента для массивов, если не включена опция <see cref="FlattenArrays"/>.
49 /// По умолчанию <c>item</c>.
46 /// По умолчанию <c>item</c>.
50 /// </summary>
47 /// </summary>
51 public string ArrayItemName {
48 public string ArrayItemName {
52 get;
49 get;
53 set;
50 set;
54 }
51 }
55
52
56 /// <summary>
53 /// <summary>
57 /// Таблица атомизированных строк для построения документа.
54 /// Таблица атомизированных строк для построения документа.
58 /// </summary>
55 /// </summary>
59 public XmlNameTable NameTable {
56 public XmlNameTable NameTable {
60 get;
57 get;
61 set;
58 set;
62 }
59 }
63
60
64 }
61 }
65 }
62 }
@@ -1,95 +1,52
1 using Implab;
1 using Implab;
2 using Implab.Formats;
2 using Implab.Formats;
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.Linq;
6 using System.Linq;
7 using System.Text;
7 using System.Text;
8 using System.Threading.Tasks;
8 using System.Threading.Tasks;
9
9
10 namespace Implab.Formats.JSON {
10 namespace Implab.Formats.JSON {
11 /// <summary>
11 /// <summary>
12 /// Класс для преобразования экранированной строки JSON
12 /// Класс для преобразования экранированной строки JSON
13 /// </summary>
13 /// </summary>
14 public class StringTranslator : TextScanner<JSONGrammar.TokenType> {
14 static class StringTranslator {
15 static readonly char[] _escMap;
15 static readonly char[] _escMap;
16 static readonly int[] _hexMap;
16 static readonly int[] _hexMap;
17
17
18 static StringTranslator() {
18 static StringTranslator() {
19 var chars = new char[] { 'b', 'f', 't', 'r', 'n', '\\', '/' };
19 var chars = new char[] { 'b', 'f', 't', 'r', 'n', '\\', '/' };
20 var vals = new char[] { '\b', '\f', '\t', '\r', '\n', '\\', '/' };
20 var vals = new char[] { '\b', '\f', '\t', '\r', '\n', '\\', '/' };
21
21
22 _escMap = new char[chars.Max() + 1];
22 _escMap = new char[chars.Max() + 1];
23
23
24 for (int i = 0; i < chars.Length; i++)
24 for (int i = 0; i < chars.Length; i++)
25 _escMap[chars[i]] = vals[i];
25 _escMap[chars[i]] = vals[i];
26
26
27 var hexs = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F' };
27 var hexs = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F' };
28 var ints = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 10, 11, 12, 13, 14, 15 };
28 var ints = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 10, 11, 12, 13, 14, 15 };
29
29
30 _hexMap = new int[hexs.Max() + 1];
30 _hexMap = new int[hexs.Max() + 1];
31
31
32 for (int i = 0; i < hexs.Length; i++)
32 for (int i = 0; i < hexs.Length; i++)
33 _hexMap[hexs[i]] = ints[i];
33 _hexMap[hexs[i]] = ints[i];
34
34
35 }
35 }
36
36
37 public StringTranslator() {
38 }
39
40 public string Translate(string data) {
41 Safe.ArgumentNotNull(data, "data");
42 return Translate(data.ToCharArray());
43 }
44
45 public string Translate(char[] data) {
46 Safe.ArgumentNotNull(data, "data");
47 return Translate(data, data.Length);
48 }
49
50 public string Translate(char[] data, int length) {
51 Safe.ArgumentNotNull(data, "data");
52 Safe.ArgumentInRange(length, 0, data.Length, "length");
53
54 var translated = new char[length];
55
56 Feed(data,length);
57
58 int pos = 0;
59
60 while (ReadTokenInternal()) {
61 switch ((JSONGrammar.TokenType)Tags[0]) {
62 case JSONGrammar.TokenType.UnescapedChar:
63 Array.Copy(m_buffer,m_tokenOffset,translated,pos,m_tokenLen);
64 pos += m_tokenLen;
65 break;
66 case JSONGrammar.TokenType.EscapedChar:
67 translated[pos] = _escMap[m_buffer[m_tokenOffset + 1]];
68 pos++;
69 break;
70 case JSONGrammar.TokenType.EscapedUnicode:
71 translated[pos] = TranslateHexUnicode(m_buffer,m_tokenOffset + 2);
72 pos++;
73 break;
74 }
75 }
76
77 return new String(translated, 0, pos);
78 }
79
80 internal static char TranslateEscapedChar(char symbol) {
37 internal static char TranslateEscapedChar(char symbol) {
81 return _escMap[symbol];
38 return _escMap[symbol];
82 }
39 }
83
40
84 internal static char TranslateHexUnicode(char[] symbols, int offset) {
41 internal static char TranslateHexUnicode(char[] symbols, int offset) {
85 Debug.Assert(symbols != null);
42 Debug.Assert(symbols != null);
86 Debug.Assert(symbols.Length - offset >= 4);
43 Debug.Assert(symbols.Length - offset >= 4);
87
44
88 int value = (_hexMap[symbols[offset]] << 12)
45 int value = (_hexMap[symbols[offset]] << 12)
89 | (_hexMap[symbols[offset + 1]] << 8)
46 | (_hexMap[symbols[offset + 1]] << 8)
90 | (_hexMap[symbols[offset + 2]] << 4)
47 | (_hexMap[symbols[offset + 2]] << 4)
91 | (_hexMap[symbols[offset + 3]]);
48 | (_hexMap[symbols[offset + 3]]);
92 return (char)value;
49 return (char)value;
93 }
50 }
94 }
51 }
95 }
52 }
@@ -1,150 +1,156
1 using System;
1 using System;
2 using Implab.Components;
2 using Implab.Components;
3 using System.Diagnostics;
3 using System.Diagnostics;
4 using Implab.Automaton;
4 using Implab.Automaton;
5 using System.Text;
5 using System.Text;
6
6
7 namespace Implab.Formats {
7 namespace Implab.Formats {
8 public abstract class TextScanner : Disposable {
8 public abstract class TextScanner : Disposable {
9 readonly int m_bufferMax;
9 readonly int m_bufferMax;
10 readonly int m_chunkSize;
10 readonly int m_chunkSize;
11
11
12 char[] m_buffer;
12 char[] m_buffer;
13 int m_bufferOffset;
13 int m_bufferOffset;
14 int m_bufferSize;
14 int m_bufferSize;
15 int m_tokenOffset;
15 int m_tokenOffset;
16 int m_tokenLength;
16 int m_tokenLength;
17
17
18 /// <summary>
18 /// <summary>
19 /// Initializes a new instance of the <see cref="Implab.Formats.TextScanner"/> class.
19 /// Initializes a new instance of the <see cref="Implab.Formats.TextScanner"/> class.
20 /// </summary>
20 /// </summary>
21 /// <param name="bufferMax">Buffer max.</param>
21 /// <param name="bufferMax">Buffer max.</param>
22 /// <param name="chunkSize">Chunk size.</param>
22 /// <param name="chunkSize">Chunk size.</param>
23 protected TextScanner(int bufferMax, int chunkSize) {
23 protected TextScanner(int bufferMax, int chunkSize) {
24 Debug.Assert(m_chunkSize <= m_bufferMax);
24 Debug.Assert(m_chunkSize <= m_bufferMax);
25
25
26 m_bufferMax = bufferMax;
26 m_bufferMax = bufferMax;
27 m_chunkSize = chunkSize;
27 m_chunkSize = chunkSize;
28 }
28 }
29
29
30 /// <summary>
30 /// <summary>
31 /// Initializes a new instance of the <see cref="Implab.Formats.TextScanner"/> class.
31 /// Initializes a new instance of the <see cref="Implab.Formats.TextScanner"/> class.
32 /// </summary>
32 /// </summary>
33 /// <param name="buffer">Buffer.</param>
33 /// <param name="buffer">Buffer.</param>
34 protected TextScanner(char[] buffer) {
34 protected TextScanner(char[] buffer) {
35 if (buffer != null) {
35 if (buffer != null) {
36 m_buffer = buffer;
36 m_buffer = buffer;
37 m_bufferSize = buffer.Length;
37 m_bufferSize = buffer.Length;
38 }
38 }
39 }
39 }
40
40
41 /// <summary>
41 /// <summary>
42 /// (hungry) Reads the next token.
42 /// (hungry) Reads the next token.
43 /// </summary>
43 /// </summary>
44 /// <returns><c>true</c>, if token internal was read, <c>false</c> if there is no more tokens in the stream.</returns>
44 /// <returns><c>true</c>, if token internal was read, <c>false</c> if there is no more tokens in the stream.</returns>
45 /// <param name="dfa">The transition map for the automaton</param>
45 /// <param name="dfa">The transition map for the automaton</param>
46 /// <param name="final">Final states of the automaton.</param>
46 /// <param name="final">Final states of the automaton.</param>
47 /// <param name="tags">Tags.</param>
47 /// <param name="tags">Tags.</param>
48 /// <param name="state">The initial state for the automaton.</param>
48 /// <param name="state">The initial state for the automaton.</param>
49 /// <param name="alphabet"></param>
49 /// <param name="alphabet"></param>
50 /// <param name = "tag"></param>
50 /// <param name = "tag"></param>
51 internal bool ReadToken<TTag>(int[,] dfa, bool[] final, TTag[][] tags, int state, int[] alphabet, out TTag[] tag) {
51 internal bool ReadToken<TTag>(int[,] dfa, bool[] final, TTag[][] tags, int state, int[] alphabet, out TTag[] tag) {
52 Safe.ArgumentNotNull();
53 m_tokenLength = 0;
52 m_tokenLength = 0;
53 tag = null;
54
54
55 var maxSymbol = alphabet.Length - 1;
55 var maxSymbol = alphabet.Length - 1;
56
56
57 do {
57 do {
58 // after the next chunk is read the offset in the buffer may change
58 // after the next chunk is read the offset in the buffer may change
59 int pos = m_bufferOffset + m_tokenLength;
59 int pos = m_bufferOffset + m_tokenLength;
60
60
61 while (pos < m_bufferSize) {
61 while (pos < m_bufferSize) {
62 var ch = m_buffer[pos];
62 var ch = m_buffer[pos];
63
63
64 state = dfa[state, ch > maxSymbol ? AutomatonConst.UNCLASSIFIED_INPUT : alphabet[ch]];
64 state = dfa[state, ch > maxSymbol ? AutomatonConst.UNCLASSIFIED_INPUT : alphabet[ch]];
65 if (state == AutomatonConst.UNREACHABLE_STATE)
65 if (state == AutomatonConst.UNREACHABLE_STATE)
66 break;
66 break;
67
67
68 pos++;
68 pos++;
69 }
69 }
70
70
71 m_tokenLength = pos - m_bufferOffset;
71 m_tokenLength = pos - m_bufferOffset;
72 } while (state != AutomatonConst.UNREACHABLE_STATE && Feed());
72 } while (state != AutomatonConst.UNREACHABLE_STATE && Feed());
73
73
74 m_tokenOffset = m_bufferOffset;
74 m_tokenOffset = m_bufferOffset;
75 m_bufferOffset += m_tokenLength;
75 m_bufferOffset += m_tokenLength;
76
76
77 if (final[state]) {
77 if (final[state]) {
78 tag = tags[state];
78 tag = tags[state];
79 return true;
79 return true;
80 }
80 }
81
81
82 if (m_bufferOffset == m_bufferSize) {
82 if (m_bufferOffset == m_bufferSize) {
83 if (m_tokenLength == 0) //EOF
83 if (m_tokenLength == 0) //EOF
84 return false;
84 return false;
85
85
86 throw new ParserException();
86 throw new ParserException();
87 }
87 }
88
88
89 throw new ParserException(String.Format("Unexpected symbol '{0}'", m_buffer[m_bufferOffset]));
89 throw new ParserException(String.Format("Unexpected symbol '{0}'", m_buffer[m_bufferOffset]));
90
90
91 }
91 }
92
92
93 protected void Feed(char[] buffer, int offset, int length) {
93 protected void Feed(char[] buffer, int offset, int length) {
94 m_buffer = buffer;
94 m_buffer = buffer;
95 m_bufferOffset = offset;
95 m_bufferOffset = offset;
96 m_bufferSize = offset + length;
96 m_bufferSize = offset + length;
97 }
97 }
98
98
99 protected bool Feed() {
99 protected bool Feed() {
100 if (m_chunkSize <= 0)
100 if (m_chunkSize <= 0)
101 return false;
101 return false;
102
102
103 if (m_buffer != null) {
103 if (m_buffer != null) {
104 var free = m_buffer.Length - m_bufferSize;
104 var free = m_buffer.Length - m_bufferSize;
105
105
106 if (free < m_chunkSize) {
106 if (free < m_chunkSize) {
107 free += m_chunkSize;
107 free += m_chunkSize;
108 var used = m_bufferSize - m_bufferOffset;
108 var used = m_bufferSize - m_bufferOffset;
109 var size = used + free;
109 var size = used + free;
110
110
111 if (size > m_bufferMax)
111 if (size > m_bufferMax)
112 throw new ParserException(String.Format("The buffer limit ({0} Kb) is reached", m_bufferMax/1024));
112 throw new ParserException(String.Format("The buffer limit ({0} Kb) is reached", m_bufferMax / 1024));
113
113
114 var temp = new char[size];
114 var temp = new char[size];
115
115
116 var read = Read(temp, used, m_chunkSize);
116 var read = Read(temp, used, m_chunkSize);
117 if (read == 0)
117 if (read == 0)
118 return false;
118 return false;
119
119
120 Array.Copy(m_buffer, m_bufferOffset, temp, 0, used);
120 Array.Copy(m_buffer, m_bufferOffset, temp, 0, used);
121
121
122 m_bufferOffset = 0;
122 m_bufferOffset = 0;
123 m_bufferSize = used + read;
123 m_bufferSize = used + read;
124 m_buffer = temp;
124 m_buffer = temp;
125 } else {
126 var read = Read(m_buffer, m_bufferSize, m_chunkSize);
127 if (read == 0)
128 return false;
129 m_bufferSize += m_chunkSize;
125 }
130 }
131 return true;
126 } else {
132 } else {
127 Debug.Assert(m_bufferOffset == 0);
133 Debug.Assert(m_bufferOffset == 0);
128 m_buffer = new char[m_chunkSize];
134 m_buffer = new char[m_chunkSize];
129 m_bufferSize = Read(m_buffer, 0, m_chunkSize);
135 m_bufferSize = Read(m_buffer, 0, m_chunkSize);
130 return (m_bufferSize != 0);
136 return (m_bufferSize != 0);
131 }
137 }
132 }
138 }
133
139
134 protected abstract int Read(char[] buffer, int offset, int size);
140 protected abstract int Read(char[] buffer, int offset, int size);
135
141
136 public string GetTokenValue() {
142 public string GetTokenValue() {
137 return new String(m_buffer, m_tokenOffset, m_tokenLength);
143 return new String(m_buffer, m_tokenOffset, m_tokenLength);
138 }
144 }
139
145
140 public void CopyTokenTo(char[] buffer, int offset) {
146 public void CopyTokenTo(char[] buffer, int offset) {
141 m_buffer.CopyTo(buffer, offset);
147 m_buffer.CopyTo(buffer, offset);
142 }
148 }
143
149
144 public void CopyTokenTo(StringBuilder sb) {
150 public void CopyTokenTo(StringBuilder sb) {
145 sb.Append(m_buffer, m_tokenOffset, m_tokenLength);
151 sb.Append(m_buffer, m_tokenOffset, m_tokenLength);
146 }
152 }
147
153
148 }
154 }
149 }
155 }
150
156
@@ -1,276 +1,274
1 <?xml version="1.0" encoding="utf-8"?>
1 <?xml version="1.0" encoding="utf-8"?>
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup>
3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
7 <OutputType>Library</OutputType>
7 <OutputType>Library</OutputType>
8 <RootNamespace>Implab</RootNamespace>
8 <RootNamespace>Implab</RootNamespace>
9 <AssemblyName>Implab</AssemblyName>
9 <AssemblyName>Implab</AssemblyName>
10 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
10 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
11 <ReleaseVersion>0.2</ReleaseVersion>
11 <ReleaseVersion>0.2</ReleaseVersion>
12 <ProductVersion>8.0.30703</ProductVersion>
12 <ProductVersion>8.0.30703</ProductVersion>
13 <SchemaVersion>2.0</SchemaVersion>
13 <SchemaVersion>2.0</SchemaVersion>
14 </PropertyGroup>
14 </PropertyGroup>
15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16 <DebugSymbols>true</DebugSymbols>
16 <DebugSymbols>true</DebugSymbols>
17 <DebugType>full</DebugType>
17 <DebugType>full</DebugType>
18 <Optimize>false</Optimize>
18 <Optimize>false</Optimize>
19 <OutputPath>bin\Debug</OutputPath>
19 <OutputPath>bin\Debug</OutputPath>
20 <DefineConstants>TRACE;DEBUG;</DefineConstants>
20 <DefineConstants>TRACE;DEBUG;</DefineConstants>
21 <ErrorReport>prompt</ErrorReport>
21 <ErrorReport>prompt</ErrorReport>
22 <WarningLevel>4</WarningLevel>
22 <WarningLevel>4</WarningLevel>
23 <ConsolePause>false</ConsolePause>
23 <ConsolePause>false</ConsolePause>
24 <RunCodeAnalysis>true</RunCodeAnalysis>
24 <RunCodeAnalysis>true</RunCodeAnalysis>
25 </PropertyGroup>
25 </PropertyGroup>
26 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
26 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
27 <DebugType>full</DebugType>
27 <DebugType>full</DebugType>
28 <Optimize>true</Optimize>
28 <Optimize>true</Optimize>
29 <OutputPath>bin\Release</OutputPath>
29 <OutputPath>bin\Release</OutputPath>
30 <ErrorReport>prompt</ErrorReport>
30 <ErrorReport>prompt</ErrorReport>
31 <WarningLevel>4</WarningLevel>
31 <WarningLevel>4</WarningLevel>
32 <ConsolePause>false</ConsolePause>
32 <ConsolePause>false</ConsolePause>
33 </PropertyGroup>
33 </PropertyGroup>
34 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
34 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
35 <DebugSymbols>true</DebugSymbols>
35 <DebugSymbols>true</DebugSymbols>
36 <DebugType>full</DebugType>
36 <DebugType>full</DebugType>
37 <Optimize>false</Optimize>
37 <Optimize>false</Optimize>
38 <OutputPath>bin\Debug</OutputPath>
38 <OutputPath>bin\Debug</OutputPath>
39 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
39 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
40 <ErrorReport>prompt</ErrorReport>
40 <ErrorReport>prompt</ErrorReport>
41 <WarningLevel>4</WarningLevel>
41 <WarningLevel>4</WarningLevel>
42 <RunCodeAnalysis>true</RunCodeAnalysis>
42 <RunCodeAnalysis>true</RunCodeAnalysis>
43 <ConsolePause>false</ConsolePause>
43 <ConsolePause>false</ConsolePause>
44 </PropertyGroup>
44 </PropertyGroup>
45 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
45 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
46 <Optimize>true</Optimize>
46 <Optimize>true</Optimize>
47 <OutputPath>bin\Release</OutputPath>
47 <OutputPath>bin\Release</OutputPath>
48 <ErrorReport>prompt</ErrorReport>
48 <ErrorReport>prompt</ErrorReport>
49 <WarningLevel>4</WarningLevel>
49 <WarningLevel>4</WarningLevel>
50 <ConsolePause>false</ConsolePause>
50 <ConsolePause>false</ConsolePause>
51 <DefineConstants>NET_4_5</DefineConstants>
51 <DefineConstants>NET_4_5</DefineConstants>
52 </PropertyGroup>
52 </PropertyGroup>
53 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMono|AnyCPU' ">
53 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMono|AnyCPU' ">
54 <DebugSymbols>true</DebugSymbols>
54 <DebugSymbols>true</DebugSymbols>
55 <DebugType>full</DebugType>
55 <DebugType>full</DebugType>
56 <Optimize>false</Optimize>
56 <Optimize>false</Optimize>
57 <OutputPath>bin\Debug</OutputPath>
57 <OutputPath>bin\Debug</OutputPath>
58 <DefineConstants>TRACE;DEBUG;NET_4_5;MONO</DefineConstants>
58 <DefineConstants>TRACE;DEBUG;NET_4_5;MONO</DefineConstants>
59 <ErrorReport>prompt</ErrorReport>
59 <ErrorReport>prompt</ErrorReport>
60 <WarningLevel>4</WarningLevel>
60 <WarningLevel>4</WarningLevel>
61 <RunCodeAnalysis>true</RunCodeAnalysis>
61 <RunCodeAnalysis>true</RunCodeAnalysis>
62 <ConsolePause>false</ConsolePause>
62 <ConsolePause>false</ConsolePause>
63 </PropertyGroup>
63 </PropertyGroup>
64 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMono|AnyCPU' ">
64 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMono|AnyCPU' ">
65 <Optimize>true</Optimize>
65 <Optimize>true</Optimize>
66 <OutputPath>bin\Release</OutputPath>
66 <OutputPath>bin\Release</OutputPath>
67 <DefineConstants>NET_4_5;MONO;</DefineConstants>
67 <DefineConstants>NET_4_5;MONO;</DefineConstants>
68 <ErrorReport>prompt</ErrorReport>
68 <ErrorReport>prompt</ErrorReport>
69 <WarningLevel>4</WarningLevel>
69 <WarningLevel>4</WarningLevel>
70 <ConsolePause>false</ConsolePause>
70 <ConsolePause>false</ConsolePause>
71 </PropertyGroup>
71 </PropertyGroup>
72 <ItemGroup>
72 <ItemGroup>
73 <Reference Include="System" />
73 <Reference Include="System" />
74 <Reference Include="System.Xml" />
74 <Reference Include="System.Xml" />
75 <Reference Include="mscorlib" />
75 <Reference Include="mscorlib" />
76 </ItemGroup>
76 </ItemGroup>
77 <ItemGroup>
77 <ItemGroup>
78 <Compile Include="CustomEqualityComparer.cs" />
78 <Compile Include="CustomEqualityComparer.cs" />
79 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
79 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
80 <Compile Include="Diagnostics\EventText.cs" />
80 <Compile Include="Diagnostics\EventText.cs" />
81 <Compile Include="Diagnostics\LogChannel.cs" />
81 <Compile Include="Diagnostics\LogChannel.cs" />
82 <Compile Include="Diagnostics\LogicalOperation.cs" />
82 <Compile Include="Diagnostics\LogicalOperation.cs" />
83 <Compile Include="Diagnostics\TextFileListener.cs" />
83 <Compile Include="Diagnostics\TextFileListener.cs" />
84 <Compile Include="Diagnostics\TraceLog.cs" />
84 <Compile Include="Diagnostics\TraceLog.cs" />
85 <Compile Include="Diagnostics\TraceEvent.cs" />
85 <Compile Include="Diagnostics\TraceEvent.cs" />
86 <Compile Include="Diagnostics\TraceEventType.cs" />
86 <Compile Include="Diagnostics\TraceEventType.cs" />
87 <Compile Include="ICancellable.cs" />
87 <Compile Include="ICancellable.cs" />
88 <Compile Include="IProgressHandler.cs" />
88 <Compile Include="IProgressHandler.cs" />
89 <Compile Include="IProgressNotifier.cs" />
89 <Compile Include="IProgressNotifier.cs" />
90 <Compile Include="IPromiseT.cs" />
90 <Compile Include="IPromiseT.cs" />
91 <Compile Include="IPromise.cs" />
91 <Compile Include="IPromise.cs" />
92 <Compile Include="IServiceLocator.cs" />
92 <Compile Include="IServiceLocator.cs" />
93 <Compile Include="ITaskController.cs" />
93 <Compile Include="ITaskController.cs" />
94 <Compile Include="Parallels\DispatchPool.cs" />
94 <Compile Include="Parallels\DispatchPool.cs" />
95 <Compile Include="Parallels\ArrayTraits.cs" />
95 <Compile Include="Parallels\ArrayTraits.cs" />
96 <Compile Include="Parallels\MTQueue.cs" />
96 <Compile Include="Parallels\MTQueue.cs" />
97 <Compile Include="Parallels\WorkerPool.cs" />
97 <Compile Include="Parallels\WorkerPool.cs" />
98 <Compile Include="ProgressInitEventArgs.cs" />
98 <Compile Include="ProgressInitEventArgs.cs" />
99 <Compile Include="Properties\AssemblyInfo.cs" />
99 <Compile Include="Properties\AssemblyInfo.cs" />
100 <Compile Include="Parallels\AsyncPool.cs" />
100 <Compile Include="Parallels\AsyncPool.cs" />
101 <Compile Include="Safe.cs" />
101 <Compile Include="Safe.cs" />
102 <Compile Include="ValueEventArgs.cs" />
102 <Compile Include="ValueEventArgs.cs" />
103 <Compile Include="PromiseExtensions.cs" />
103 <Compile Include="PromiseExtensions.cs" />
104 <Compile Include="SyncContextPromise.cs" />
104 <Compile Include="SyncContextPromise.cs" />
105 <Compile Include="Diagnostics\OperationContext.cs" />
105 <Compile Include="Diagnostics\OperationContext.cs" />
106 <Compile Include="Diagnostics\TraceContext.cs" />
106 <Compile Include="Diagnostics\TraceContext.cs" />
107 <Compile Include="Diagnostics\LogEventArgs.cs" />
107 <Compile Include="Diagnostics\LogEventArgs.cs" />
108 <Compile Include="Diagnostics\LogEventArgsT.cs" />
108 <Compile Include="Diagnostics\LogEventArgsT.cs" />
109 <Compile Include="Diagnostics\Extensions.cs" />
109 <Compile Include="Diagnostics\Extensions.cs" />
110 <Compile Include="PromiseEventType.cs" />
110 <Compile Include="PromiseEventType.cs" />
111 <Compile Include="Parallels\AsyncQueue.cs" />
111 <Compile Include="Parallels\AsyncQueue.cs" />
112 <Compile Include="PromiseT.cs" />
112 <Compile Include="PromiseT.cs" />
113 <Compile Include="IDeferred.cs" />
113 <Compile Include="IDeferred.cs" />
114 <Compile Include="IDeferredT.cs" />
114 <Compile Include="IDeferredT.cs" />
115 <Compile Include="Promise.cs" />
115 <Compile Include="Promise.cs" />
116 <Compile Include="PromiseTransientException.cs" />
116 <Compile Include="PromiseTransientException.cs" />
117 <Compile Include="Parallels\Signal.cs" />
117 <Compile Include="Parallels\Signal.cs" />
118 <Compile Include="Parallels\SharedLock.cs" />
118 <Compile Include="Parallels\SharedLock.cs" />
119 <Compile Include="Diagnostics\ILogWriter.cs" />
119 <Compile Include="Diagnostics\ILogWriter.cs" />
120 <Compile Include="Diagnostics\ListenerBase.cs" />
120 <Compile Include="Diagnostics\ListenerBase.cs" />
121 <Compile Include="Parallels\BlockingQueue.cs" />
121 <Compile Include="Parallels\BlockingQueue.cs" />
122 <Compile Include="AbstractEvent.cs" />
122 <Compile Include="AbstractEvent.cs" />
123 <Compile Include="AbstractPromise.cs" />
123 <Compile Include="AbstractPromise.cs" />
124 <Compile Include="AbstractPromiseT.cs" />
124 <Compile Include="AbstractPromiseT.cs" />
125 <Compile Include="FuncTask.cs" />
125 <Compile Include="FuncTask.cs" />
126 <Compile Include="FuncTaskBase.cs" />
126 <Compile Include="FuncTaskBase.cs" />
127 <Compile Include="FuncTaskT.cs" />
127 <Compile Include="FuncTaskT.cs" />
128 <Compile Include="ActionChainTaskBase.cs" />
128 <Compile Include="ActionChainTaskBase.cs" />
129 <Compile Include="ActionChainTask.cs" />
129 <Compile Include="ActionChainTask.cs" />
130 <Compile Include="ActionChainTaskT.cs" />
130 <Compile Include="ActionChainTaskT.cs" />
131 <Compile Include="FuncChainTaskBase.cs" />
131 <Compile Include="FuncChainTaskBase.cs" />
132 <Compile Include="FuncChainTask.cs" />
132 <Compile Include="FuncChainTask.cs" />
133 <Compile Include="FuncChainTaskT.cs" />
133 <Compile Include="FuncChainTaskT.cs" />
134 <Compile Include="ActionTaskBase.cs" />
134 <Compile Include="ActionTaskBase.cs" />
135 <Compile Include="ActionTask.cs" />
135 <Compile Include="ActionTask.cs" />
136 <Compile Include="ActionTaskT.cs" />
136 <Compile Include="ActionTaskT.cs" />
137 <Compile Include="ICancellationToken.cs" />
137 <Compile Include="ICancellationToken.cs" />
138 <Compile Include="SuccessPromise.cs" />
138 <Compile Include="SuccessPromise.cs" />
139 <Compile Include="SuccessPromiseT.cs" />
139 <Compile Include="SuccessPromiseT.cs" />
140 <Compile Include="PromiseAwaiterT.cs" />
140 <Compile Include="PromiseAwaiterT.cs" />
141 <Compile Include="PromiseAwaiter.cs" />
141 <Compile Include="PromiseAwaiter.cs" />
142 <Compile Include="Components\ComponentContainer.cs" />
142 <Compile Include="Components\ComponentContainer.cs" />
143 <Compile Include="Components\Disposable.cs" />
143 <Compile Include="Components\Disposable.cs" />
144 <Compile Include="Components\DisposablePool.cs" />
144 <Compile Include="Components\DisposablePool.cs" />
145 <Compile Include="Components\ObjectPool.cs" />
145 <Compile Include="Components\ObjectPool.cs" />
146 <Compile Include="Components\ServiceLocator.cs" />
146 <Compile Include="Components\ServiceLocator.cs" />
147 <Compile Include="Components\IInitializable.cs" />
147 <Compile Include="Components\IInitializable.cs" />
148 <Compile Include="TaskController.cs" />
148 <Compile Include="TaskController.cs" />
149 <Compile Include="Components\App.cs" />
149 <Compile Include="Components\App.cs" />
150 <Compile Include="Components\IRunnable.cs" />
150 <Compile Include="Components\IRunnable.cs" />
151 <Compile Include="Components\ExecutionState.cs" />
151 <Compile Include="Components\ExecutionState.cs" />
152 <Compile Include="Components\RunnableComponent.cs" />
152 <Compile Include="Components\RunnableComponent.cs" />
153 <Compile Include="Components\IFactory.cs" />
153 <Compile Include="Components\IFactory.cs" />
154 <Compile Include="Automaton\EnumAlphabet.cs" />
155 <Compile Include="Automaton\IAlphabet.cs" />
154 <Compile Include="Automaton\IAlphabet.cs" />
156 <Compile Include="Automaton\ParserException.cs" />
155 <Compile Include="Automaton\ParserException.cs" />
157 <Compile Include="Automaton\IndexedAlphabetBase.cs" />
156 <Compile Include="Automaton\IndexedAlphabetBase.cs" />
158 <Compile Include="Automaton\IAlphabetBuilder.cs" />
157 <Compile Include="Automaton\IAlphabetBuilder.cs" />
159 <Compile Include="Automaton\RegularExpressions\AltToken.cs" />
158 <Compile Include="Automaton\RegularExpressions\AltToken.cs" />
160 <Compile Include="Automaton\RegularExpressions\BinaryToken.cs" />
159 <Compile Include="Automaton\RegularExpressions\BinaryToken.cs" />
161 <Compile Include="Automaton\RegularExpressions\CatToken.cs" />
160 <Compile Include="Automaton\RegularExpressions\CatToken.cs" />
162 <Compile Include="Automaton\RegularExpressions\StarToken.cs" />
161 <Compile Include="Automaton\RegularExpressions\StarToken.cs" />
163 <Compile Include="Automaton\RegularExpressions\SymbolToken.cs" />
162 <Compile Include="Automaton\RegularExpressions\SymbolToken.cs" />
164 <Compile Include="Automaton\RegularExpressions\EmptyToken.cs" />
163 <Compile Include="Automaton\RegularExpressions\EmptyToken.cs" />
165 <Compile Include="Automaton\RegularExpressions\Token.cs" />
164 <Compile Include="Automaton\RegularExpressions\Token.cs" />
166 <Compile Include="Automaton\RegularExpressions\IVisitor.cs" />
165 <Compile Include="Automaton\RegularExpressions\IVisitor.cs" />
167 <Compile Include="Automaton\AutomatonTransition.cs" />
166 <Compile Include="Automaton\AutomatonTransition.cs" />
168 <Compile Include="Formats\JSON\JSONElementContext.cs" />
167 <Compile Include="Formats\JSON\JSONElementContext.cs" />
169 <Compile Include="Formats\JSON\JSONElementType.cs" />
168 <Compile Include="Formats\JSON\JSONElementType.cs" />
170 <Compile Include="Formats\JSON\JSONGrammar.cs" />
169 <Compile Include="Formats\JSON\JSONGrammar.cs" />
171 <Compile Include="Formats\JSON\JSONParser.cs" />
170 <Compile Include="Formats\JSON\JSONParser.cs" />
172 <Compile Include="Formats\JSON\JSONScanner.cs" />
171 <Compile Include="Formats\JSON\JSONScanner.cs" />
173 <Compile Include="Formats\JSON\JsonTokenType.cs" />
172 <Compile Include="Formats\JSON\JsonTokenType.cs" />
174 <Compile Include="Formats\JSON\JSONWriter.cs" />
173 <Compile Include="Formats\JSON\JSONWriter.cs" />
175 <Compile Include="Formats\JSON\JSONXmlReader.cs" />
174 <Compile Include="Formats\JSON\JSONXmlReader.cs" />
176 <Compile Include="Formats\JSON\JSONXmlReaderOptions.cs" />
175 <Compile Include="Formats\JSON\JSONXmlReaderOptions.cs" />
177 <Compile Include="Formats\JSON\StringTranslator.cs" />
176 <Compile Include="Formats\JSON\StringTranslator.cs" />
178 <Compile Include="Automaton\MapAlphabet.cs" />
177 <Compile Include="Automaton\MapAlphabet.cs" />
179 <Compile Include="Automaton\DummyAlphabet.cs" />
180 <Compile Include="Formats\CharAlphabet.cs" />
178 <Compile Include="Formats\CharAlphabet.cs" />
181 <Compile Include="Formats\ByteAlphabet.cs" />
179 <Compile Include="Formats\ByteAlphabet.cs" />
182 <Compile Include="Automaton\IDFATable.cs" />
180 <Compile Include="Automaton\IDFATable.cs" />
183 <Compile Include="Automaton\IDFATableBuilder.cs" />
181 <Compile Include="Automaton\IDFATableBuilder.cs" />
184 <Compile Include="Automaton\DFATable.cs" />
182 <Compile Include="Automaton\DFATable.cs" />
185 <Compile Include="Automaton\RegularExpressions\RegularExpressionVisitor.cs" />
183 <Compile Include="Automaton\RegularExpressions\RegularExpressionVisitor.cs" />
186 <Compile Include="Automaton\RegularExpressions\ITaggedDFABuilder.cs" />
184 <Compile Include="Automaton\RegularExpressions\ITaggedDFABuilder.cs" />
187 <Compile Include="Formats\TextScanner.cs" />
185 <Compile Include="Formats\TextScanner.cs" />
188 <Compile Include="Formats\StringScanner.cs" />
186 <Compile Include="Formats\StringScanner.cs" />
189 <Compile Include="Formats\ReaderScanner.cs" />
187 <Compile Include="Formats\ReaderScanner.cs" />
190 <Compile Include="Formats\ScannerContext.cs" />
188 <Compile Include="Formats\ScannerContext.cs" />
191 <Compile Include="Formats\Grammar.cs" />
189 <Compile Include="Formats\Grammar.cs" />
192 <Compile Include="Automaton\RegularExpressions\EndTokenT.cs" />
190 <Compile Include="Automaton\RegularExpressions\EndTokenT.cs" />
193 <Compile Include="Automaton\RegularExpressions\EndToken.cs" />
191 <Compile Include="Automaton\RegularExpressions\EndToken.cs" />
194 <Compile Include="Automaton\RegularExpressions\RegularExpressionVisitorT.cs" />
192 <Compile Include="Automaton\RegularExpressions\RegularExpressionVisitorT.cs" />
195 <Compile Include="Automaton\AutomatonConst.cs" />
193 <Compile Include="Automaton\AutomatonConst.cs" />
196 <Compile Include="Automaton\RegularExpressions\RegularDFA.cs" />
194 <Compile Include="Automaton\RegularExpressions\RegularDFA.cs" />
197 <Compile Include="Components\LazyAndWeak.cs" />
195 <Compile Include="Components\LazyAndWeak.cs" />
198 </ItemGroup>
196 </ItemGroup>
199 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
197 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
200 <ItemGroup />
198 <ItemGroup />
201 <ProjectExtensions>
199 <ProjectExtensions>
202 <MonoDevelop>
200 <MonoDevelop>
203 <Properties>
201 <Properties>
204 <Policies>
202 <Policies>
205 <CSharpFormattingPolicy IndentSwitchBody="True" NamespaceBraceStyle="EndOfLine" ClassBraceStyle="EndOfLine" InterfaceBraceStyle="EndOfLine" StructBraceStyle="EndOfLine" EnumBraceStyle="EndOfLine" MethodBraceStyle="EndOfLine" ConstructorBraceStyle="EndOfLine" DestructorBraceStyle="EndOfLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeIndexerDeclarationBracket="False" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
203 <CSharpFormattingPolicy IndentSwitchBody="True" NamespaceBraceStyle="EndOfLine" ClassBraceStyle="EndOfLine" InterfaceBraceStyle="EndOfLine" StructBraceStyle="EndOfLine" EnumBraceStyle="EndOfLine" MethodBraceStyle="EndOfLine" ConstructorBraceStyle="EndOfLine" DestructorBraceStyle="EndOfLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeIndexerDeclarationBracket="False" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
206 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
204 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
207 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
205 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
208 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
206 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
209 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
207 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
210 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
208 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
211 <NameConventionPolicy>
209 <NameConventionPolicy>
212 <Rules>
210 <Rules>
213 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
211 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
214 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
212 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
215 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
213 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
216 <RequiredPrefixes>
214 <RequiredPrefixes>
217 <String>I</String>
215 <String>I</String>
218 </RequiredPrefixes>
216 </RequiredPrefixes>
219 </NamingRule>
217 </NamingRule>
220 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
218 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
221 <RequiredSuffixes>
219 <RequiredSuffixes>
222 <String>Attribute</String>
220 <String>Attribute</String>
223 </RequiredSuffixes>
221 </RequiredSuffixes>
224 </NamingRule>
222 </NamingRule>
225 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
223 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
226 <RequiredSuffixes>
224 <RequiredSuffixes>
227 <String>EventArgs</String>
225 <String>EventArgs</String>
228 </RequiredSuffixes>
226 </RequiredSuffixes>
229 </NamingRule>
227 </NamingRule>
230 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
228 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
231 <RequiredSuffixes>
229 <RequiredSuffixes>
232 <String>Exception</String>
230 <String>Exception</String>
233 </RequiredSuffixes>
231 </RequiredSuffixes>
234 </NamingRule>
232 </NamingRule>
235 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
233 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
236 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
234 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
237 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
235 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
238 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
236 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
239 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
237 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
240 <RequiredPrefixes>
238 <RequiredPrefixes>
241 <String>m_</String>
239 <String>m_</String>
242 </RequiredPrefixes>
240 </RequiredPrefixes>
243 </NamingRule>
241 </NamingRule>
244 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
242 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
245 <RequiredPrefixes>
243 <RequiredPrefixes>
246 <String>_</String>
244 <String>_</String>
247 </RequiredPrefixes>
245 </RequiredPrefixes>
248 </NamingRule>
246 </NamingRule>
249 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
247 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
250 <RequiredPrefixes>
248 <RequiredPrefixes>
251 <String>m_</String>
249 <String>m_</String>
252 </RequiredPrefixes>
250 </RequiredPrefixes>
253 </NamingRule>
251 </NamingRule>
254 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
252 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
255 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
253 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
256 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
254 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
257 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
255 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
258 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
256 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
259 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
257 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
260 <RequiredPrefixes>
258 <RequiredPrefixes>
261 <String>T</String>
259 <String>T</String>
262 </RequiredPrefixes>
260 </RequiredPrefixes>
263 </NamingRule>
261 </NamingRule>
264 </Rules>
262 </Rules>
265 </NameConventionPolicy>
263 </NameConventionPolicy>
266 </Policies>
264 </Policies>
267 </Properties>
265 </Properties>
268 </MonoDevelop>
266 </MonoDevelop>
269 </ProjectExtensions>
267 </ProjectExtensions>
270 <ItemGroup>
268 <ItemGroup>
271 <Folder Include="Components\" />
269 <Folder Include="Components\" />
272 <Folder Include="Automaton\RegularExpressions\" />
270 <Folder Include="Automaton\RegularExpressions\" />
273 <Folder Include="Formats\" />
271 <Folder Include="Formats\" />
274 <Folder Include="Formats\JSON\" />
272 <Folder Include="Formats\JSON\" />
275 </ItemGroup>
273 </ItemGroup>
276 </Project> No newline at end of file
274 </Project>
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now