##// END OF EJS Templates
DFA refactoring
cin -
r165:e227e78d72e4 ref20160224
parent child
Show More
@@ -0,0 +1,59
1 using System.Collections.Generic;
2
3
4 namespace Implab.Automaton {
5 /// <summary>
6 /// Полностью описывает DFA автомат, его поведение, состояние и входные символы.
7 /// </summary>
8 /// <example>
9 /// class MyAutomaton {
10 /// int m_current;
11 /// readonly DFAStateDescriptor<string>[] m_automaton;
12 /// readonly IAlphabet<MyCommands> m_commands;
13 ///
14 /// public MyAutomaton(IDFADefinition&lt;MyCommands,MyStates,string&gt; definition) {
15 /// m_current = definition.StateAlphabet.Translate(MyStates.Initial);
16 /// m_automaton = definition.GetTransitionTable();
17 /// m_commands = definition.InputAlphabet;
18 /// }
19 ///
20 /// // defined a method which will move the automaton to the next state
21 /// public void Move(MyCommands cmd) {
22 /// // use transition map to determine the next state
23 /// var next = m_automaton[m_current].transitions[m_commands.Translate(cmd)];
24 ///
25 /// // validate that we aren't in the unreachable state
26 /// if (next == DFAConst.UNREACHABLE_STATE)
27 /// throw new InvalidOperationException("The specified command is invalid");
28 ///
29 /// // if everything is ok
30 /// m_current = next;
31 /// }
32 /// }
33 /// </example>
34 public interface IDFATable {
35 /// <summary>
36 /// Таблица переходов состояний автомата
37 /// </summary>
38 /// <returns>The transition table.</returns>
39 DFAStateDescriptior[] GetTransitionTable();
40
41 int StateCount {
42 get;
43 }
44
45 int AlphabetSize {
46 get;
47 }
48
49 int InitialState {
50 get;
51 }
52
53 bool IsFinalState(int s);
54
55 IEnumerable<int> FinalStates {
56 get;
57 }
58 }
59 }
@@ -0,0 +1,24
1 using System;
2
3 namespace Implab.Automaton {
4 public interface IDFATableBuilder : IDFATable {
5 /// <summary>
6 /// Marks the state as final.
7 /// </summary>
8 /// <param name="state">State.</param>
9 void MarkFinalState(int state);
10
11 /// <summary>
12 /// Defines the transition from <paramref name="s1"/> to
13 /// <paramref name="s2"/> with input <paramref name="symbol"/>.
14 /// </summary>
15 /// <param name="s1">S1.</param>
16 /// <param name="s2">S2.</param>
17 /// <param name="symbol">Symbol.</param>
18 void DefineTransition(int s1, int s2, int symbol);
19
20 void SetInitialState(int s);
21
22 }
23 }
24
@@ -0,0 +1,17
1 using System;
2 using Implab.Automaton.RegularExpressions;
3
4 namespace Implab.Formats {
5 public class RegularCharDFADefinition<TTag> : RegularDFADefinition<char,TTag> {
6 readonly CharAlphabet m_alphabet;
7
8 public RegularCharDFADefinition(CharAlphabet alphabet) : base(alphabet) {
9 m_alphabet = alphabet;
10 }
11
12 public new CharAlphabet InputAlphabet {
13 get { return m_alphabet; }
14 }
15 }
16 }
17
@@ -1,7 +1,15
1 namespace Implab.Automaton {
1 namespace Implab.Automaton {
2 public struct DFAStateDescriptior<TTag> {
2 public struct DFAStateDescriptior {
3 public bool final;
3 public readonly bool final;
4 public TTag[] tag;
4 public readonly int[] transitions;
5 public int[] transitions;
5
6
7 public DFAStateDescriptior(int[] transitions, bool final) {
8 this.transitions = transitions;
9 this.final = final;
10 }
11
12 public DFAStateDescriptior(int[] transitions) : this(transitions, false) {
6 }
13 }
7 }
14 }
15 }
@@ -1,251 +1,251
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 DFATransitionTable<TTag> : IDFATransitionTableBuilder<TTag> {
7 public class DFATransitionTable<TTag> : IDFATableBuilder {
8 DFAStateDescriptior<TTag>[] m_dfaTable;
8 DFAStateDescriptior[] m_dfaTable;
9
9
10 int m_stateCount;
10 int m_stateCount;
11 int m_symbolCount;
11 int m_symbolCount;
12 int m_initialState;
12 int m_initialState;
13
13
14 readonly Dictionary<int, TTag[]> m_finalStates = new Dictionary<int, TTag[]>();
14 readonly Dictionary<int, TTag[]> m_finalStates = new Dictionary<int, TTag[]>();
15 readonly HashSet<AutomatonTransition> m_transitions = new HashSet<AutomatonTransition>();
15 readonly HashSet<AutomatonTransition> m_transitions = new HashSet<AutomatonTransition>();
16
16
17
17
18 #region IDFADefinition implementation
18 #region IDFADefinition implementation
19
19
20 public DFAStateDescriptior<TTag>[] GetTransitionTable() {
20 public DFAStateDescriptior[] GetTransitionTable() {
21 if (m_dfaTable == null) {
21 if (m_dfaTable == null) {
22 if (m_stateCount <= 0)
22 if (m_stateCount <= 0)
23 throw new InvalidOperationException("Invalid automaton definition: states count = {0}", m_stateCount);
23 throw new InvalidOperationException("Invalid automaton definition: states count = {0}", m_stateCount);
24 if (m_symbolCount <= 0)
24 if (m_symbolCount <= 0)
25 throw new InvalidOperationException("Invalid automaton definition: symbols count = {0}", m_symbolCount);
25 throw new InvalidOperationException("Invalid automaton definition: symbols count = {0}", m_symbolCount);
26
26
27 m_dfaTable = ConstructTransitionTable();
27 m_dfaTable = ConstructTransitionTable();
28 }
28 }
29 return m_dfaTable;
29 return m_dfaTable;
30 }
30 }
31
31
32 public bool IsFinalState(int s) {
32 public bool IsFinalState(int s) {
33 Safe.ArgumentInRange(s, 0, m_stateCount, "s");
33 Safe.ArgumentInRange(s, 0, m_stateCount, "s");
34
34
35 return m_finalStates.ContainsKey(s);
35 return m_finalStates.ContainsKey(s);
36 }
36 }
37
37
38 public IEnumerable<KeyValuePair<int,TTag[]>> FinalStates {
38 public IEnumerable<KeyValuePair<int,TTag[]>> FinalStates {
39 get {
39 get {
40 return m_finalStates;
40 return m_finalStates;
41 }
41 }
42 }
42 }
43
43
44 public int StateCount {
44 public int StateCount {
45 get { return m_stateCount; }
45 get { return m_stateCount; }
46 }
46 }
47
47
48 public int AlphabetSize {
48 public int AlphabetSize {
49 get { return m_symbolCount; }
49 get { return m_symbolCount; }
50 }
50 }
51
51
52 public int InitialState {
52 public int InitialState {
53 get { return m_initialState; }
53 get { return m_initialState; }
54 }
54 }
55
55
56 #endregion
56 #endregion
57
57
58 protected virtual DFAStateDescriptior<TTag>[] ConstructTransitionTable() {
58 protected virtual DFAStateDescriptior<TTag>[] ConstructTransitionTable() {
59 var dfaTable = new DFAStateDescriptior<TTag>[m_stateCount];
59 var dfaTable = new DFAStateDescriptior<TTag>[m_stateCount];
60
60
61 foreach (var pair in m_finalStates) {
61 foreach (var pair in m_finalStates) {
62 var idx = pair.Key;
62 var idx = pair.Key;
63
63
64 dfaTable[idx].final = true;
64 dfaTable[idx].final = true;
65 dfaTable[idx].tag = pair.Value;
65 dfaTable[idx].tag = pair.Value;
66 }
66 }
67
67
68 foreach (var t in m_transitions) {
68 foreach (var t in m_transitions) {
69 if (dfaTable[t.s1].transitions == null) {
69 if (dfaTable[t.s1].transitions == null) {
70 dfaTable[t.s1].transitions = new int[m_symbolCount];
70 dfaTable[t.s1].transitions = new int[m_symbolCount];
71 for (int i = 0; i < dfaTable[t.s1].transitions.Length; i++)
71 for (int i = 0; i < dfaTable[t.s1].transitions.Length; i++)
72 dfaTable[t.s1].transitions[i] = DFAConst.UNREACHABLE_STATE;
72 dfaTable[t.s1].transitions[i] = DFAConst.UNREACHABLE_STATE;
73 }
73 }
74
74
75 dfaTable[t.s1].transitions[t.edge] = t.s2;
75 dfaTable[t.s1].transitions[t.edge] = t.s2;
76 }
76 }
77 }
77 }
78
78
79 #region IDFADefinitionBuilder
79 #region IDFADefinitionBuilder
80
80
81 public void DefineTransition(int s1, int s2, int symbol) {
81 public void DefineTransition(int s1, int s2, int symbol) {
82 if (m_dfaTable != null)
82 if (m_dfaTable != null)
83 throw new InvalidOperationException("The transition table is already built");
83 throw new InvalidOperationException("The transition table is already built");
84
84
85 Safe.ArgumentAssert(s1 > 0, "s1");
85 Safe.ArgumentAssert(s1 > 0, "s1");
86 Safe.ArgumentAssert(s2 > 0, "s2");
86 Safe.ArgumentAssert(s2 > 0, "s2");
87 Safe.ArgumentAssert(symbol >= 0, "symbol");
87 Safe.ArgumentAssert(symbol >= 0, "symbol");
88
88
89 m_stateCount = Math.Max(Math.Max(m_stateCount, s1 + 1), s2 + 1);
89 m_stateCount = Math.Max(Math.Max(m_stateCount, s1 + 1), s2 + 1);
90 m_symbolCount = Math.Max(m_symbolCount, symbol + 1);
90 m_symbolCount = Math.Max(m_symbolCount, symbol + 1);
91
91
92 m_transitions.Add(new AutomatonTransition(s1, s2, symbol));
92 m_transitions.Add(new AutomatonTransition(s1, s2, symbol));
93 }
93 }
94
94
95 public void MarkFinalState(int state, params TTag[] tags) {
95 public void MarkFinalState(int state, params TTag[] tags) {
96 if (m_dfaTable != null)
96 if (m_dfaTable != null)
97 throw new InvalidOperationException("The transition table is already built");
97 throw new InvalidOperationException("The transition table is already built");
98
98
99 m_finalStates[state] = tags;
99 m_finalStates[state] = tags;
100 }
100 }
101
101
102 public void SetInitialState(int s) {
102 public void SetInitialState(int s) {
103 Safe.ArgumentAssert(s >= 0, "s");
103 Safe.ArgumentAssert(s >= 0, "s");
104 m_initialState = s;
104 m_initialState = s;
105 }
105 }
106
106
107
107
108 #endregion
108 #endregion
109
109
110 protected void Optimize<TInput, TState>(
110 protected void Optimize<TInput, TState>(
111 IDFATransitionTableBuilder<TTag> optimalDFA,
111 IDFATableBuilder<TTag> optimalDFA,
112 IAlphabet<TInput> inputAlphabet,
112 IAlphabet<TInput> inputAlphabet,
113 IAlphabetBuilder<TInput> optimalInputAlphabet,
113 IAlphabetBuilder<TInput> optimalInputAlphabet,
114 IAlphabet<TState> stateAlphabet,
114 IAlphabet<TState> stateAlphabet,
115 IAlphabetBuilder<TState> optimalStateAlphabet
115 IAlphabetBuilder<TState> optimalStateAlphabet
116 ) {
116 ) {
117 Safe.ArgumentNotNull(optimalDFA, "dfa");
117 Safe.ArgumentNotNull(optimalDFA, "dfa");
118 Safe.ArgumentNotNull(optimalInputAlphabet, "optimalInputAlphabet");
118 Safe.ArgumentNotNull(optimalInputAlphabet, "optimalInputAlphabet");
119 Safe.ArgumentNotNull(optimalStateAlphabet, "optimalStateAlphabet");
119 Safe.ArgumentNotNull(optimalStateAlphabet, "optimalStateAlphabet");
120 Safe.ArgumentNotNull(inputAlphabet, "inputAlphabet");
120 Safe.ArgumentNotNull(inputAlphabet, "inputAlphabet");
121 Safe.ArgumentNotNull(stateAlphabet, "stateAlphabet");
121 Safe.ArgumentNotNull(stateAlphabet, "stateAlphabet");
122
122
123 if (inputAlphabet.Count != m_symbolCount)
123 if (inputAlphabet.Count != m_symbolCount)
124 throw new InvalidOperationException("The input symbols aphabet mismatch");
124 throw new InvalidOperationException("The input symbols aphabet mismatch");
125 if (stateAlphabet.Count != m_stateCount)
125 if (stateAlphabet.Count != m_stateCount)
126 throw new InvalidOperationException("The states alphabet mismatch");
126 throw new InvalidOperationException("The states alphabet mismatch");
127
127
128 var setComparer = new CustomEqualityComparer<HashSet<int>>(
128 var setComparer = new CustomEqualityComparer<HashSet<int>>(
129 (x, y) => x.SetEquals(y),
129 (x, y) => x.SetEquals(y),
130 s => s.Sum(x => x.GetHashCode())
130 s => s.Sum(x => x.GetHashCode())
131 );
131 );
132
132
133 var arrayComparer = new CustomEqualityComparer<TTag[]>(
133 var arrayComparer = new CustomEqualityComparer<TTag[]>(
134 (x,y) => (new HashSet<int>(x)).SetEquals(new HashSet<int>(y)),
134 (x,y) => (new HashSet<int>(x)).SetEquals(new HashSet<int>(y)),
135 a => a.Sum(x => x.GetHashCode())
135 a => a.Sum(x => x.GetHashCode())
136 );
136 );
137
137
138 var optimalStates = new HashSet<HashSet<int>>(setComparer);
138 var optimalStates = new HashSet<HashSet<int>>(setComparer);
139 var queue = new HashSet<HashSet<int>>(setComparer);
139 var queue = new HashSet<HashSet<int>>(setComparer);
140
140
141 // получаем конечные состояния, сгруппированные по маркерам
141 // получаем конечные состояния, сгруппированные по маркерам
142 optimalStates.UnionWith(
142 optimalStates.UnionWith(
143 m_finalStates
143 m_finalStates
144 .GroupBy(pair => pair.Value, arrayComparer)
144 .GroupBy(pair => pair.Value, arrayComparer)
145 .Select(
145 .Select(
146 g => new HashSet<int>(
146 g => new HashSet<int>(
147 g.Select( pair => pair.Key)
147 g.Select( pair => pair.Key)
148 )
148 )
149 )
149 )
150 );
150 );
151
151
152 var state = new HashSet<int>(
152 var state = new HashSet<int>(
153 Enumerable
153 Enumerable
154 .Range(0, m_stateCount - 1)
154 .Range(0, m_stateCount - 1)
155 .Where(i => !m_finalStates.ContainsKey(i))
155 .Where(i => !m_finalStates.ContainsKey(i))
156 );
156 );
157 optimalStates.Add(state);
157 optimalStates.Add(state);
158 queue.Add(state);
158 queue.Add(state);
159
159
160 var rmap = m_transitions
160 var rmap = m_transitions
161 .GroupBy(t => t.s2)
161 .GroupBy(t => t.s2)
162 .ToLookup(
162 .ToLookup(
163 g => g.Key, // s2
163 g => g.Key, // s2
164 g => g.ToLookup(t => t.edge, t => t.s1)
164 g => g.ToLookup(t => t.edge, t => t.s1)
165 );
165 );
166
166
167 while (queue.Count > 0) {
167 while (queue.Count > 0) {
168 var stateA = queue.First();
168 var stateA = queue.First();
169 queue.Remove(stateA);
169 queue.Remove(stateA);
170
170
171 for (int c = 0; c < m_symbolCount; c++) {
171 for (int c = 0; c < m_symbolCount; c++) {
172 var stateX = new HashSet<int>();
172 var stateX = new HashSet<int>();
173 foreach(var a in stateA)
173 foreach(var a in stateA)
174 stateX.UnionWith(rmap[a][c]); // all states from wich 'c' leads to 'a'
174 stateX.UnionWith(rmap[a][c]); // all states from wich 'c' leads to 'a'
175
175
176 foreach (var stateY in optimalStates.ToArray()) {
176 foreach (var stateY in optimalStates.ToArray()) {
177 if (stateX.Overlaps(stateY) && !stateY.IsSubsetOf(stateX)) {
177 if (stateX.Overlaps(stateY) && !stateY.IsSubsetOf(stateX)) {
178 var stateR1 = new HashSet<int>(stateY);
178 var stateR1 = new HashSet<int>(stateY);
179 var stateR2 = new HashSet<int>(stateY);
179 var stateR2 = new HashSet<int>(stateY);
180
180
181 stateR1.IntersectWith(stateX);
181 stateR1.IntersectWith(stateX);
182 stateR2.ExceptWith(stateX);
182 stateR2.ExceptWith(stateX);
183
183
184 optimalStates.Remove(stateY);
184 optimalStates.Remove(stateY);
185 optimalStates.Add(stateR1);
185 optimalStates.Add(stateR1);
186 optimalStates.Add(stateR2);
186 optimalStates.Add(stateR2);
187
187
188 if (queue.Contains(stateY)) {
188 if (queue.Contains(stateY)) {
189 queue.Remove(stateY);
189 queue.Remove(stateY);
190 queue.Add(stateR1);
190 queue.Add(stateR1);
191 queue.Add(stateR2);
191 queue.Add(stateR2);
192 } else {
192 } else {
193 queue.Add(stateR1.Count <= stateR2.Count ? stateR1 : stateR2);
193 queue.Add(stateR1.Count <= stateR2.Count ? stateR1 : stateR2);
194 }
194 }
195 }
195 }
196 }
196 }
197 }
197 }
198 }
198 }
199
199
200 // карта получения оптимального состояния по соотвествующему ему простому состоянию
200 // карта получения оптимального состояния по соотвествующему ему простому состоянию
201 var statesMap = stateAlphabet.Reclassify(optimalStateAlphabet, optimalStates);
201 var statesMap = stateAlphabet.Reclassify(optimalStateAlphabet, optimalStates);
202
202
203 // получаем минимальный алфавит
203 // получаем минимальный алфавит
204 // входные символы не различимы, если Move(s,a1) == Move(s,a2)
204 // входные символы не различимы, если Move(s,a1) == Move(s,a2)
205 var optimalAlphabet = m_transitions
205 var optimalAlphabet = m_transitions
206 .GroupBy(t => Tuple.Create(statesMap[t.s1], statesMap[t.s2]), t => t.edge);
206 .GroupBy(t => Tuple.Create(statesMap[t.s1], statesMap[t.s2]), t => t.edge);
207
207
208 var alphabetMap = inputAlphabet.Reclassify(optimalInputAlphabet, optimalAlphabet);
208 var alphabetMap = inputAlphabet.Reclassify(optimalInputAlphabet, optimalAlphabet);
209
209
210 var optimalTags = m_finalStates
210 var optimalTags = m_finalStates
211 .GroupBy(pair => statesMap[pair.Key])
211 .GroupBy(pair => statesMap[pair.Key])
212 .ToDictionary(
212 .ToDictionary(
213 g => g.Key,
213 g => g.Key,
214 g => g.SelectMany(pair => pair.Value).ToArray()
214 g => g.SelectMany(pair => pair.Value).ToArray()
215 );
215 );
216
216
217 // построение автомата
217 // построение автомата
218 optimalDFA.SetInitialState(statesMap[m_initialState]);
218 optimalDFA.SetInitialState(statesMap[m_initialState]);
219
219
220 foreach (var pair in optimalTags)
220 foreach (var pair in optimalTags)
221 optimalDFA.MarkFinalState(pair.Key, pair.Value);
221 optimalDFA.MarkFinalState(pair.Key, pair.Value);
222
222
223 foreach (var t in m_transitions.Select(t => new AutomatonTransition(statesMap[t.s1],statesMap[t.s2],alphabetMap[t.edge])).Distinct())
223 foreach (var t in m_transitions.Select(t => new AutomatonTransition(statesMap[t.s1],statesMap[t.s2],alphabetMap[t.edge])).Distinct())
224 optimalDFA.DefineTransition(t.s1, t.s2, t.edge);
224 optimalDFA.DefineTransition(t.s1, t.s2, t.edge);
225
225
226 }
226 }
227
227
228 protected void PrintDFA<TInput, TState>(IAlphabet<TInput> inputAlphabet, IAlphabet<TState> stateAlphabet) {
228 protected void PrintDFA<TInput, TState>(IAlphabet<TInput> inputAlphabet, IAlphabet<TState> stateAlphabet) {
229 Safe.ArgumentNotNull(inputAlphabet, "inputAlphabet");
229 Safe.ArgumentNotNull(inputAlphabet, "inputAlphabet");
230 Safe.ArgumentNotNull(stateAlphabet, "stateAlphabet");
230 Safe.ArgumentNotNull(stateAlphabet, "stateAlphabet");
231
231
232 var inputMap = inputAlphabet.CreateReverseMap();
232 var inputMap = inputAlphabet.CreateReverseMap();
233 var stateMap = stateAlphabet.CreateReverseMap();
233 var stateMap = stateAlphabet.CreateReverseMap();
234
234
235 for (int i = 0; i < inputMap.Length; i++)
235 for (int i = 0; i < inputMap.Length; i++)
236 Console.WriteLine("C{0}: {1}", i, String.Join(",", inputMap[i]));
236 Console.WriteLine("C{0}: {1}", i, String.Join(",", inputMap[i]));
237
237
238
238
239 foreach(var t in m_transitions)
239 foreach(var t in m_transitions)
240 Console.WriteLine(
240 Console.WriteLine(
241 "[{0}] -{{{1}}}-> [{2}]{3}",
241 "[{0}] -{{{1}}}-> [{2}]{3}",
242 stateMap[t.s1],
242 stateMap[t.s1],
243 String.Join(",", inputMap[t.edge]),
243 String.Join(",", inputMap[t.edge]),
244 stateMap[t.s2],
244 stateMap[t.s2],
245 m_finalStates.ContainsKey(t.s2) ? "$" : ""
245 m_finalStates.ContainsKey(t.s2) ? "$" : ""
246 );
246 );
247
247
248 }
248 }
249
249
250 }
250 }
251 }
251 }
@@ -1,95 +1,91
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 using System.Text;
6 using System.Threading.Tasks;
7
5
8 namespace Implab.Automaton.RegularExpressions {
6 namespace Implab.Automaton.RegularExpressions {
9 /// <summary>
7 /// <summary>
10 /// Базовый абстрактный класс. Грамматика, позволяет формулировать выражения над алфавитом типа <c>char</c>.
8 /// Базовый абстрактный класс. Грамматика, позволяет формулировать выражения над алфавитом типа <c>char</c>.
11 /// </summary>
9 /// </summary>
12 public abstract class Grammar<TSymbol, TTag> {
10 public abstract class Grammar<TSymbol, TTag> {
13
11
14 public abstract IAlphabetBuilder<TSymbol> Alphabet {
12 protected abstract IAlphabetBuilder<TSymbol> AlphabetBuilder {
15 get;
13 get;
16 }
14 }
17
15
18 public SymbolToken<TTag> UnclassifiedToken() {
16 protected SymbolToken<TTag> UnclassifiedToken() {
19 return new SymbolToken<TTag>(DFAConst.UNCLASSIFIED_INPUT);
17 return new SymbolToken<TTag>(DFAConst.UNCLASSIFIED_INPUT);
20 }
18 }
21
19
22 public void DefineAlphabet(IEnumerable<TSymbol> alphabet) {
20 protected void DefineAlphabet(IEnumerable<TSymbol> alphabet) {
23 Safe.ArgumentNotNull(alphabet, "alphabet");
21 Safe.ArgumentNotNull(alphabet, "alphabet");
24
22
25 foreach (var ch in alphabet)
23 foreach (var ch in alphabet)
26 Alphabet.DefineSymbol(ch);
24 AlphabetBuilder.DefineSymbol(ch);
27 }
25 }
28
26
29 public Token<TTag> SymbolToken(TSymbol symbol) {
27 protected Token<TTag> SymbolToken(TSymbol symbol) {
30 return Token<TTag>.New(TranslateOrAdd(symbol));
28 return Token<TTag>.New(TranslateOrAdd(symbol));
31 }
29 }
32
30
33 public Token<TTag> SymbolToken(IEnumerable<TSymbol> symbols) {
31 protected Token<TTag> SymbolToken(IEnumerable<TSymbol> symbols) {
34 Safe.ArgumentNotNull(symbols, "symbols");
32 Safe.ArgumentNotNull(symbols, "symbols");
35
33
36 return Token<TTag>.New(TranslateOrAdd(symbols).ToArray());
34 return Token<TTag>.New(TranslateOrAdd(symbols).ToArray());
37 }
35 }
38
36
39 public Token<TTag> SymbolSetToken(params TSymbol[] set) {
37 protected Token<TTag> SymbolSetToken(params TSymbol[] set) {
40 return SymbolToken(set);
38 return SymbolToken(set);
41 }
39 }
42
40
43 int TranslateOrAdd(TSymbol ch) {
41 int TranslateOrAdd(TSymbol ch) {
44 var t = Alphabet.Translate(ch);
42 var t = AlphabetBuilder.Translate(ch);
45 if (t == DFAConst.UNCLASSIFIED_INPUT)
43 if (t == DFAConst.UNCLASSIFIED_INPUT)
46 t = Alphabet.DefineSymbol(ch);
44 t = AlphabetBuilder.DefineSymbol(ch);
47 return t;
45 return t;
48 }
46 }
49
47
50 IEnumerable<int> TranslateOrAdd(IEnumerable<TSymbol> symbols) {
48 IEnumerable<int> TranslateOrAdd(IEnumerable<TSymbol> symbols) {
51 return symbols.Distinct().Select(TranslateOrAdd);
49 return symbols.Distinct().Select(TranslateOrAdd);
52 }
50 }
53
51
54 int TranslateOrDie(TSymbol ch) {
52 int TranslateOrDie(TSymbol ch) {
55 var t = Alphabet.Translate(ch);
53 var t = AlphabetBuilder.Translate(ch);
56 if (t == DFAConst.UNCLASSIFIED_INPUT)
54 if (t == DFAConst.UNCLASSIFIED_INPUT)
57 throw new ApplicationException(String.Format("Symbol '{0}' is UNCLASSIFIED", ch));
55 throw new ApplicationException(String.Format("Symbol '{0}' is UNCLASSIFIED", ch));
58 return t;
56 return t;
59 }
57 }
60
58
61 IEnumerable<int> TranslateOrDie(IEnumerable<TSymbol> symbols) {
59 IEnumerable<int> TranslateOrDie(IEnumerable<TSymbol> symbols) {
62 return symbols.Distinct().Select(TranslateOrDie);
60 return symbols.Distinct().Select(TranslateOrDie);
63 }
61 }
64
62
65 public Token<TTag> SymbolTokenExcept(IEnumerable<TSymbol> symbols) {
63 protected Token<TTag> SymbolTokenExcept(IEnumerable<TSymbol> symbols) {
66 Safe.ArgumentNotNull(symbols, "symbols");
64 Safe.ArgumentNotNull(symbols, "symbols");
67
65
68 return Token<TTag>.New( Enumerable.Range(0, Alphabet.Count).Except(TranslateOrDie(symbols)).ToArray() );
66 return Token<TTag>.New( Enumerable.Range(0, AlphabetBuilder.Count).Except(TranslateOrDie(symbols)).ToArray() );
69 }
67 }
70
68
71 protected CDFADefinition BuildDFA(Token<TTag> lang) {
69 protected void BuildDFA(Token<TTag> lang, IDFATableBuilder<TTag> dfaTable, IAlphabetBuilder<TSymbol> dfaAlphabet) {
72 Safe.ArgumentNotNull(lang, "lang");
70 Safe.ArgumentNotNull(lang, "lang");
71 Safe.ArgumentNotNull(dfaAlphabet, "dfaAlphabet");
73
72
74 var dfa = new RegularDFADefinition<TSymbol, TTag>(Alphabet, 0);
73 var dfa = new RegularDFADefinition<TSymbol, TTag>(AlphabetBuilder);
75
76 var table = new DFATransitionTable<TTag>();
77
74
78 var builder = new RegularDFABuilder<TTag>();
75 var builder = new RegularDFABuilder<TTag>();
79
76
80 lang.Accept( builder );
77 lang.Accept( builder );
81
78
82 var initialState = builder.BuildDFA(table);
79 builder.BuildDFA(dfa);
83 if (table.IsFinalState(initialState))
80
81 if (dfa.IsFinalState(dfa.InitialState))
84 throw new ApplicationException("The specified language contains empty token");
82 throw new ApplicationException("The specified language contains empty token");
85
83
86 return dfa.Optimize();
84 dfa.Optimize(dfaTable, dfaAlphabet);
85
87 }
86 }
88
87
89
90
91 //protected abstract TGrammar CreateInstance();
92 }
88 }
93
89
94
90
95 }
91 }
@@ -1,180 +1,180
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.RegularExpressions {
7 namespace Implab.Automaton.RegularExpressions {
8 /// <summary>
8 /// <summary>
9 /// Используется для построения ДКА по регулярному выражению, сначала обходит
9 /// Используется для построения ДКА по регулярному выражению, сначала обходит
10 /// регулярное выражение и вычисляет followpos, затем используется метод
10 /// регулярное выражение и вычисляет followpos, затем используется метод
11 /// <see cref="BuildDFA(IDFADefinition)"/> для построения автомата.
11 /// <see cref="BuildDFA(IDFADefinition)"/> для построения автомата.
12 /// </summary>
12 /// </summary>
13 public class RegularDFABuilder<TTag> : IVisitor<TTag> {
13 public class RegularDFABuilder<TTag> : IVisitor<TTag> {
14 int m_idx = 0;
14 int m_idx;
15 Token<TTag> m_root;
15 Token<TTag> m_root;
16 HashSet<int> m_firstpos;
16 HashSet<int> m_firstpos;
17 HashSet<int> m_lastpos;
17 HashSet<int> m_lastpos;
18
18
19 readonly Dictionary<int, HashSet<int>> m_followpos = new Dictionary<int, HashSet<int>>();
19 readonly Dictionary<int, HashSet<int>> m_followpos = new Dictionary<int, HashSet<int>>();
20 readonly Dictionary<int, int> m_indexes = new Dictionary<int, int>();
20 readonly Dictionary<int, int> m_indexes = new Dictionary<int, int>();
21 readonly Dictionary<int, TTag> m_ends = new Dictionary<int, TTag>();
21 readonly Dictionary<int, TTag> m_ends = new Dictionary<int, TTag>();
22
22
23 public Dictionary<int, HashSet<int>> FollowposMap {
23 public Dictionary<int, HashSet<int>> FollowposMap {
24 get { return m_followpos; }
24 get { return m_followpos; }
25 }
25 }
26
26
27 public HashSet<int> Followpos(int pos) {
27 public HashSet<int> Followpos(int pos) {
28 HashSet<int> set;
28 HashSet<int> set;
29 if (m_followpos.TryGetValue(pos, out set))
29 return m_followpos.TryGetValue(pos, out set) ? set : m_followpos[pos] = new HashSet<int>();
30 return set;
31 return m_followpos[pos] = new HashSet<int>();
32 }
30 }
33
31
34 bool Nullable(object n) {
32 bool Nullable(object n) {
35 if (n is EmptyToken<TTag> || n is StarToken<TTag>)
33 if (n is EmptyToken<TTag> || n is StarToken<TTag>)
36 return true;
34 return true;
37 if (n is AltToken<TTag>)
35 var altToken = n as AltToken<TTag>;
38 return Nullable(((AltToken<TTag>)n).Left) || Nullable(((AltToken<TTag>)n).Right);
36 if (altToken != null)
39 if (n is CatToken<TTag>)
37 return Nullable(altToken.Left) || Nullable(altToken.Right);
40 return Nullable(((CatToken<TTag>)n).Left) && Nullable(((CatToken<TTag>)n).Right);
38 var catToken = n as CatToken<TTag>;
39 if (catToken != null)
40 return Nullable(catToken.Left) && Nullable(catToken.Right);
41 return false;
41 return false;
42 }
42 }
43
43
44
44
45 public void Visit(AltToken<TTag> token) {
45 public void Visit(AltToken<TTag> token) {
46 if (m_root == null)
46 if (m_root == null)
47 m_root = token;
47 m_root = token;
48 var firtspos = new HashSet<int>();
48 var firtspos = new HashSet<int>();
49 var lastpos = new HashSet<int>();
49 var lastpos = new HashSet<int>();
50
50
51 token.Left.Accept(this);
51 token.Left.Accept(this);
52 firtspos.UnionWith(m_firstpos);
52 firtspos.UnionWith(m_firstpos);
53 lastpos.UnionWith(m_lastpos);
53 lastpos.UnionWith(m_lastpos);
54
54
55 token.Right.Accept(this);
55 token.Right.Accept(this);
56 firtspos.UnionWith(m_firstpos);
56 firtspos.UnionWith(m_firstpos);
57 lastpos.UnionWith(m_lastpos);
57 lastpos.UnionWith(m_lastpos);
58
58
59 m_firstpos = firtspos;
59 m_firstpos = firtspos;
60 m_lastpos = lastpos;
60 m_lastpos = lastpos;
61 }
61 }
62
62
63 public void Visit(StarToken<TTag> token) {
63 public void Visit(StarToken<TTag> token) {
64 if (m_root == null)
64 if (m_root == null)
65 m_root = token;
65 m_root = token;
66 token.Token.Accept(this);
66 token.Token.Accept(this);
67
67
68 foreach (var i in m_lastpos)
68 foreach (var i in m_lastpos)
69 Followpos(i).UnionWith(m_firstpos);
69 Followpos(i).UnionWith(m_firstpos);
70 }
70 }
71
71
72 public void Visit(CatToken<TTag> token) {
72 public void Visit(CatToken<TTag> token) {
73 if (m_root == null)
73 if (m_root == null)
74 m_root = token;
74 m_root = token;
75
75
76 var firtspos = new HashSet<int>();
76 var firtspos = new HashSet<int>();
77 var lastpos = new HashSet<int>();
77 var lastpos = new HashSet<int>();
78 token.Left.Accept(this);
78 token.Left.Accept(this);
79 firtspos.UnionWith(m_firstpos);
79 firtspos.UnionWith(m_firstpos);
80 var leftLastpos = m_lastpos;
80 var leftLastpos = m_lastpos;
81
81
82 token.Right.Accept(this);
82 token.Right.Accept(this);
83 lastpos.UnionWith(m_lastpos);
83 lastpos.UnionWith(m_lastpos);
84 var rightFirstpos = m_firstpos;
84 var rightFirstpos = m_firstpos;
85
85
86 if (Nullable(token.Left))
86 if (Nullable(token.Left))
87 firtspos.UnionWith(rightFirstpos);
87 firtspos.UnionWith(rightFirstpos);
88
88
89 if (Nullable(token.Right))
89 if (Nullable(token.Right))
90 lastpos.UnionWith(leftLastpos);
90 lastpos.UnionWith(leftLastpos);
91
91
92 m_firstpos = firtspos;
92 m_firstpos = firtspos;
93 m_lastpos = lastpos;
93 m_lastpos = lastpos;
94
94
95 foreach (var i in leftLastpos)
95 foreach (var i in leftLastpos)
96 Followpos(i).UnionWith(rightFirstpos);
96 Followpos(i).UnionWith(rightFirstpos);
97
97
98 }
98 }
99
99
100 public void Visit(EmptyToken<TTag> token) {
100 public void Visit(EmptyToken<TTag> token) {
101 if (m_root == null)
101 if (m_root == null)
102 m_root = token;
102 m_root = token;
103 }
103 }
104
104
105 public void Visit(SymbolToken<TTag> token) {
105 public void Visit(SymbolToken<TTag> token) {
106 if (m_root == null)
106 if (m_root == null)
107 m_root = token;
107 m_root = token;
108 m_idx++;
108 m_idx++;
109 m_indexes[m_idx] = token.Value;
109 m_indexes[m_idx] = token.Value;
110 m_firstpos = new HashSet<int>(new[] { m_idx });
110 m_firstpos = new HashSet<int>(new[] { m_idx });
111 m_lastpos = new HashSet<int>(new[] { m_idx });
111 m_lastpos = new HashSet<int>(new[] { m_idx });
112 }
112 }
113
113
114 public void Visit(EndToken<TTag> token) {
114 public void Visit(EndToken<TTag> token) {
115 if (m_root == null)
115 if (m_root == null)
116 m_root = token;
116 m_root = token;
117 m_idx++;
117 m_idx++;
118 m_indexes[m_idx] = DFAConst.UNCLASSIFIED_INPUT;
118 m_indexes[m_idx] = DFAConst.UNCLASSIFIED_INPUT;
119 m_firstpos = new HashSet<int>(new[] { m_idx });
119 m_firstpos = new HashSet<int>(new[] { m_idx });
120 m_lastpos = new HashSet<int>(new[] { m_idx });
120 m_lastpos = new HashSet<int>(new[] { m_idx });
121 Followpos(m_idx);
121 Followpos(m_idx);
122 m_ends.Add(m_idx, token.Tag);
122 m_ends.Add(m_idx, token.Tag);
123 }
123 }
124
124
125 public void BuildDFA(IDFATransitionTableBuilder<TTag> dfa) {
125 public void BuildDFA(IDFATableBuilder<TTag> dfa) {
126 Safe.ArgumentNotNull(dfa,"dfa");
126 Safe.ArgumentNotNull(dfa,"dfa");
127
127
128 var states = new MapAlphabet<HashSet<int>>(new CustomEqualityComparer<HashSet<int>>(
128 var states = new MapAlphabet<HashSet<int>>(new CustomEqualityComparer<HashSet<int>>(
129 (x, y) => x.SetEquals(y),
129 (x, y) => x.SetEquals(y),
130 x => x.Sum(n => n.GetHashCode())
130 x => x.Sum(n => n.GetHashCode())
131 ));
131 ));
132
132
133 var initialState = states.DefineSymbol(m_firstpos);
133 var initialState = states.DefineSymbol(m_firstpos);
134 dfa.SetInitialState(initialState);
134 dfa.SetInitialState(initialState);
135
135
136 var tags = GetStateTags(m_firstpos);
136 var tags = GetStateTags(m_firstpos);
137 if (tags != null && tags.Length > 0)
137 if (tags != null && tags.Length > 0)
138 dfa.MarkFinalState(initialState, tags);
138 dfa.MarkFinalState(initialState, tags);
139
139
140 var inputMax = m_indexes.Values.Max();
140 var inputMax = m_indexes.Values.Max();
141 var queue = new Queue<HashSet<int>>();
141 var queue = new Queue<HashSet<int>>();
142
142
143 queue.Enqueue(m_firstpos);
143 queue.Enqueue(m_firstpos);
144
144
145 while (queue.Count > 0) {
145 while (queue.Count > 0) {
146 var state = queue.Dequeue();
146 var state = queue.Dequeue();
147 var s1 = states.Translate(state);
147 var s1 = states.Translate(state);
148 Debug.Assert(s1 != DFAConst.UNCLASSIFIED_INPUT);
148 Debug.Assert(s1 != DFAConst.UNCLASSIFIED_INPUT);
149
149
150 for (int a = 0; a <= inputMax; a++) {
150 for (int a = 0; a <= inputMax; a++) {
151 var next = new HashSet<int>();
151 var next = new HashSet<int>();
152 foreach (var p in state) {
152 foreach (var p in state) {
153 if (m_indexes[p] == a) {
153 if (m_indexes[p] == a) {
154 next.UnionWith(Followpos(p));
154 next.UnionWith(Followpos(p));
155 }
155 }
156 }
156 }
157 if (next.Count > 0) {
157 if (next.Count > 0) {
158 int s2 = states.Translate(next);
158 int s2 = states.Translate(next);
159 if (s2 == DFAConst.UNCLASSIFIED_INPUT) {
159 if (s2 == DFAConst.UNCLASSIFIED_INPUT) {
160 s2 = states.DefineSymbol(next);
160 s2 = states.DefineSymbol(next);
161
161
162 tags = GetStateTags(next);
162 tags = GetStateTags(next);
163 if (tags != null && tags.Length > 0)
163 if (tags != null && tags.Length > 0)
164 dfa.MarkFinalState(s2, tags);
164 dfa.MarkFinalState(s2, tags);
165
165
166 queue.Enqueue(next);
166 queue.Enqueue(next);
167 }
167 }
168 dfa.DefineTransition(s1, s2, a);
168 dfa.DefineTransition(s1, s2, a);
169 }
169 }
170 }
170 }
171 }
171 }
172 }
172 }
173
173
174 TTag[] GetStateTags(IEnumerable<int> state) {
174 TTag[] GetStateTags(IEnumerable<int> state) {
175 Debug.Assert(state != null);
175 Debug.Assert(state != null);
176 return state.Where(m_ends.ContainsKey).Select(pos => m_ends[pos]).ToArray();
176 return state.Where(m_ends.ContainsKey).Select(pos => m_ends[pos]).ToArray();
177 }
177 }
178
178
179 }
179 }
180 }
180 }
@@ -1,46 +1,43
1 using System;
1 using System;
2
2
3 namespace Implab.Automaton.RegularExpressions {
3 namespace Implab.Automaton.RegularExpressions {
4 public class RegularDFADefinition<TInput, TTag> : DFATransitionTable<TTag>, IDFATransitionTable<TTag> {
4 public class RegularDFADefinition<TInput, TTag> : DFATransitionTable<TTag>, IDFATransitionTable<TTag> {
5
5
6 readonly IAlphabet<TInput> m_alphabet;
6 readonly IAlphabet<TInput> m_alphabet;
7 readonly int m_initialState;
8
7
9 public RegularDFADefinition(IAlphabet<TInput> alphabet, int initialState) {
8 public RegularDFADefinition(IAlphabet<TInput> alphabet) {
10 Safe.ArgumentNotNull(alphabet, "aplhabet");
9 Safe.ArgumentNotNull(alphabet, "aplhabet");
11
10
12 m_alphabet = alphabet;
11 m_alphabet = alphabet;
13 m_initialState = initialState;
14 }
12 }
15
13
16
14
17 public IAlphabet<TInput> InputAlphabet {
15 public IAlphabet<TInput> InputAlphabet {
18 get {
16 get {
19 return m_alphabet;
17 return m_alphabet;
20 }
18 }
21 }
19 }
22
20
23 protected override DFAStateDescriptior<TTag>[] ConstructTransitionTable() {
21 protected override DFAStateDescriptior<TTag>[] ConstructTransitionTable() {
24 if (InputAlphabet.Count != m_alphabet.Count)
22 if (InputAlphabet.Count != m_alphabet.Count)
25 throw new InvalidOperationException("The alphabet doesn't match the transition table");
23 throw new InvalidOperationException("The alphabet doesn't match the transition table");
26
24
27 return base.ConstructTransitionTable();
25 return base.ConstructTransitionTable();
28 }
26 }
29
27
30 /// <summary>
28 /// <summary>
31 /// Optimize the specified alphabet.
29 /// Optimize the specified alphabet.
32 /// </summary>
30 /// </summary>
31 /// <param name = "dfaTable"></param>
33 /// <param name="alphabet">Пустой алфавит, который будет зполнен в процессе оптимизации.</param>
32 /// <param name="alphabet">Пустой алфавит, который будет зполнен в процессе оптимизации.</param>
34 public RegularDFADefinition<TInput, TTag> Optimize(IAlphabetBuilder<TInput> alphabet) {
33 public void Optimize(IDFATableBuilder<TTag> dfaTable, IAlphabetBuilder<TInput> alphabet) {
35 Safe.ArgumentNotNull(alphabet, "alphabet");
34 Safe.ArgumentNotNull(alphabet, "alphabet");
35 Safe.ArgumentNotNull(dfaTable, "dfaTable");
36
36
37 var optimalDFA = new RegularDFADefinition<TInput,TTag>(alphabet, m_initialState);
37 Optimize(dfaTable, InputAlphabet, alphabet, new DummyAlphabet(StateCount), new MapAlphabet<int>());
38
39 Optimize(optimalDFA, InputAlphabet, alphabet, new DummyAlphabet(StateCount), new MapAlphabet<int>());
40
41 }
38 }
42
39
43
40
44 }
41 }
45 }
42 }
46
43
@@ -1,63 +1,63
1 using Implab;
1 using Implab;
2 using System;
2 using System;
3 using System.Linq;
3 using System.Linq;
4
4
5 namespace Implab.Automaton.RegularExpressions {
5 namespace Implab.Automaton.RegularExpressions {
6 public abstract class Token<TTag> {
6 public abstract class Token<TTag> {
7 public abstract void Accept(IVisitor<TTag> visitor);
7 public abstract void Accept(IVisitor<TTag> visitor);
8
8
9 public Token<TTag> Extend() {
9 public Token<TTag> Extend() {
10 return Cat(new EndToken<TTag>());
10 return Cat(new EndToken<TTag>());
11 }
11 }
12
12
13 public Token<TTag> Tag<T>(T tag) where T : IConvertible {
13 public Token<TTag> Tag(TTag tag) {
14 return Cat(new EndToken<TTag>(tag));
14 return Cat(new EndToken<TTag>(tag));
15 }
15 }
16
16
17 public Token<TTag> Cat(Token<TTag> right) {
17 public Token<TTag> Cat(Token<TTag> right) {
18 return new CatToken<TTag>(this, right);
18 return new CatToken<TTag>(this, right);
19 }
19 }
20
20
21 public Token<TTag> Or(Token<TTag> right) {
21 public Token<TTag> Or(Token<TTag> right) {
22 return new AltToken<TTag>(this, right);
22 return new AltToken<TTag>(this, right);
23 }
23 }
24
24
25 public Token<TTag> Optional() {
25 public Token<TTag> Optional() {
26 return Or(new EmptyToken<TTag>());
26 return Or(new EmptyToken<TTag>());
27 }
27 }
28
28
29 public Token<TTag> EClosure() {
29 public Token<TTag> EClosure() {
30 return new StarToken<TTag>(this);
30 return new StarToken<TTag>(this);
31 }
31 }
32
32
33 public Token<TTag> Closure() {
33 public Token<TTag> Closure() {
34 return Cat(new StarToken<TTag>(this));
34 return Cat(new StarToken<TTag>(this));
35 }
35 }
36
36
37 public Token<TTag> Repeat(int count) {
37 public Token<TTag> Repeat(int count) {
38 Token<TTag> token = null;
38 Token<TTag> token = null;
39
39
40 for (int i = 0; i < count; i++)
40 for (int i = 0; i < count; i++)
41 token = token != null ? token.Cat(this) : this;
41 token = token != null ? token.Cat(this) : this;
42 return token ?? new EmptyToken<TTag>();
42 return token ?? new EmptyToken<TTag>();
43 }
43 }
44
44
45 public Token<TTag> Repeat(int min, int max) {
45 public Token<TTag> Repeat(int min, int max) {
46 if (min > max || min < 1)
46 if (min > max || min < 1)
47 throw new ArgumentOutOfRangeException();
47 throw new ArgumentOutOfRangeException();
48 var token = Repeat(min);
48 var token = Repeat(min);
49
49
50 for (int i = min; i < max; i++)
50 for (int i = min; i < max; i++)
51 token = token.Cat( this.Optional() );
51 token = token.Cat( Optional() );
52 return token;
52 return token;
53 }
53 }
54
54
55 public static Token<TTag> New<T>(params T[] set) where T : struct, IConvertible {
55 public static Token<TTag> New(params int[] set) {
56 Safe.ArgumentNotNull(set, "set");
56 Safe.ArgumentNotNull(set, "set");
57 Token<TTag> token = null;
57 Token<TTag> token = null;
58 foreach(var c in set.Distinct())
58 foreach(var c in set.Distinct())
59 token = token == null ? new SymbolToken<TTag>(c) : token.Or(new SymbolToken<TTag>(c));
59 token = token == null ? new SymbolToken<TTag>(c) : token.Or(new SymbolToken<TTag>(c));
60 return token;
60 return token;
61 }
61 }
62 }
62 }
63 }
63 }
@@ -1,265 +1,265
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.IO;
4 using System.IO;
5 using Implab.Components;
5 using Implab.Components;
6
6
7 namespace Implab.Automaton {
7 namespace Implab.Automaton {
8 /// <summary>
8 /// <summary>
9 /// Базовый класс для разбора потока входных символов на токены.
9 /// Базовый класс для разбора потока входных символов на токены.
10 /// </summary>
10 /// </summary>
11 /// <remarks>
11 /// <remarks>
12 /// Сканнер имеет внутри буффер с симолами входного текста, по которому перемещаются два
12 /// Сканнер имеет внутри буффер с симолами входного текста, по которому перемещаются два
13 /// указателя, начала и конца токена, при перемещении искользуется ДКА для определения
13 /// указателя, начала и конца токена, при перемещении искользуется ДКА для определения
14 /// конца токена и допустимости текущего символа.
14 /// конца токена и допустимости текущего символа.
15 /// </remarks>
15 /// </remarks>
16 public abstract class Scanner<TTag> : Disposable {
16 public abstract class Scanner<TTag> : Disposable {
17 struct ScannerConfig {
17 struct ScannerConfig {
18 public DFAStateDescriptior<TTag>[] states;
18 public DFAStateDescriptior<TTag>[] states;
19 public int[] alphabetMap;
19 public int[] alphabetMap;
20 public int initialState;
20 public int initialState;
21 }
21 }
22
22
23 Stack<ScannerConfig> m_defs = new Stack<ScannerConfig>();
23 Stack<ScannerConfig> m_defs = new Stack<ScannerConfig>();
24
24
25 DFAStateDescriptior<TTag>[] m_states;
25 DFAStateDescriptior<TTag>[] m_states;
26 int[] m_alphabetMap;
26 int[] m_alphabetMap;
27 int m_initialState;
27 int m_initialState;
28
28
29 protected DFAStateDescriptior<TTag> m_currentState;
29 protected DFAStateDescriptior<TTag> m_currentState;
30 int m_previewCode;
30 int m_previewCode;
31
31
32 protected int m_tokenLen = 0;
32 protected int m_tokenLen;
33 protected int m_tokenOffset;
33 protected int m_tokenOffset;
34
34
35 protected char[] m_buffer;
35 protected char[] m_buffer;
36 protected int m_bufferSize;
36 protected int m_bufferSize;
37 protected int m_pointer;
37 protected int m_pointer;
38
38
39 TextReader m_reader;
39 TextReader m_reader;
40 bool m_disposeReader;
40 bool m_disposeReader;
41 int m_chunkSize = 1024; // 1k
41 int m_chunkSize = 1024; // 1k
42 int m_limit = 10 * 1024 * 1024; // 10Mb
42 int m_limit = 10 * 1024 * 1024; // 10Mb
43
43
44 protected Scanner(DFAStateDescriptior<TTag>[] states, int[] alphabet, int initialState) {
44 protected Scanner(DFAStateDescriptior<TTag>[] states, int[] alphabet, int initialState) {
45 Safe.ArgumentNotEmpty(states, "states");
45 Safe.ArgumentNotEmpty(states, "states");
46 Safe.ArgumentNotNull(alphabet, "alphabet");
46 Safe.ArgumentNotNull(alphabet, "alphabet");
47
47
48 m_states = states;
48 m_states = states;
49 m_alphabetMap = alphabet;
49 m_alphabetMap = alphabet;
50 m_initialState = initialState;
50 m_initialState = initialState;
51
51
52 Feed(new char[0]);
52 Feed(new char[0]);
53 }
53 }
54
54
55 /// <summary>
55 /// <summary>
56 /// Заполняет входными данными буффер.
56 /// Заполняет входными данными буффер.
57 /// </summary>
57 /// </summary>
58 /// <param name="data">Данные для обработки.</param>
58 /// <param name="data">Данные для обработки.</param>
59 /// <remarks>Копирование данных не происходит, переданный массив используется в
59 /// <remarks>Копирование данных не происходит, переданный массив используется в
60 /// качестве входного буффера.</remarks>
60 /// качестве входного буффера.</remarks>
61 public void Feed(char[] data) {
61 public void Feed(char[] data) {
62 Safe.ArgumentNotNull(data, "data");
62 Safe.ArgumentNotNull(data, "data");
63
63
64 Feed(data, data.Length);
64 Feed(data, data.Length);
65 }
65 }
66
66
67 /// <summary>
67 /// <summary>
68 /// Заполняет буффур чтения входными данными.
68 /// Заполняет буффур чтения входными данными.
69 /// </summary>
69 /// </summary>
70 /// <param name="data">Данные для обработки.</param>
70 /// <param name="data">Данные для обработки.</param>
71 /// <param name="length">Длина данных для обработки.</param>
71 /// <param name="length">Длина данных для обработки.</param>
72 /// <remarks>Копирование данных не происходит, переданный массив используется в
72 /// <remarks>Копирование данных не происходит, переданный массив используется в
73 /// качестве входного буффера.</remarks>
73 /// качестве входного буффера.</remarks>
74 public void Feed(char[] data, int length) {
74 public void Feed(char[] data, int length) {
75 Safe.ArgumentNotNull(data, "data");
75 Safe.ArgumentNotNull(data, "data");
76 Safe.ArgumentInRange(length, 0, data.Length, "length");
76 Safe.ArgumentInRange(length, 0, data.Length, "length");
77 AssertNotDisposed();
77 AssertNotDisposed();
78
78
79 m_pointer = -1;
79 m_pointer = -1;
80 m_buffer = data;
80 m_buffer = data;
81 m_bufferSize = length;
81 m_bufferSize = length;
82 Shift();
82 Shift();
83 }
83 }
84
84
85 public void Feed(TextReader reader, bool dispose) {
85 public void Feed(TextReader reader, bool dispose) {
86 Safe.ArgumentNotNull(reader, "reader");
86 Safe.ArgumentNotNull(reader, "reader");
87 AssertNotDisposed();
87 AssertNotDisposed();
88
88
89 if (m_reader != null && m_disposeReader)
89 if (m_reader != null && m_disposeReader)
90 m_reader.Dispose();
90 m_reader.Dispose();
91
91
92 m_reader = reader;
92 m_reader = reader;
93 m_disposeReader = dispose;
93 m_disposeReader = dispose;
94 m_pointer = -1;
94 m_pointer = -1;
95 m_buffer = new char[m_chunkSize];
95 m_buffer = new char[m_chunkSize];
96 m_bufferSize = 0;
96 m_bufferSize = 0;
97 Shift();
97 Shift();
98 }
98 }
99
99
100 /// <summary>
100 /// <summary>
101 /// Получает текущий токен в виде строки.
101 /// Получает текущий токен в виде строки.
102 /// </summary>
102 /// </summary>
103 /// <returns></returns>
103 /// <returns></returns>
104 protected string GetTokenValue() {
104 protected string GetTokenValue() {
105 return new String(m_buffer, m_tokenOffset, m_tokenLen);
105 return new String(m_buffer, m_tokenOffset, m_tokenLen);
106 }
106 }
107
107
108 /// <summary>
108 /// <summary>
109 /// Метки текущего токена, которые были назначены в регулярном выражении.
109 /// Метки текущего токена, которые были назначены в регулярном выражении.
110 /// </summary>
110 /// </summary>
111 protected TTag[] TokenTags {
111 protected TTag[] TokenTags {
112 get {
112 get {
113 return m_currentState.tag;
113 return m_currentState.tag;
114 }
114 }
115 }
115 }
116
116
117 /// <summary>
117 /// <summary>
118 /// Признак конца данных
118 /// Признак конца данных
119 /// </summary>
119 /// </summary>
120 public bool EOF {
120 public bool EOF {
121 get {
121 get {
122 return m_pointer >= m_bufferSize;
122 return m_pointer >= m_bufferSize;
123 }
123 }
124 }
124 }
125
125
126 /// <summary>
126 /// <summary>
127 /// Читает следующий токен, при этом <see cref="m_tokenOffset"/> указывает на начало токена,
127 /// Читает следующий токен, при этом <see cref="m_tokenOffset"/> указывает на начало токена,
128 /// <see cref="m_tokenLen"/> на длину токена, <see cref="m_buffer"/> - массив символов, в
128 /// <see cref="m_tokenLen"/> на длину токена, <see cref="m_buffer"/> - массив символов, в
129 /// котором находится токен.
129 /// котором находится токен.
130 /// </summary>
130 /// </summary>
131 /// <returns><c>false</c> - достигнут конец данных, токен не прочитан.</returns>
131 /// <returns><c>false</c> - достигнут конец данных, токен не прочитан.</returns>
132 protected bool ReadTokenInternal() {
132 protected bool ReadTokenInternal() {
133 if (m_pointer >= m_bufferSize)
133 if (m_pointer >= m_bufferSize)
134 return false;
134 return false;
135
135
136 m_currentState = m_states[m_initialState];
136 m_currentState = m_states[m_initialState];
137 m_tokenLen = 0;
137 m_tokenLen = 0;
138 m_tokenOffset = m_pointer;
138 m_tokenOffset = m_pointer;
139 int nextState;
139 int nextState;
140 do {
140 do {
141 nextState = m_currentState.transitions[m_previewCode];
141 nextState = m_currentState.transitions[m_previewCode];
142 if (nextState == DFAConst.UNREACHABLE_STATE) {
142 if (nextState == DFAConst.UNREACHABLE_STATE) {
143 if (m_currentState.final)
143 if (m_currentState.final)
144 return true;
144 return true;
145 else
145
146 throw new ParserException(
146 throw new ParserException(
147 String.Format(
147 String.Format(
148 "Unexpected symbol '{0}', at pos {1}",
148 "Unexpected symbol '{0}', at pos {1}",
149 m_buffer[m_pointer],
149 m_buffer[m_pointer],
150 Position
150 Position
151 )
151 )
152 );
152 );
153 } else {
153 }
154 m_currentState = m_states[nextState];
154 m_currentState = m_states[nextState];
155 m_tokenLen++;
155 m_tokenLen++;
156 }
157
156
158 } while (Shift());
157 } while (Shift());
159
158
160 // END OF DATA
159 // END OF DATA
161 if (!m_currentState.final)
160 if (!m_currentState.final)
162 throw new ParserException("Unexpected end of data");
161 throw new ParserException("Unexpected end of data");
163
162
164 return true;
163 return true;
165 }
164 }
166
165
167
166
168 bool Shift() {
167 bool Shift() {
169 m_pointer++;
168 m_pointer++;
170
169
171 if (m_pointer >= m_bufferSize) {
170 if (m_pointer >= m_bufferSize) {
172 if (!ReadNextChunk())
171 if (!ReadNextChunk())
173 return false;
172 return false;
174 }
173 }
175
174
176 m_previewCode = m_alphabetMap[m_buffer[m_pointer]];
175 m_previewCode = m_alphabetMap[m_buffer[m_pointer]];
177
176
178 return true;
177 return true;
179 }
178 }
180
179
181 bool ReadNextChunk() {
180 bool ReadNextChunk() {
182 if (m_reader == null)
181 if (m_reader == null)
183 return false;
182 return false;
184
183
185 // extend buffer if nesessary
184 // extend buffer if nesessary
186 if (m_pointer + m_chunkSize > m_buffer.Length) {
185 if (m_pointer + m_chunkSize > m_buffer.Length) {
187 // trim unused buffer head
186 // trim unused buffer head
188 var size = m_tokenLen + m_chunkSize;
187 var size = m_tokenLen + m_chunkSize;
189 if (size >= m_limit)
188 if (size >= m_limit)
190 throw new ParserException(String.Format("Input buffer {0} bytes limit exceeded", m_limit));
189 throw new ParserException(String.Format("Input buffer {0} bytes limit exceeded", m_limit));
191 var temp = new char[size];
190 var temp = new char[size];
192 Array.Copy(m_buffer, m_tokenOffset, temp, 0, m_tokenLen);
191 Array.Copy(m_buffer, m_tokenOffset, temp, 0, m_tokenLen);
193 m_pointer -= m_tokenOffset;
192 m_pointer -= m_tokenOffset;
194 m_bufferSize -= m_tokenOffset;
193 m_bufferSize -= m_tokenOffset;
195 m_tokenOffset = 0;
194 m_tokenOffset = 0;
196 m_buffer = temp;
195 m_buffer = temp;
197 }
196 }
198
197
199 var read = m_reader.Read(m_buffer, m_tokenLen, m_chunkSize);
198 var read = m_reader.Read(m_buffer, m_tokenLen, m_chunkSize);
200 if (read == 0)
199 if (read == 0)
201 return false;
200 return false;
202
201
203 m_bufferSize += read;
202 m_bufferSize += read;
204
203
205 return true;
204 return true;
206 }
205 }
207
206
208 /// <summary>
207 /// <summary>
209 /// Позиция сканнера во входном буфере
208 /// Позиция сканнера во входном буфере
210 /// </summary>
209 /// </summary>
211 public int Position {
210 public int Position {
212 get {
211 get {
213 return m_pointer + 1;
212 return m_pointer + 1;
214 }
213 }
215 }
214 }
216
215
217 /// <summary>
216 /// <summary>
218 /// Преключает внутренний ДКА на указанный, позволяет реализовать подобие захватывающей
217 /// Преключает внутренний ДКА на указанный, позволяет реализовать подобие захватывающей
219 /// группировки.
218 /// группировки.
220 /// </summary>
219 /// </summary>
221 /// <param name="states">Таблица состояний нового ДКА</param>
220 /// <param name="states">Таблица состояний нового ДКА</param>
222 /// <param name="alphabet">Таблица входных символов для нового ДКА</param>
221 /// <param name="alphabet">Таблица входных символов для нового ДКА</param>
222 /// <param name = "initialState"></param>
223 protected void Switch(DFAStateDescriptior<TTag>[] states, int[] alphabet, int initialState) {
223 protected void Switch(DFAStateDescriptior<TTag>[] states, int[] alphabet, int initialState) {
224 Safe.ArgumentNotNull(states, "dfa");
224 Safe.ArgumentNotNull(states, "dfa");
225
225
226 m_defs.Push(new ScannerConfig {
226 m_defs.Push(new ScannerConfig {
227 states = m_states,
227 states = m_states,
228 alphabetMap = m_alphabetMap,
228 alphabetMap = m_alphabetMap,
229 initialState = m_initialState
229 initialState = m_initialState
230 });
230 });
231
231
232 m_states = states;
232 m_states = states;
233 m_alphabetMap = alphabet;
233 m_alphabetMap = alphabet;
234 m_initialState = initialState;
234 m_initialState = initialState;
235
235
236 m_previewCode = m_alphabetMap[m_buffer[m_pointer]];
236 m_previewCode = m_alphabetMap[m_buffer[m_pointer]];
237 }
237 }
238
238
239 /// <summary>
239 /// <summary>
240 /// Восстанавливает предыдущей ДКА сканнера.
240 /// Восстанавливает предыдущей ДКА сканнера.
241 /// </summary>
241 /// </summary>
242 protected void Restore() {
242 protected void Restore() {
243 if (m_defs.Count == 0)
243 if (m_defs.Count == 0)
244 throw new InvalidOperationException();
244 throw new InvalidOperationException();
245 var prev = m_defs.Pop();
245 var prev = m_defs.Pop();
246 m_states = prev.states;
246 m_states = prev.states;
247 m_alphabetMap = prev.alphabetMap;
247 m_alphabetMap = prev.alphabetMap;
248 m_initialState = prev.initialState;
248 m_initialState = prev.initialState;
249 m_previewCode = m_alphabetMap[m_buffer[m_pointer]];
249 m_previewCode = m_alphabetMap[m_buffer[m_pointer]];
250 }
250 }
251
251
252 protected override void Dispose(bool disposing) {
252 protected override void Dispose(bool disposing) {
253 if (disposing) {
253 if (disposing) {
254 if (m_reader != null && m_disposeReader)
254 if (m_reader != null && m_disposeReader)
255 m_reader.Dispose();
255 m_reader.Dispose();
256 m_buffer = null;
256 m_buffer = null;
257 m_bufferSize = 0;
257 m_bufferSize = 0;
258 m_pointer = 0;
258 m_pointer = 0;
259 m_tokenLen = 0;
259 m_tokenLen = 0;
260 m_tokenOffset = 0;
260 m_tokenOffset = 0;
261 }
261 }
262 base.Dispose(disposing);
262 base.Dispose(disposing);
263 }
263 }
264 }
264 }
265 }
265 }
@@ -1,25 +1,25
1 using System;
1 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
2 using System.Linq;
3 using Implab.Automaton;
4
4
5 namespace Implab.Automaton {
5 namespace Implab.Formats {
6 public class ByteAlphabet : IndexedAlphabetBase<byte> {
6 public class ByteAlphabet : IndexedAlphabetBase<byte> {
7 public ByteAlphabet() : base(byte.MaxValue + 1){
7 public ByteAlphabet() : base(byte.MaxValue + 1){
8 }
8 }
9
9
10 #region implemented abstract members of IndexedAlphabetBase
10 #region implemented abstract members of IndexedAlphabetBase
11
11
12 public override int GetSymbolIndex(byte symbol) {
12 public override int GetSymbolIndex(byte symbol) {
13 return (int)symbol;
13 return (int)symbol;
14 }
14 }
15
15
16 public IEnumerable<byte> InputSymbols {
16 public IEnumerable<byte> InputSymbols {
17 get {
17 get {
18 return Enumerable.Range(byte.MinValue, byte.MaxValue).Cast<byte>();
18 return Enumerable.Range(byte.MinValue, byte.MaxValue).Cast<byte>();
19 }
19 }
20 }
20 }
21
21
22 #endregion
22 #endregion
23 }
23 }
24 }
24 }
25
25
@@ -1,23 +1,20
1 using Implab;
1 using System.Collections.Generic;
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
2 using System.Linq;
5 using System.Text;
3 using Implab.Automaton;
6 using System.Threading.Tasks;
7
4
8 namespace Implab.Automaton {
5 namespace Implab.Formats {
9 public class CharAlphabet: IndexedAlphabetBase<char> {
6 public class CharAlphabet: IndexedAlphabetBase<char> {
10
7
11 public CharAlphabet()
8 public CharAlphabet()
12 : base(char.MaxValue + 1) {
9 : base(char.MaxValue + 1) {
13 }
10 }
14
11
15 public override int GetSymbolIndex(char symbol) {
12 public override int GetSymbolIndex(char symbol) {
16 return symbol;
13 return symbol;
17 }
14 }
18
15
19 public override IEnumerable<char> InputSymbols {
16 public override IEnumerable<char> InputSymbols {
20 get { return Enumerable.Range(char.MinValue, char.MaxValue).Cast<char>(); }
17 get { return Enumerable.Range(char.MinValue, char.MaxValue).Cast<char>(); }
21 }
18 }
22 }
19 }
23 }
20 }
@@ -1,17 +1,11
1 using System;
1 namespace Implab.Formats.JSON {
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace Implab.JSON {
8 /// <summary>
2 /// <summary>
9 /// internal
3 /// internal
10 /// </summary>
4 /// </summary>
11 public enum JSONElementContext {
5 enum JSONElementContext {
12 None,
6 None,
13 Object,
7 Object,
14 Array,
8 Array,
15 Closed
9 Closed
16 }
10 }
17 }
11 }
@@ -1,34 +1,28
1 using System;
1 namespace Implab.Formats.JSON {
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace Implab.JSON {
8 /// <summary>
2 /// <summary>
9 /// Тип элемента на котором находится парсер
3 /// Тип элемента на котором находится парсер
10 /// </summary>
4 /// </summary>
11 public enum JSONElementType {
5 public enum JSONElementType {
12 None,
6 None,
13 /// <summary>
7 /// <summary>
14 /// Начало объекта
8 /// Начало объекта
15 /// </summary>
9 /// </summary>
16 BeginObject,
10 BeginObject,
17 /// <summary>
11 /// <summary>
18 /// Конец объекта
12 /// Конец объекта
19 /// </summary>
13 /// </summary>
20 EndObject,
14 EndObject,
21 /// <summary>
15 /// <summary>
22 /// Начало массива
16 /// Начало массива
23 /// </summary>
17 /// </summary>
24 BeginArray,
18 BeginArray,
25 /// <summary>
19 /// <summary>
26 /// Конец массива
20 /// Конец массива
27 /// </summary>
21 /// </summary>
28 EndArray,
22 EndArray,
29 /// <summary>
23 /// <summary>
30 /// Простое значение
24 /// Простое значение
31 /// </summary>
25 /// </summary>
32 Value
26 Value
33 }
27 }
34 }
28 }
@@ -1,99 +1,115
1 using System.Linq;
1 using System.Linq;
2 using Implab.Automaton.RegularExpressions;
2 using Implab.Automaton.RegularExpressions;
3 using System;
3
4
4 namespace Implab.Formats.JSON {
5 namespace Implab.Formats.JSON {
5 class JSONGrammar : Grammar<JSONGrammar> {
6 class JSONGrammar : Grammar<char,JSONGrammar.TokenType> {
6 public enum TokenType {
7 public enum TokenType {
7 None,
8 None,
8 BeginObject,
9 BeginObject,
9 EndObject,
10 EndObject,
10 BeginArray,
11 BeginArray,
11 EndArray,
12 EndArray,
12 String,
13 String,
13 Number,
14 Number,
14 Literal,
15 Literal,
15 NameSeparator,
16 NameSeparator,
16 ValueSeparator,
17 ValueSeparator,
17
18
18 StringBound,
19 StringBound,
19 EscapedChar,
20 EscapedChar,
20 UnescapedChar,
21 UnescapedChar,
21 EscapedUnicode,
22 EscapedUnicode,
22
23
23 Minus,
24 Minus,
24 Plus,
25 Plus,
25 Sign,
26 Sign,
26 Integer,
27 Integer,
27 Dot,
28 Dot,
28 Exp
29 Exp
29 }
30 }
30
31
31 readonly CDFADefinition m_jsonDFA;
32 static Lazy<JSONGrammar> _instance = new Lazy<JSONGrammar>();
32 readonly CDFADefinition m_stringDFA;
33
34 public static JSONGrammar Instance {
35 get { return _instance.Value; }
36 }
37
38 readonly RegularCharDFADefinition<TokenType> m_jsonDFA;
39 readonly RegularCharDFADefinition<TokenType> m_stringDFA;
33
40
34 public JSONGrammar() {
41 public JSONGrammar() {
35 DefineAlphabet(Enumerable.Range(0, 0x20).Select(x => (char)x));
42 DefineAlphabet(Enumerable.Range(0, 0x20).Select(x => (char)x));
36 var hexDigit = SymbolRangeToken('a','f').Or(SymbolRangeToken('A','F')).Or(SymbolRangeToken('0','9'));
43 var hexDigit = SymbolRangeToken('a','f').Or(SymbolRangeToken('A','F')).Or(SymbolRangeToken('0','9'));
37 var digit9 = SymbolRangeToken('1', '9');
44 var digit9 = SymbolRangeToken('1', '9');
38 var zero = SymbolToken('0');
45 var zero = SymbolToken('0');
39 var digit = zero.Or(digit9);
46 var digit = zero.Or(digit9);
40 var dot = SymbolToken('.');
47 var dot = SymbolToken('.');
41 var minus = SymbolToken('-');
48 var minus = SymbolToken('-');
42 var sign = SymbolSetToken('-', '+');
49 var sign = SymbolSetToken('-', '+');
43 var expSign = SymbolSetToken('e', 'E');
50 var expSign = SymbolSetToken('e', 'E');
44 var letters = SymbolRangeToken('a', 'z');
51 var letters = SymbolRangeToken('a', 'z');
45 var integer = zero.Or(digit9.Cat(digit.EClosure()));
52 var integer = zero.Or(digit9.Cat(digit.EClosure()));
46 var frac = dot.Cat(digit.Closure());
53 var frac = dot.Cat(digit.Closure());
47 var exp = expSign.Cat(sign.Optional()).Cat(digit.Closure());
54 var exp = expSign.Cat(sign.Optional()).Cat(digit.Closure());
48 var quote = SymbolToken('"');
55 var quote = SymbolToken('"');
49 var backSlash = SymbolToken('\\');
56 var backSlash = SymbolToken('\\');
50 var specialEscapeChars = SymbolSetToken('\\', '"', '/', 'b', 'f', 't', 'n', 'r');
57 var specialEscapeChars = SymbolSetToken('\\', '"', '/', 'b', 'f', 't', 'n', 'r');
51 var unicodeEspace = SymbolToken('u').Cat(hexDigit.Repeat(4));
58 var unicodeEspace = SymbolToken('u').Cat(hexDigit.Repeat(4));
52 var whitespace = SymbolSetToken('\n', '\r', '\t', ' ').EClosure();
59 var whitespace = SymbolSetToken('\n', '\r', '\t', ' ').EClosure();
53 var beginObject = whitespace.Cat(SymbolToken('{')).Cat(whitespace);
60 var beginObject = whitespace.Cat(SymbolToken('{')).Cat(whitespace);
54 var endObject = whitespace.Cat(SymbolToken('}')).Cat(whitespace);
61 var endObject = whitespace.Cat(SymbolToken('}')).Cat(whitespace);
55 var beginArray = whitespace.Cat(SymbolToken('[')).Cat(whitespace);
62 var beginArray = whitespace.Cat(SymbolToken('[')).Cat(whitespace);
56 var endArray = whitespace.Cat(SymbolToken(']')).Cat(whitespace);
63 var endArray = whitespace.Cat(SymbolToken(']')).Cat(whitespace);
57 var nameSep = whitespace.Cat(SymbolToken(':')).Cat(whitespace);
64 var nameSep = whitespace.Cat(SymbolToken(':')).Cat(whitespace);
58 var valueSep = whitespace.Cat(SymbolToken(',')).Cat(whitespace);
65 var valueSep = whitespace.Cat(SymbolToken(',')).Cat(whitespace);
59
66
60 var number = minus.Optional().Cat(integer).Cat(frac.Optional()).Cat(exp.Optional());
67 var number = minus.Optional().Cat(integer).Cat(frac.Optional()).Cat(exp.Optional());
61 var literal = letters.Closure();
68 var literal = letters.Closure();
62 var unescaped = SymbolTokenExcept(Enumerable.Range(0, 0x20).Union(new int[] { '\\', '"' }).Select(x => (char)x));
69 var unescaped = SymbolTokenExcept(Enumerable.Range(0, 0x20).Union(new int[] { '\\', '"' }).Select(x => (char)x));
63
70
64 var jsonExpression =
71 var jsonExpression =
65 number.Tag(TokenType.Number)
72 number.Tag(TokenType.Number)
66 .Or(literal.Tag(TokenType.Literal))
73 .Or(literal.Tag(TokenType.Literal))
67 .Or(quote.Tag(TokenType.StringBound))
74 .Or(quote.Tag(TokenType.StringBound))
68 .Or(beginObject.Tag(TokenType.BeginObject))
75 .Or(beginObject.Tag(TokenType.BeginObject))
69 .Or(endObject.Tag(TokenType.EndObject))
76 .Or(endObject.Tag(TokenType.EndObject))
70 .Or(beginArray.Tag(TokenType.BeginArray))
77 .Or(beginArray.Tag(TokenType.BeginArray))
71 .Or(endArray.Tag(TokenType.EndArray))
78 .Or(endArray.Tag(TokenType.EndArray))
72 .Or(nameSep.Tag(TokenType.NameSeparator))
79 .Or(nameSep.Tag(TokenType.NameSeparator))
73 .Or(valueSep.Tag(TokenType.ValueSeparator));
80 .Or(valueSep.Tag(TokenType.ValueSeparator));
74
81
75
82
76 var jsonStringExpression =
83 var jsonStringExpression =
77 quote.Tag(TokenType.StringBound)
84 quote.Tag(TokenType.StringBound)
78 .Or(backSlash.Cat(specialEscapeChars).Tag(TokenType.EscapedChar))
85 .Or(backSlash.Cat(specialEscapeChars).Tag(TokenType.EscapedChar))
79 .Or(backSlash.Cat(unicodeEspace).Tag(TokenType.EscapedUnicode))
86 .Or(backSlash.Cat(unicodeEspace).Tag(TokenType.EscapedUnicode))
80 .Or(unescaped.Closure().Tag(TokenType.UnescapedChar));
87 .Or(unescaped.Closure().Tag(TokenType.UnescapedChar));
81
88
82
89
83 m_jsonDFA = BuildDFA(jsonExpression);
90 m_jsonDFA = new RegularCharDFADefinition<TokenType>(new CharAlphabet());
84 m_stringDFA = BuildDFA(jsonStringExpression);
91 BuildDFA(jsonExpression, m_jsonDFA, m_jsonDFA.InputAlphabet);
92
93
94 m_stringDFA = new RegularCharDFADefinition<TokenType>(new CharAlphabet());
95 BuildDFA(jsonStringExpression, m_jsonDFA, m_jsonDFA.InputAlphabet);
85 }
96 }
86
97
87 public CDFADefinition JsonDFA {
98 public RegularCharDFADefinition<TokenType> JsonDFA {
88 get {
99 get {
89 return m_jsonDFA;
100 return m_jsonDFA;
90 }
101 }
91 }
102 }
92
103
93 public CDFADefinition JsonStringDFA {
104 public RegularDFADefinition<char,TokenType> JsonStringDFA {
94 get {
105 get {
95 return m_stringDFA;
106 return m_stringDFA;
96 }
107 }
97 }
108 }
109
110 Token<TokenType> SymbolRangeToken(char start, char stop) {
111 return SymbolToken(Enumerable.Range(start,stop - start).Cast<char>());
112 }
113
98 }
114 }
99 }
115 }
@@ -1,277 +1,280
1 using Implab.Parsing;
1 using System;
2 using System;
3 using System.Diagnostics;
2 using System.Diagnostics;
4 using System.IO;
3 using System.IO;
4 using Implab.Automaton;
5 using Implab.Automaton.RegularExpressions;
6 using System.Linq;
7 using Implab.Components;
5
8
6 namespace Implab.JSON {
9 namespace Implab.Formats.JSON {
7 /// <summary>
10 /// <summary>
8 /// internal
11 /// internal
9 /// </summary>
12 /// </summary>
10 public struct JSONParserContext {
13 public struct JSONParserContext {
11 public string memberName;
14 public string memberName;
12 public JSONElementContext elementContext;
15 public JSONElementContext elementContext;
13 }
16 }
14
17
15 /// <summary>
18 /// <summary>
16 /// Pull парсер JSON данных.
19 /// Pull парсер JSON данных.
17 /// </summary>
20 /// </summary>
18 /// <remarks>
21 /// <remarks>
19 /// Следует отметить отдельную интерпретацию свойства <see cref="Level"/>,
22 /// Следует отметить отдельную интерпретацию свойства <see cref="Level"/>,
20 /// оно означает текущий уровень вложенности объектов, однако закрывающий
23 /// оно означает текущий уровень вложенности объектов, однако закрывающий
21 /// элемент объекта и массива имеет уровень меньше, чем сам объект.
24 /// элемент объекта и массива имеет уровень меньше, чем сам объект.
22 /// <code>
25 /// <code>
23 /// { // Level = 1
26 /// { // Level = 1
24 /// "name" : "Peter", // Level = 1
27 /// "name" : "Peter", // Level = 1
25 /// "address" : { // Level = 2
28 /// "address" : { // Level = 2
26 /// city : "Stern" // Level = 2
29 /// city : "Stern" // Level = 2
27 /// } // Level = 1
30 /// } // Level = 1
28 /// } // Level = 0
31 /// } // Level = 0
29 /// </code>
32 /// </code>
30 /// </remarks>
33 /// </remarks>
31 public class JSONParser : DFAutomaton<JSONParserContext>, IDisposable {
34 public class JSONParser : Disposable {
32
35
33 enum MemberContext {
36 enum MemberContext {
34 MemberName,
37 MemberName,
35 MemberValue
38 MemberValue
36 }
39 }
37
40
41 struct ParserContext {
42 DFAStateDescriptior<object>
43 }
44
38 static readonly EnumAlphabet<JsonTokenType> _alphabet = EnumAlphabet<JsonTokenType>.FullAlphabet;
45 static readonly EnumAlphabet<JsonTokenType> _alphabet = EnumAlphabet<JsonTokenType>.FullAlphabet;
39 static readonly DFAStateDescriptior[] _jsonDFA;
46 static readonly DFAStateDescriptior<object>[] _jsonDFA;
40 static readonly DFAStateDescriptior[] _objectDFA;
47 static readonly int _jsonDFAInitialState;
41 static readonly DFAStateDescriptior[] _arrayDFA;
48 static readonly DFAStateDescriptior<object>[] _objectDFA;
49 static readonly int _objectDFAInitialState;
50 static readonly DFAStateDescriptior<object>[] _arrayDFA;
51 static readonly int _arrayDFAInitialState;
42
52
43 static JSONParser() {
53 static JSONParser() {
44
54
45
55
46 var valueExpression = Token.New(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String);
56 var valueExpression = Token(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String);
47 var memberExpression = Token.New(JsonTokenType.String).Cat(Token.New(JsonTokenType.NameSeparator)).Cat(valueExpression);
57 var memberExpression = Token(JsonTokenType.String).Cat(Token(JsonTokenType.NameSeparator)).Cat(valueExpression);
48
58
49 var objectExpression = memberExpression
59 var objectExpression = memberExpression
50 .Cat(
60 .Cat(
51 Token.New(JsonTokenType.ValueSeparator)
61 Token(JsonTokenType.ValueSeparator)
52 .Cat(memberExpression)
62 .Cat(memberExpression)
53 .EClosure()
63 .EClosure()
54 )
64 )
55 .Optional()
65 .Optional()
56 .Cat(Token.New(JsonTokenType.EndObject))
66 .Cat(Token(JsonTokenType.EndObject))
57 .Tag(0);
67 .Tag(null);
58 var arrayExpression = valueExpression
68 var arrayExpression = valueExpression
59 .Cat(
69 .Cat(
60 Token.New(JsonTokenType.ValueSeparator)
70 Token(JsonTokenType.ValueSeparator)
61 .Cat(valueExpression)
71 .Cat(valueExpression)
62 .EClosure()
72 .EClosure()
63 )
73 )
64 .Optional()
74 .Optional()
65 .Cat(Token.New(JsonTokenType.EndArray))
75 .Cat(Token(JsonTokenType.EndArray))
66 .Tag(0);
76 .Tag(null);
67
77
68 var jsonExpression = valueExpression.Tag(0);
78 var jsonExpression = valueExpression.Tag(null);
69
79
70 _jsonDFA = BuildDFA(jsonExpression).States;
80 _jsonDFA = CreateDFA(jsonExpression).GetTransitionTable();
71 _objectDFA = BuildDFA(objectExpression).States;
81 _objectDFA = CreateDFA(objectExpression).GetTransitionTable();
72 _arrayDFA = BuildDFA(arrayExpression).States;
82 _arrayDFA = CreateDFA(arrayExpression).GetTransitionTable();
73 }
83 }
74
84
75 static EDFADefinition<JsonTokenType> BuildDFA(Token expr) {
85 static Token<object> Token(params JsonTokenType[] input) {
76 var builder = new DFABuilder();
86 return Token<object>.New(input.Select(t => _alphabet.Translate(t)).ToArray());
77 var dfa = new EDFADefinition<JsonTokenType>(_alphabet);
87 }
88
89 static RegularDFADefinition<JsonTokenType,object> CreateDFA(Token<object> expr) {
90 var builder = new RegularDFABuilder<object>();
91 var dfa = new RegularDFADefinition<JsonTokenType,object>(_alphabet);
92
78 expr.Accept(builder);
93 expr.Accept(builder);
79
94
80 builder.BuildDFA(dfa);
95 builder.BuildDFA(dfa);
81 return dfa;
96 return dfa;
82 }
97 }
83
98
84 JSONScanner m_scanner;
99 JSONScanner m_scanner;
85 MemberContext m_memberContext;
100 MemberContext m_memberContext;
86
101
87 JSONElementType m_elementType;
102 JSONElementType m_elementType;
88 object m_elementValue;
103 object m_elementValue;
89
104
90 /// <summary>
105 /// <summary>
91 /// Создает новый парсер на основе строки, содержащей JSON
106 /// Создает новый парсер на основе строки, содержащей JSON
92 /// </summary>
107 /// </summary>
93 /// <param name="text"></param>
108 /// <param name="text"></param>
94 public JSONParser(string text)
109 public JSONParser(string text)
95 : base(_jsonDFA, INITIAL_STATE, new JSONParserContext { elementContext = JSONElementContext.None, memberName = String.Empty }) {
110 : base(_jsonDFA, INITIAL_STATE, new JSONParserContext { elementContext = JSONElementContext.None, memberName = String.Empty }) {
96 Safe.ArgumentNotEmpty(text, "text");
111 Safe.ArgumentNotEmpty(text, "text");
97 m_scanner = new JSONScanner();
112 m_scanner = new JSONScanner();
98 m_scanner.Feed(text.ToCharArray());
113 m_scanner.Feed(text.ToCharArray());
99 }
114 }
100
115
101 /// <summary>
116 /// <summary>
102 /// Создает новый экземпляр парсера, на основе текстового потока.
117 /// Создает новый экземпляр парсера, на основе текстового потока.
103 /// </summary>
118 /// </summary>
104 /// <param name="reader">Текстовый поток.</param>
119 /// <param name="reader">Текстовый поток.</param>
105 /// <param name="dispose">Признак того, что парсер должен конролировать время жизни входного потока.</param>
120 /// <param name="dispose">Признак того, что парсер должен конролировать время жизни входного потока.</param>
106 public JSONParser(TextReader reader, bool dispose)
121 public JSONParser(TextReader reader, bool dispose)
107 : base(_jsonDFA, INITIAL_STATE, new JSONParserContext { elementContext = JSONElementContext.None, memberName = String.Empty }) {
122 : base(_jsonDFA, INITIAL_STATE, new JSONParserContext { elementContext = JSONElementContext.None, memberName = String.Empty }) {
108 Safe.ArgumentNotNull(reader, "reader");
123 Safe.ArgumentNotNull(reader, "reader");
109 m_scanner = new JSONScanner();
124 m_scanner = new JSONScanner();
110 m_scanner.Feed(reader, dispose);
125 m_scanner.Feed(reader, dispose);
111 }
126 }
112
127
113 /// <summary>
128 /// <summary>
114 /// Тип текущего элемента на котором стоит парсер.
129 /// Тип текущего элемента на котором стоит парсер.
115 /// </summary>
130 /// </summary>
116 public JSONElementType ElementType {
131 public JSONElementType ElementType {
117 get { return m_elementType; }
132 get { return m_elementType; }
118 }
133 }
119
134
120 /// <summary>
135 /// <summary>
121 /// Имя элемента - имя свойства родительского контейнера. Для элементов массивов и корневого всегда
136 /// Имя элемента - имя свойства родительского контейнера. Для элементов массивов и корневого всегда
122 /// пустая строка.
137 /// пустая строка.
123 /// </summary>
138 /// </summary>
124 public string ElementName {
139 public string ElementName {
125 get { return m_context.info.memberName; }
140 get { return m_context.info.memberName; }
126 }
141 }
127
142
128 /// <summary>
143 /// <summary>
129 /// Значение элемента. Только для элементов типа <see cref="JSONElementType.Value"/>, для остальных <c>null</c>
144 /// Значение элемента. Только для элементов типа <see cref="JSONElementType.Value"/>, для остальных <c>null</c>
130 /// </summary>
145 /// </summary>
131 public object ElementValue {
146 public object ElementValue {
132 get { return m_elementValue; }
147 get { return m_elementValue; }
133 }
148 }
134
149
135 /// <summary>
150 /// <summary>
136 /// Читает слеюудущий объект из потока
151 /// Читает слеюудущий объект из потока
137 /// </summary>
152 /// </summary>
138 /// <returns><c>true</c> - операция чтения прошла успешно, <c>false</c> - конец данных</returns>
153 /// <returns><c>true</c> - операция чтения прошла успешно, <c>false</c> - конец данных</returns>
139 public bool Read() {
154 public bool Read() {
140 if (m_context.current == UNREACHEBLE_STATE)
155 if (m_context.current == UNREACHEBLE_STATE)
141 throw new InvalidOperationException("The parser is in invalid state");
156 throw new InvalidOperationException("The parser is in invalid state");
142 object tokenValue;
157 object tokenValue;
143 JsonTokenType tokenType;
158 JsonTokenType tokenType;
144 m_context.info.memberName = String.Empty;
159 m_context.info.memberName = String.Empty;
145 while (m_scanner.ReadToken(out tokenValue, out tokenType)) {
160 while (m_scanner.ReadToken(out tokenValue, out tokenType)) {
146 Move((int)tokenType);
161 Move((int)tokenType);
147 if (m_context.current == UNREACHEBLE_STATE)
162 if (m_context.current == UNREACHEBLE_STATE)
148 UnexpectedToken(tokenValue, tokenType);
163 UnexpectedToken(tokenValue, tokenType);
149 switch (tokenType) {
164 switch (tokenType) {
150 case JsonTokenType.BeginObject:
165 case JsonTokenType.BeginObject:
151 Switch(
166 Switch(
152 _objectDFA,
167 _objectDFA,
153 INITIAL_STATE,
168 INITIAL_STATE,
154 new JSONParserContext {
169 new JSONParserContext {
155 memberName = m_context.info.memberName,
170 memberName = m_context.info.memberName,
156 elementContext = JSONElementContext.Object
171 elementContext = JSONElementContext.Object
157 }
172 }
158 );
173 );
159 m_elementValue = null;
174 m_elementValue = null;
160 m_memberContext = MemberContext.MemberName;
175 m_memberContext = MemberContext.MemberName;
161 m_elementType = JSONElementType.BeginObject;
176 m_elementType = JSONElementType.BeginObject;
162 return true;
177 return true;
163 case JsonTokenType.EndObject:
178 case JsonTokenType.EndObject:
164 Restore();
179 Restore();
165 m_elementValue = null;
180 m_elementValue = null;
166 m_elementType = JSONElementType.EndObject;
181 m_elementType = JSONElementType.EndObject;
167 return true;
182 return true;
168 case JsonTokenType.BeginArray:
183 case JsonTokenType.BeginArray:
169 Switch(
184 Switch(
170 _arrayDFA,
185 _arrayDFA,
171 INITIAL_STATE,
186 INITIAL_STATE,
172 new JSONParserContext {
187 new JSONParserContext {
173 memberName = m_context.info.memberName,
188 memberName = m_context.info.memberName,
174 elementContext = JSONElementContext.Array
189 elementContext = JSONElementContext.Array
175 }
190 }
176 );
191 );
177 m_elementValue = null;
192 m_elementValue = null;
178 m_memberContext = MemberContext.MemberValue;
193 m_memberContext = MemberContext.MemberValue;
179 m_elementType = JSONElementType.BeginArray;
194 m_elementType = JSONElementType.BeginArray;
180 return true;
195 return true;
181 case JsonTokenType.EndArray:
196 case JsonTokenType.EndArray:
182 Restore();
197 Restore();
183 m_elementValue = null;
198 m_elementValue = null;
184 m_elementType = JSONElementType.EndArray;
199 m_elementType = JSONElementType.EndArray;
185 return true;
200 return true;
186 case JsonTokenType.String:
201 case JsonTokenType.String:
187 if (m_memberContext == MemberContext.MemberName) {
202 if (m_memberContext == MemberContext.MemberName) {
188 m_context.info.memberName = (string)tokenValue;
203 m_context.info.memberName = (string)tokenValue;
189 break;
204 break;
190 }
205 }
191 m_elementType = JSONElementType.Value;
206 m_elementType = JSONElementType.Value;
192 m_elementValue = tokenValue;
207 m_elementValue = tokenValue;
193 return true;
208 return true;
194 case JsonTokenType.Number:
209 case JsonTokenType.Number:
195 m_elementType = JSONElementType.Value;
210 m_elementType = JSONElementType.Value;
196 m_elementValue = tokenValue;
211 m_elementValue = tokenValue;
197 return true;
212 return true;
198 case JsonTokenType.Literal:
213 case JsonTokenType.Literal:
199 m_elementType = JSONElementType.Value;
214 m_elementType = JSONElementType.Value;
200 m_elementValue = ParseLiteral((string)tokenValue);
215 m_elementValue = ParseLiteral((string)tokenValue);
201 return true;
216 return true;
202 case JsonTokenType.NameSeparator:
217 case JsonTokenType.NameSeparator:
203 m_memberContext = MemberContext.MemberValue;
218 m_memberContext = MemberContext.MemberValue;
204 break;
219 break;
205 case JsonTokenType.ValueSeparator:
220 case JsonTokenType.ValueSeparator:
206 m_memberContext = m_context.info.elementContext == JSONElementContext.Object ? MemberContext.MemberName : MemberContext.MemberValue;
221 m_memberContext = m_context.info.elementContext == JSONElementContext.Object ? MemberContext.MemberName : MemberContext.MemberValue;
207 break;
222 break;
208 default:
223 default:
209 UnexpectedToken(tokenValue, tokenType);
224 UnexpectedToken(tokenValue, tokenType);
210 break;
225 break;
211 }
226 }
212 }
227 }
213 if (m_context.info.elementContext != JSONElementContext.None)
228 if (m_context.info.elementContext != JSONElementContext.None)
214 throw new ParserException("Unexpedted end of data");
229 throw new ParserException("Unexpedted end of data");
215 return false;
230 return false;
216 }
231 }
217
232
218 object ParseLiteral(string literal) {
233 object ParseLiteral(string literal) {
219 switch (literal) {
234 switch (literal) {
220 case "null":
235 case "null":
221 return null;
236 return null;
222 case "false":
237 case "false":
223 return false;
238 return false;
224 case "true":
239 case "true":
225 return true;
240 return true;
226 default:
241 default:
227 UnexpectedToken(literal, JsonTokenType.Literal);
242 UnexpectedToken(literal, JsonTokenType.Literal);
228 return null; // avoid compliler error
243 return null; // avoid compliler error
229 }
244 }
230 }
245 }
231
246
232 void UnexpectedToken(object value, JsonTokenType tokenType) {
247 void UnexpectedToken(object value, JsonTokenType tokenType) {
233 throw new ParserException(String.Format("Unexpected token {0}: '{1}'", tokenType, value));
248 throw new ParserException(String.Format("Unexpected token {0}: '{1}'", tokenType, value));
234 }
249 }
235
250
236
251
237 /// <summary>
252 /// <summary>
238 /// Признак конца потока
253 /// Признак конца потока
239 /// </summary>
254 /// </summary>
240 public bool EOF {
255 public bool EOF {
241 get {
256 get {
242 return m_scanner.EOF;
257 return m_scanner.EOF;
243 }
258 }
244 }
259 }
245
260
246 protected virtual void Dispose(bool disposing) {
261 protected override void Dispose(bool disposing) {
247 if (disposing) {
262 if (disposing) {
248 m_scanner.Dispose();
263 m_scanner.Dispose();
249 }
264 }
250 }
265 }
251
266
252 /// <summary>
267 /// <summary>
253 /// Освобождает парсер и связанный с ним сканнер.
254 /// </summary>
255 public void Dispose() {
256 Dispose(true);
257 GC.SuppressFinalize(this);
258 }
259
260 ~JSONParser() {
261 Dispose(false);
262 }
263
264 /// <summary>
265 /// Переходит в конец текущего объекта.
268 /// Переходит в конец текущего объекта.
266 /// </summary>
269 /// </summary>
267 public void SeekElementEnd() {
270 public void SeekElementEnd() {
268 var level = Level - 1;
271 var level = Level - 1;
269
272
270 Debug.Assert(level >= 0);
273 Debug.Assert(level >= 0);
271
274
272 while (Level != level)
275 while (Level != level)
273 Read();
276 Read();
274 }
277 }
275 }
278 }
276
279
277 }
280 }
@@ -1,100 +1,96
1 using Implab.Parsing;
1 using System;
2 using System;
3 using System.Collections.Generic;
4 using System.Globalization;
2 using System.Globalization;
5 using System.Linq;
3 using Implab.Automaton;
6 using System.Text;
7 using System.Threading.Tasks;
8
4
9 namespace Implab.JSON {
5 namespace Implab.Formats.JSON {
10 /// <summary>
6 /// <summary>
11 /// Сканнер (лексер), разбивающий поток символов на токены JSON.
7 /// Сканнер (лексер), разбивающий поток символов на токены JSON.
12 /// </summary>
8 /// </summary>
13 public class JSONScanner : Scanner {
9 public class JSONScanner : Scanner<object> {
14 char[] m_stringBuffer;
10 char[] m_stringBuffer;
15 DFAStateDescriptior[] m_stringDFA;
11 DFAStateDescriptior<>[] m_stringDFA;
16 int[] m_stringAlphabet;
12 int[] m_stringAlphabet;
17
13
18 /// <summary>
14 /// <summary>
19 /// Создает новый экземпляр сканнера
15 /// Создает новый экземпляр сканнера
20 /// </summary>
16 /// </summary>
21 public JSONScanner()
17 public JSONScanner()
22 : base(JSONGrammar.Instance.JsonDFA.States, JSONGrammar.Instance.JsonDFA.Alphabet.GetTranslationMap()) {
18 : base(JSONGrammar.Instance.JsonDFA.GetTransitionTable(), JSONGrammar.Instance.JsonDFA.Alphabet.GetTranslationMap()) {
23 m_stringBuffer = new char[1024];
19 m_stringBuffer = new char[1024];
24 var dfa = JSONGrammar.Instance.JsonStringDFA;
20 var dfa = JSONGrammar.Instance.JsonStringDFA;
25 m_stringAlphabet = dfa.Alphabet.GetTranslationMap();
21 m_stringAlphabet = dfa.Alphabet.GetTranslationMap();
26 m_stringDFA = dfa.States;
22 m_stringDFA = dfa.States;
27 }
23 }
28
24
29 /// <summary>
25 /// <summary>
30 /// Читает следующий лексический элемент из входных данных.
26 /// Читает следующий лексический элемент из входных данных.
31 /// </summary>
27 /// </summary>
32 /// <param name="tokenValue">Возвращает значение прочитанного токена.</param>
28 /// <param name="tokenValue">Возвращает значение прочитанного токена.</param>
33 /// <param name="tokenType">Возвращает тип прочитанного токена.</param>
29 /// <param name="tokenType">Возвращает тип прочитанного токена.</param>
34 /// <returns><c>true</c> - чтение произведено успешно. <c>false</c> - достигнут конец входных данных</returns>
30 /// <returns><c>true</c> - чтение произведено успешно. <c>false</c> - достигнут конец входных данных</returns>
35 /// <remarks>В случе если токен не распознается, возникает исключение. Значения токенов обрабатываются, т.е.
31 /// <remarks>В случе если токен не распознается, возникает исключение. Значения токенов обрабатываются, т.е.
36 /// в строках обрабатываются экранированные символы, числа становтся типа double.</remarks>
32 /// в строках обрабатываются экранированные символы, числа становтся типа double.</remarks>
37 public bool ReadToken(out object tokenValue, out JsonTokenType tokenType) {
33 public bool ReadToken(out object tokenValue, out JsonTokenType tokenType) {
38 if (ReadTokenInternal()) {
34 if (ReadTokenInternal()) {
39 switch ((JSONGrammar.TokenType)m_currentState.tag[0]) {
35 switch ((JSONGrammar.TokenType)m_currentState.tag[0]) {
40 case JSONGrammar.TokenType.StringBound:
36 case JSONGrammar.TokenType.StringBound:
41 tokenValue = ReadString();
37 tokenValue = ReadString();
42 tokenType = JsonTokenType.String;
38 tokenType = JsonTokenType.String;
43 break;
39 break;
44 case JSONGrammar.TokenType.Number:
40 case JSONGrammar.TokenType.Number:
45 tokenValue = Double.Parse(new String(m_buffer, m_tokenOffset, m_tokenLen), CultureInfo.InvariantCulture);
41 tokenValue = Double.Parse(new String(m_buffer, m_tokenOffset, m_tokenLen), CultureInfo.InvariantCulture);
46 tokenType = JsonTokenType.Number;
42 tokenType = JsonTokenType.Number;
47 break;
43 break;
48 default:
44 default:
49 tokenType = (JsonTokenType)m_currentState.tag[0];
45 tokenType = (JsonTokenType)m_currentState.tag[0];
50 tokenValue = new String(m_buffer, m_tokenOffset, m_tokenLen);
46 tokenValue = new String(m_buffer, m_tokenOffset, m_tokenLen);
51 break;
47 break;
52 }
48 }
53 return true;
49 return true;
54 }
50 }
55 tokenValue = null;
51 tokenValue = null;
56 tokenType = JsonTokenType.None;
52 tokenType = JsonTokenType.None;
57 return false;
53 return false;
58 }
54 }
59
55
60 string ReadString() {
56 string ReadString() {
61 int pos = 0;
57 int pos = 0;
62 Switch(m_stringDFA, m_stringAlphabet);
58 Switch(m_stringDFA, m_stringAlphabet);
63 while (ReadTokenInternal()) {
59 while (ReadTokenInternal()) {
64 switch ((JSONGrammar.TokenType)m_currentState.tag[0]) {
60 switch ((JSONGrammar.TokenType)m_currentState.tag[0]) {
65 case JSONGrammar.TokenType.StringBound:
61 case JSONGrammar.TokenType.StringBound:
66 Restore();
62 Restore();
67 return new String(m_stringBuffer, 0, pos);
63 return new String(m_stringBuffer, 0, pos);
68 case JSONGrammar.TokenType.UnescapedChar:
64 case JSONGrammar.TokenType.UnescapedChar:
69 EnsureStringBufferSize(pos + m_tokenLen);
65 EnsureStringBufferSize(pos + m_tokenLen);
70 Array.Copy(m_buffer, m_tokenOffset, m_stringBuffer, pos, m_tokenLen);
66 Array.Copy(m_buffer, m_tokenOffset, m_stringBuffer, pos, m_tokenLen);
71 pos += m_tokenLen;
67 pos += m_tokenLen;
72 break;
68 break;
73 case JSONGrammar.TokenType.EscapedUnicode:
69 case JSONGrammar.TokenType.EscapedUnicode:
74 EnsureStringBufferSize(pos + 1);
70 EnsureStringBufferSize(pos + 1);
75 m_stringBuffer[pos] = StringTranslator.TranslateHexUnicode(m_buffer, m_tokenOffset + 2);
71 m_stringBuffer[pos] = StringTranslator.TranslateHexUnicode(m_buffer, m_tokenOffset + 2);
76 pos++;
72 pos++;
77 break;
73 break;
78 case JSONGrammar.TokenType.EscapedChar:
74 case JSONGrammar.TokenType.EscapedChar:
79 EnsureStringBufferSize(pos + 1);
75 EnsureStringBufferSize(pos + 1);
80 m_stringBuffer[pos] = StringTranslator.TranslateEscapedChar(m_buffer[m_tokenOffset + 1]);
76 m_stringBuffer[pos] = StringTranslator.TranslateEscapedChar(m_buffer[m_tokenOffset + 1]);
81 pos++;
77 pos++;
82 break;
78 break;
83 default:
79 default:
84 break;
80 break;
85 }
81 }
86
82
87 }
83 }
88
84
89 throw new ParserException("Unexpected end of data");
85 throw new ParserException("Unexpected end of data");
90 }
86 }
91
87
92 void EnsureStringBufferSize(int size) {
88 void EnsureStringBufferSize(int size) {
93 if (size > m_stringBuffer.Length) {
89 if (size > m_stringBuffer.Length) {
94 var newBuffer = new char[size];
90 var newBuffer = new char[size];
95 m_stringBuffer.CopyTo(newBuffer, 0);
91 m_stringBuffer.CopyTo(newBuffer, 0);
96 m_stringBuffer = newBuffer;
92 m_stringBuffer = newBuffer;
97 }
93 }
98 }
94 }
99 }
95 }
100 }
96 }
@@ -1,50 +1,44
1 using System;
1 namespace Implab.Formats.JSON {
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace Implab.JSON {
8 /// <summary>
2 /// <summary>
9 /// Тип токенов, возвращаемых <see cref="JSONScanner"/>.
3 /// Тип токенов, возвращаемых <see cref="JSONScanner"/>.
10 /// </summary>
4 /// </summary>
11 public enum JsonTokenType : int {
5 public enum JsonTokenType : int {
12 None = 0,
6 None = 0,
13 /// <summary>
7 /// <summary>
14 /// Начало объекта
8 /// Начало объекта
15 /// </summary>
9 /// </summary>
16 BeginObject,
10 BeginObject,
17 /// <summary>
11 /// <summary>
18 /// Конец объекта
12 /// Конец объекта
19 /// </summary>
13 /// </summary>
20 EndObject,
14 EndObject,
21 /// <summary>
15 /// <summary>
22 /// Начало массива
16 /// Начало массива
23 /// </summary>
17 /// </summary>
24 BeginArray,
18 BeginArray,
25 /// <summary>
19 /// <summary>
26 /// Конец массива
20 /// Конец массива
27 /// </summary>
21 /// </summary>
28 EndArray,
22 EndArray,
29 /// <summary>
23 /// <summary>
30 /// Строка
24 /// Строка
31 /// </summary>
25 /// </summary>
32 String,
26 String,
33 /// <summary>
27 /// <summary>
34 /// Число
28 /// Число
35 /// </summary>
29 /// </summary>
36 Number,
30 Number,
37 /// <summary>
31 /// <summary>
38 /// Литерал
32 /// Литерал
39 /// </summary>
33 /// </summary>
40 Literal,
34 Literal,
41 /// <summary>
35 /// <summary>
42 /// Разделитель имени <c>:</c>
36 /// Разделитель имени <c>:</c>
43 /// </summary>
37 /// </summary>
44 NameSeparator,
38 NameSeparator,
45 /// <summary>
39 /// <summary>
46 /// Разделитель имени <c>,</c>
40 /// Разделитель имени <c>,</c>
47 /// </summary>
41 /// </summary>
48 ValueSeparator
42 ValueSeparator
49 }
43 }
50 }
44 }
@@ -1,271 +1,271
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\DFAStateDescriptor.cs" />
154 <Compile Include="Automaton\DFAStateDescriptor.cs" />
155 <Compile Include="Automaton\DFAutomaton.cs" />
156 <Compile Include="Automaton\EnumAlphabet.cs" />
155 <Compile Include="Automaton\EnumAlphabet.cs" />
157 <Compile Include="Automaton\IAlphabet.cs" />
156 <Compile Include="Automaton\IAlphabet.cs" />
158 <Compile Include="Automaton\ParserException.cs" />
157 <Compile Include="Automaton\ParserException.cs" />
159 <Compile Include="Automaton\Scanner.cs" />
158 <Compile Include="Automaton\Scanner.cs" />
160 <Compile Include="Automaton\IndexedAlphabetBase.cs" />
159 <Compile Include="Automaton\IndexedAlphabetBase.cs" />
161 <Compile Include="Automaton\IAlphabetBuilder.cs" />
160 <Compile Include="Automaton\IAlphabetBuilder.cs" />
162 <Compile Include="Automaton\RegularExpressions\AltToken.cs" />
161 <Compile Include="Automaton\RegularExpressions\AltToken.cs" />
163 <Compile Include="Automaton\RegularExpressions\BinaryToken.cs" />
162 <Compile Include="Automaton\RegularExpressions\BinaryToken.cs" />
164 <Compile Include="Automaton\RegularExpressions\CatToken.cs" />
163 <Compile Include="Automaton\RegularExpressions\CatToken.cs" />
165 <Compile Include="Automaton\DFAConst.cs" />
164 <Compile Include="Automaton\DFAConst.cs" />
166 <Compile Include="Automaton\RegularExpressions\Grammar.cs" />
165 <Compile Include="Automaton\RegularExpressions\Grammar.cs" />
167 <Compile Include="Automaton\RegularExpressions\StarToken.cs" />
166 <Compile Include="Automaton\RegularExpressions\StarToken.cs" />
168 <Compile Include="Automaton\RegularExpressions\SymbolToken.cs" />
167 <Compile Include="Automaton\RegularExpressions\SymbolToken.cs" />
169 <Compile Include="Automaton\RegularExpressions\EmptyToken.cs" />
168 <Compile Include="Automaton\RegularExpressions\EmptyToken.cs" />
170 <Compile Include="Automaton\RegularExpressions\EndToken.cs" />
169 <Compile Include="Automaton\RegularExpressions\EndToken.cs" />
171 <Compile Include="Automaton\RegularExpressions\Token.cs" />
170 <Compile Include="Automaton\RegularExpressions\Token.cs" />
172 <Compile Include="Automaton\RegularExpressions\IVisitor.cs" />
171 <Compile Include="Automaton\RegularExpressions\IVisitor.cs" />
173 <Compile Include="Automaton\AutomatonTransition.cs" />
172 <Compile Include="Automaton\AutomatonTransition.cs" />
174 <Compile Include="Automaton\RegularExpressions\RegularDFABuilder.cs" />
173 <Compile Include="Automaton\RegularExpressions\RegularDFABuilder.cs" />
175 <Compile Include="Formats\JSON\JSONElementContext.cs" />
174 <Compile Include="Formats\JSON\JSONElementContext.cs" />
176 <Compile Include="Formats\JSON\JSONElementType.cs" />
175 <Compile Include="Formats\JSON\JSONElementType.cs" />
177 <Compile Include="Formats\JSON\JSONGrammar.cs" />
176 <Compile Include="Formats\JSON\JSONGrammar.cs" />
178 <Compile Include="Formats\JSON\JSONParser.cs" />
177 <Compile Include="Formats\JSON\JSONParser.cs" />
179 <Compile Include="Formats\JSON\JSONScanner.cs" />
178 <Compile Include="Formats\JSON\JSONScanner.cs" />
180 <Compile Include="Formats\JSON\JsonTokenType.cs" />
179 <Compile Include="Formats\JSON\JsonTokenType.cs" />
181 <Compile Include="Formats\JSON\JSONWriter.cs" />
180 <Compile Include="Formats\JSON\JSONWriter.cs" />
182 <Compile Include="Formats\JSON\JSONXmlReader.cs" />
181 <Compile Include="Formats\JSON\JSONXmlReader.cs" />
183 <Compile Include="Formats\JSON\JSONXmlReaderOptions.cs" />
182 <Compile Include="Formats\JSON\JSONXmlReaderOptions.cs" />
184 <Compile Include="Formats\JSON\StringTranslator.cs" />
183 <Compile Include="Formats\JSON\StringTranslator.cs" />
185 <Compile Include="Automaton\MapAlphabet.cs" />
184 <Compile Include="Automaton\MapAlphabet.cs" />
186 <Compile Include="Automaton\DummyAlphabet.cs" />
185 <Compile Include="Automaton\DummyAlphabet.cs" />
187 <Compile Include="Automaton\DFATransitionTable.cs" />
186 <Compile Include="Automaton\DFATransitionTable.cs" />
188 <Compile Include="Automaton\IDFATransitionTableBuilder.cs" />
189 <Compile Include="Automaton\IDFATransitionTable.cs" />
190 <Compile Include="Automaton\RegularExpressions\RegularDFADefinition.cs" />
187 <Compile Include="Automaton\RegularExpressions\RegularDFADefinition.cs" />
191 <Compile Include="Formats\CharAlphabet.cs" />
188 <Compile Include="Formats\CharAlphabet.cs" />
192 <Compile Include="Formats\ByteAlphabet.cs" />
189 <Compile Include="Formats\ByteAlphabet.cs" />
190 <Compile Include="Formats\RegularCharDFADefinition.cs" />
191 <Compile Include="Automaton\IDFATable.cs" />
192 <Compile Include="Automaton\IDFATableBuilder.cs" />
193 </ItemGroup>
193 </ItemGroup>
194 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
194 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
195 <ItemGroup />
195 <ItemGroup />
196 <ProjectExtensions>
196 <ProjectExtensions>
197 <MonoDevelop>
197 <MonoDevelop>
198 <Properties>
198 <Properties>
199 <Policies>
199 <Policies>
200 <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" />
200 <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" />
201 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
201 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
202 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
202 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
203 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
203 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
204 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
204 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
205 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
205 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
206 <NameConventionPolicy>
206 <NameConventionPolicy>
207 <Rules>
207 <Rules>
208 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
208 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
209 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
209 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
210 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
210 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
211 <RequiredPrefixes>
211 <RequiredPrefixes>
212 <String>I</String>
212 <String>I</String>
213 </RequiredPrefixes>
213 </RequiredPrefixes>
214 </NamingRule>
214 </NamingRule>
215 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
215 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
216 <RequiredSuffixes>
216 <RequiredSuffixes>
217 <String>Attribute</String>
217 <String>Attribute</String>
218 </RequiredSuffixes>
218 </RequiredSuffixes>
219 </NamingRule>
219 </NamingRule>
220 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
220 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
221 <RequiredSuffixes>
221 <RequiredSuffixes>
222 <String>EventArgs</String>
222 <String>EventArgs</String>
223 </RequiredSuffixes>
223 </RequiredSuffixes>
224 </NamingRule>
224 </NamingRule>
225 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
225 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
226 <RequiredSuffixes>
226 <RequiredSuffixes>
227 <String>Exception</String>
227 <String>Exception</String>
228 </RequiredSuffixes>
228 </RequiredSuffixes>
229 </NamingRule>
229 </NamingRule>
230 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
230 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
231 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
231 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
232 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
232 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
233 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
233 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
234 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
234 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
235 <RequiredPrefixes>
235 <RequiredPrefixes>
236 <String>m_</String>
236 <String>m_</String>
237 </RequiredPrefixes>
237 </RequiredPrefixes>
238 </NamingRule>
238 </NamingRule>
239 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
239 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
240 <RequiredPrefixes>
240 <RequiredPrefixes>
241 <String>_</String>
241 <String>_</String>
242 </RequiredPrefixes>
242 </RequiredPrefixes>
243 </NamingRule>
243 </NamingRule>
244 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
244 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
245 <RequiredPrefixes>
245 <RequiredPrefixes>
246 <String>m_</String>
246 <String>m_</String>
247 </RequiredPrefixes>
247 </RequiredPrefixes>
248 </NamingRule>
248 </NamingRule>
249 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
249 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
250 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
250 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
251 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
251 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
252 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
252 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
253 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
253 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
254 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
254 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
255 <RequiredPrefixes>
255 <RequiredPrefixes>
256 <String>T</String>
256 <String>T</String>
257 </RequiredPrefixes>
257 </RequiredPrefixes>
258 </NamingRule>
258 </NamingRule>
259 </Rules>
259 </Rules>
260 </NameConventionPolicy>
260 </NameConventionPolicy>
261 </Policies>
261 </Policies>
262 </Properties>
262 </Properties>
263 </MonoDevelop>
263 </MonoDevelop>
264 </ProjectExtensions>
264 </ProjectExtensions>
265 <ItemGroup>
265 <ItemGroup>
266 <Folder Include="Components\" />
266 <Folder Include="Components\" />
267 <Folder Include="Automaton\RegularExpressions\" />
267 <Folder Include="Automaton\RegularExpressions\" />
268 <Folder Include="Formats\" />
268 <Folder Include="Formats\" />
269 <Folder Include="Formats\JSON\" />
269 <Folder Include="Formats\JSON\" />
270 </ItemGroup>
270 </ItemGroup>
271 </Project> No newline at end of file
271 </Project>
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
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