##// END OF EJS Templates
Promises: SignalXXX methods merged into SignalHandler method....
cin -
r156:97fbbf816844 v2
parent child
Show More
@@ -0,0 +1,8
1 using System;
2
3 namespace Implab.Components {
4 public interface IFactory<out T> {
5 T Create();
6 }
7 }
8
@@ -0,0 +1,141
1 using System;
2 using Implab.Parsing;
3
4 namespace Implab.Components {
5 public class RunnableComponent : Disposable, IRunnable, IInitializable {
6 class Automaton : DFAutomaton<ExecutionState> {
7 static readonly EDFADefinition<ExecutionState> _dfa;
8
9 static Automaton() {
10
11 var token = Token
12 .New(ExecutionState.Uninitialized).Optional() // we can skip uninitialized state
13 .Cat(
14 Token.New(ExecutionState.Ready) // uninitialized -> initial
15 .Cat(
16 Token.New(ExecutionState.Starting) // initial -> starting
17 .Cat(
18 Token.New(ExecutionState.Running) // running -> {stopping -> stopped | failed }
19 .Cat(
20 Token.New(ExecutionState.Stopping) // running -> stopping
21 .Cat(
22 Token.New(ExecutionState.Stopped) // stopping -> stopped
23 .Or(Token.New(ExecutionState.Failed)) // stopping -> failed
24 )
25 .Or(Token.New(ExecutionState.Failed)) // running -> failed
26 )
27 .Or(Token.New(ExecutionState.Failed)) // starting -> failed
28 ).EClosure()
29 )
30 .Or(Token.New(ExecutionState.Failed)) // uninitialized->failed
31 .Cat(Token.New(ExecutionState.Disposed).Tag(0)) // ... -> disposed
32 );
33
34 var builder = new DFABuilder();
35 token.Accept(builder);
36
37 var _dfa = new EDFADefinition<ExecutionState>(EnumAlphabet<ExecutionState>.FullAlphabet);
38 builder.BuildDFA(_dfa); // don't optimize dfa to avoid remapping of the alphabet
39
40 }
41
42 public Automaton() : base(_dfa.States, INITIAL_STATE, ExecutionState.Reserved) {
43 }
44
45 public void MoveTo(ExecutionState state) {
46
47 if (!CanMove((int)state))
48 throw new InvalidOperationException(String.Format("Illegal state transition from {0} to {1}", Current, state));
49 Move((int)state);
50 m_context.info = state;
51 }
52
53 public ExecutionState Current {
54 get {
55 return (ExecutionState)m_context.info;
56 }
57 }
58 }
59
60 readonly Automaton m_automaton = new Automaton();
61 IPromise m_pending;
62 Exception m_lastError;
63
64 protected RunnableComponent(bool initialized) {
65 if (initialized)
66 m_automaton.MoveTo(ExecutionState.Ready);
67 else
68 m_automaton.MoveTo(ExecutionState.Uninitialized);
69 }
70
71 #region IInitializable implementation
72
73 public void Init() {
74
75 }
76
77 #endregion
78
79 #region IRunnable implementation
80
81 public IPromise Start() {
82 return Safe.InvokePromise(() => {
83 Promise promise;
84 lock (m_automaton) {
85 if (m_automaton.Current == ExecutionState.Starting)
86 return m_pending;
87 m_automaton.MoveTo(ExecutionState.Starting);
88 m_pending = promise = new Promise();
89 }
90
91 var start = Safe.InvokePromise(OnStart);
92 promise.On(null, null, start.Cancel);
93 start.On(promise.Resolve, promise.Reject, promise.CancelOperation);
94
95 return promise.Then(() => {
96 lock(m_automaton) {
97 m_automaton.MoveTo(ExecutionState.Running);
98 m_pending = null;
99 }
100
101 Run();
102 }, err => {
103 if (BeginTransition(RUNNING_REQUIRE)) {
104 m_lastError = err;
105 CompleteTransition(FAILED_STATE);
106 throw new PromiseTransientException(err);
107 }
108 throw new OperationCanceledException();
109 }, reason => {
110 throw new OperationCanceledException("The operation was cancelled", reason);
111 });
112 });
113 }
114
115 protected virtual IPromise OnStart() {
116 return Promise.SUCCESS;
117 }
118
119 protected virtual void Run() {
120 }
121
122 public IPromise Stop() {
123 throw new NotImplementedException();
124 }
125
126 public ExecutionState State {
127 get {
128 throw new NotImplementedException();
129 }
130 }
131
132 public Exception LastError {
133 get {
134 throw new NotImplementedException();
135 }
136 }
137
138 #endregion
139 }
140 }
141
@@ -1,38 +1,23
1 1 using System.Windows.Forms;
2 2 using System;
3 3
4 4
5 5 namespace Implab.Fx {
6 6 public class ControlBoundPromise<T> : Promise<T> {
7 7 readonly Control m_target;
8 8
9 9 public ControlBoundPromise(Control target) {
10 10 Safe.ArgumentNotNull(target, "target");
11 11
12 12 m_target = target;
13 13 }
14 14
15 protected override void SignalSuccess(Promise<T>.HandlerDescriptor handler) {
15 protected override void SignalHandler(HandlerDescriptor handler, int signal) {
16 16 if (m_target.InvokeRequired)
17 m_target.BeginInvoke(new Action<Promise<T>.HandlerDescriptor>(base.SignalSuccess), handler);
18 else
19 base.SignalSuccess(handler);
20 }
21
22 protected override void SignalCancelled(Promise<T>.HandlerDescriptor handler, Exception reason) {
23 if (m_target.InvokeRequired)
24 m_target.BeginInvoke(new Action<Promise<T>.HandlerDescriptor,Exception>(base.SignalCancelled), handler, reason);
17 m_target.BeginInvoke(new Action<Promise<T>.HandlerDescriptor, int>(base.SignalHandler), handler, signal);
25 18 else
26 base.SignalCancelled(handler, reason);
19 base.SignalHandler(handler, signal);
27 20 }
28
29 protected override void SignalError(Promise<T>.HandlerDescriptor handler, Exception error) {
30 if (m_target.InvokeRequired)
31 m_target.BeginInvoke(new Action<Promise<T>.HandlerDescriptor,Exception>(base.SignalError), handler, error);
32 else
33 base.SignalError(handler, error);
34 }
35
36 21 }
37 22 }
38 23
@@ -1,353 +1,300
1 1 using System;
2 2 using Implab.Parallels;
3 3 using System.Threading;
4 4 using System.Reflection;
5 5
6 6 namespace Implab {
7 7 public abstract class AbstractEvent<THandler> : ICancellationToken, ICancellable {
8 8
9 9 const int UNRESOLVED_SATE = 0;
10 10 const int TRANSITIONAL_STATE = 1;
11 const int SUCCEEDED_STATE = 2;
12 const int REJECTED_STATE = 3;
13 const int CANCELLED_STATE = 4;
11 protected const int SUCCEEDED_STATE = 2;
12 protected const int REJECTED_STATE = 3;
13 protected const int CANCELLED_STATE = 4;
14 14
15 15 const int CANCEL_NOT_REQUESTED = 0;
16 16 const int CANCEL_REQUESTING = 1;
17 17 const int CANCEL_REQUESTED = 2;
18 18
19 19 const int RESERVED_HANDLERS_COUNT = 4;
20 20
21 21 int m_state;
22 22 Exception m_error;
23 23 int m_handlersCount;
24 24
25 readonly THandler[] m_handlers = new THandler[RESERVED_HANDLERS_COUNT];
25 //readonly THandler[] m_handlers = new THandler[RESERVED_HANDLERS_COUNT];
26 THandler[] m_handlers;
26 27 MTQueue<THandler> m_extraHandlers;
27 28 int m_handlerPointer = -1;
28 29 int m_handlersCommited;
29 30
30 31 int m_cancelRequest;
31 32 Exception m_cancelationReason;
32 33 MTQueue<Action<Exception>> m_cancelationHandlers;
33 34
34 35
35 36 #region state managment
36 37 bool BeginTransit() {
37 38 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
38 39 }
39 40
40 41 void CompleteTransit(int state) {
41 42 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
42 43 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
43 44 }
44 45
45 46 void WaitTransition() {
46 47 while (m_state == TRANSITIONAL_STATE) {
47 48 Thread.MemoryBarrier();
48 49 }
49 50 }
50 51
51 52 protected bool BeginSetResult() {
52 53 if (!BeginTransit()) {
53 54 WaitTransition();
54 55 if (m_state != CANCELLED_STATE)
55 56 throw new InvalidOperationException("The promise is already resolved");
56 57 return false;
57 58 }
58 59 return true;
59 60 }
60 61
61 62 protected void EndSetResult() {
62 63 CompleteTransit(SUCCEEDED_STATE);
63 OnSuccess();
64 Signal();
64 65 }
65 66
66 67
67 68
68 69 /// <summary>
69 70 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
70 71 /// </summary>
71 72 /// <remarks>
72 73 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
73 74 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
74 75 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
75 76 /// </remarks>
76 77 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
77 78 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
78 79 protected void SetError(Exception error) {
79 80 if (BeginTransit()) {
80 81 if (error is OperationCanceledException) {
82 m_error = error.InnerException;
81 83 CompleteTransit(CANCELLED_STATE);
82 m_error = error.InnerException;
83 OnCancelled();
84 84 } else {
85 85 m_error = error is PromiseTransientException ? error.InnerException : error;
86 86 CompleteTransit(REJECTED_STATE);
87 OnError();
88 87 }
88 Signal();
89 89 } else {
90 90 WaitTransition();
91 91 if (m_state == SUCCEEDED_STATE)
92 92 throw new InvalidOperationException("The promise is already resolved");
93 93 }
94 94 }
95 95
96 96 /// <summary>
97 97 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
98 98 /// </summary>
99 99 /// <remarks>Для опрСдСлСния Π±Ρ‹Π»Π° Π»ΠΈ опСрация ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π° слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ свойство <see cref="IsCancelled"/>.</remarks>
100 100 protected void SetCancelled(Exception reason) {
101 101 if (BeginTransit()) {
102 102 m_error = reason;
103 103 CompleteTransit(CANCELLED_STATE);
104 OnCancelled();
104 Signal();
105 105 }
106 106 }
107 107
108 protected abstract void SignalSuccess(THandler handler);
109
110 protected abstract void SignalError(THandler handler, Exception error);
108 protected abstract void SignalHandler(THandler handler, int signal);
111 109
112 protected abstract void SignalCancelled(THandler handler, Exception reason);
113
114 void OnSuccess() {
110 void Signal() {
115 111 var hp = m_handlerPointer;
116 112 var slot = hp +1 ;
117 113 while (slot < m_handlersCommited) {
118 114 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
119 SignalSuccess(m_handlers[slot]);
115 SignalHandler(m_handlers[slot], m_state);
120 116 }
121 117 hp = m_handlerPointer;
122 118 slot = hp +1 ;
123 119 }
124 120
125 121
126 122 if (m_extraHandlers != null) {
127 123 THandler handler;
128 124 while (m_extraHandlers.TryDequeue(out handler))
129 SignalSuccess(handler);
130 }
131 }
132
133 void OnError() {
134 var hp = m_handlerPointer;
135 var slot = hp +1 ;
136 while (slot < m_handlersCommited) {
137 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
138 SignalError(m_handlers[slot],m_error);
139 }
140 hp = m_handlerPointer;
141 slot = hp +1 ;
142 }
143
144 if (m_extraHandlers != null) {
145 THandler handler;
146 while (m_extraHandlers.TryDequeue(out handler))
147 SignalError(handler, m_error);
148 }
149 }
150
151 void OnCancelled() {
152 var hp = m_handlerPointer;
153 var slot = hp +1 ;
154 while (slot < m_handlersCommited) {
155 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
156 SignalCancelled(m_handlers[slot], m_error);
157 }
158 hp = m_handlerPointer;
159 slot = hp +1 ;
160 }
161
162 if (m_extraHandlers != null) {
163 THandler handler;
164 while (m_extraHandlers.TryDequeue(out handler))
165 SignalCancelled(handler, m_error);
125 SignalHandler(handler, m_state);
166 126 }
167 127 }
168 128
169 129 #endregion
170 130
171 131 protected abstract Signal GetResolveSignal();
172 132
173 133 #region synchronization traits
174 134 protected void WaitResult(int timeout) {
175 135 if (!(IsResolved || GetResolveSignal().Wait(timeout)))
176 136 throw new TimeoutException();
177 137
178 138 switch (m_state) {
179 139 case SUCCEEDED_STATE:
180 140 return;
181 141 case CANCELLED_STATE:
182 142 throw new OperationCanceledException();
183 143 case REJECTED_STATE:
184 144 throw new TargetInvocationException(m_error);
185 145 default:
186 146 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
187 147 }
188 148 }
189 149 #endregion
190 150
191 151 #region handlers managment
192 152
193 153 protected void AddHandler(THandler handler) {
194 154
195 155 if (m_state > 1) {
196 156 // the promise is in the resolved state, just invoke the handler
197 InvokeHandler(handler);
157 SignalHandler(handler, m_state);
198 158 } else {
199 159 var slot = Interlocked.Increment(ref m_handlersCount) - 1;
200 160
201 161 if (slot < RESERVED_HANDLERS_COUNT) {
202 162
163 if (slot == 0)
164 Interlocked.CompareExchange(ref m_handlers, new THandler[RESERVED_HANDLERS_COUNT], null);
165
203 166 m_handlers[slot] = handler;
204 167
205 168 while (slot != Interlocked.CompareExchange(ref m_handlersCommited, slot + 1, slot)) {
206 169 }
207 170
208 171 if (m_state > 1) {
209 172 do {
210 173 var hp = m_handlerPointer;
211 174 slot = hp + 1;
212 175 if (slot < m_handlersCommited) {
213 176 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) != hp)
214 177 continue;
215 InvokeHandler(m_handlers[slot]);
178 SignalHandler(m_handlers[slot], m_state);
216 179 }
217 180 break;
218 181 } while(true);
219 182 }
220 183 } else {
221 184 if (slot == RESERVED_HANDLERS_COUNT) {
222 185 m_extraHandlers = new MTQueue<THandler>();
223 186 } else {
224 187 while (m_extraHandlers == null)
225 188 Thread.MemoryBarrier();
226 189 }
227 190
228 191 m_extraHandlers.Enqueue(handler);
229 192
230 193 if (m_state > 1 && m_extraHandlers.TryDequeue(out handler))
231 194 // if the promise have been resolved while we was adding the handler to the queue
232 195 // we can't guarantee that someone is still processing it
233 196 // therefore we need to fetch a handler from the queue and execute it
234 197 // note that fetched handler may be not the one that we have added
235 198 // even we can fetch no handlers at all :)
236 InvokeHandler(handler);
199 SignalHandler(handler, m_state);
237 200 }
238 201 }
239 202 }
240 203
241 protected void InvokeHandler(THandler handler) {
242 switch (m_state) {
243 case SUCCEEDED_STATE:
244 SignalSuccess(handler);
245 break;
246 case CANCELLED_STATE:
247 SignalCancelled(handler, m_error);
248 break;
249 case REJECTED_STATE:
250 SignalError(handler, m_error);
251 break;
252 default:
253 throw new Exception(String.Format("Invalid promise state {0}", m_state));
254 }
255 }
256
257 204 #endregion
258 205
259 206 #region IPromise implementation
260 207
261 208 public bool IsResolved {
262 209 get {
263 210 Thread.MemoryBarrier();
264 211 return m_state > 1;
265 212 }
266 213 }
267 214
268 215 public bool IsCancelled {
269 216 get {
270 217 Thread.MemoryBarrier();
271 218 return m_state == CANCELLED_STATE;
272 219 }
273 220 }
274 221
275 222 #endregion
276 223
277 224 public Exception Error {
278 225 get {
279 226 return m_error;
280 227 }
281 228 }
282 229
283 230 public bool CancelOperationIfRequested() {
284 231 if (IsCancellationRequested) {
285 232 CancelOperation(CancellationReason);
286 233 return true;
287 234 }
288 235 return false;
289 236 }
290 237
291 238 public virtual void CancelOperation(Exception reason) {
292 239 SetCancelled(reason);
293 240 }
294 241
295 242 public void CancellationRequested(Action<Exception> handler) {
296 243 Safe.ArgumentNotNull(handler, "handler");
297 244 if (IsCancellationRequested)
298 245 handler(CancellationReason);
299 246
300 247 if (m_cancelationHandlers == null)
301 248 Interlocked.CompareExchange(ref m_cancelationHandlers, new MTQueue<Action<Exception>>(), null);
302 249
303 250 m_cancelationHandlers.Enqueue(handler);
304 251
305 252 if (IsCancellationRequested && m_cancelationHandlers.TryDequeue(out handler))
306 253 // TryDeque implies MemoryBarrier()
307 254 handler(m_cancelationReason);
308 255 }
309 256
310 257 public bool IsCancellationRequested {
311 258 get {
312 259 do {
313 260 if (m_cancelRequest == CANCEL_NOT_REQUESTED)
314 261 return false;
315 262 if (m_cancelRequest == CANCEL_REQUESTED)
316 263 return true;
317 264 Thread.MemoryBarrier();
318 265 } while(true);
319 266 }
320 267 }
321 268
322 269 public Exception CancellationReason {
323 270 get {
324 271 do {
325 272 Thread.MemoryBarrier();
326 273 } while(m_cancelRequest == CANCEL_REQUESTING);
327 274
328 275 return m_cancelationReason;
329 276 }
330 277 }
331 278
332 279 #region ICancellable implementation
333 280
334 281 public void Cancel() {
335 282 Cancel(null);
336 283 }
337 284
338 285 public void Cancel(Exception reason) {
339 286 if (CANCEL_NOT_REQUESTED == Interlocked.CompareExchange(ref m_cancelRequest, CANCEL_REQUESTING, CANCEL_NOT_REQUESTED)) {
340 287 m_cancelationReason = reason;
341 288 m_cancelRequest = CANCEL_REQUESTED;
342 289 if (m_cancelationHandlers != null) {
343 290 Action<Exception> handler;
344 291 while (m_cancelationHandlers.TryDequeue(out handler))
345 292 handler(m_cancelationReason);
346 293 }
347 294 }
348 295 }
349 296
350 297 #endregion
351 298 }
352 299 }
353 300
@@ -1,138 +1,142
1 1 using System;
2 2 using Implab.Parallels;
3 3
4 4 namespace Implab {
5 5 public abstract class AbstractPromise : AbstractEvent<AbstractPromise.HandlerDescriptor>, IPromise {
6 6 public struct HandlerDescriptor {
7 7 readonly Action m_handler;
8 8 readonly Action<Exception> m_error;
9 9 readonly Action<Exception> m_cancel;
10 10 readonly PromiseEventType m_mask;
11 11
12 12 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel) {
13 13 m_handler = success;
14 14 m_error = error;
15 15 m_cancel = cancel;
16 16 m_mask = PromiseEventType.Success;
17 17 }
18 18
19 19 public HandlerDescriptor(Action handler, PromiseEventType mask) {
20 20 m_handler = handler;
21 21 m_error = null;
22 22 m_cancel = null;
23 23 m_mask = mask;
24 24 }
25 25
26 26 public void SignalSuccess() {
27 27 if ((m_mask & PromiseEventType.Success) != 0 && m_handler != null) {
28 28 try {
29 29 m_handler();
30 30 } catch (Exception err) {
31 31 // avoid calling handler twice in case of error
32 32 if (m_error != null)
33 33 SignalError(err);
34 34 }
35 35 }
36 36 }
37 37
38 38 public void SignalError(Exception err) {
39 39 if (m_error != null) {
40 40 try {
41 41 m_error(err);
42 42 // Analysis disable once EmptyGeneralCatchClause
43 43 } catch {
44 44 }
45 45 } else if ((m_mask & PromiseEventType.Error ) != 0 && m_handler != null) {
46 46 try {
47 47 m_handler();
48 48 // Analysis disable once EmptyGeneralCatchClause
49 49 } catch {
50 50 }
51 51 }
52 52 }
53 53
54 54 public void SignalCancel(Exception reason) {
55 55 if (m_cancel != null) {
56 56 try {
57 57 m_cancel(reason);
58 58 } catch (Exception err) {
59 59 SignalError(err);
60 60 }
61 61 } else if ( (m_mask & PromiseEventType.Cancelled) != 0 && m_handler != null) {
62 62 try {
63 63 m_handler();
64 64 // Analysis disable once EmptyGeneralCatchClause
65 65 } catch {
66 66 }
67 67 }
68 68 }
69 69 }
70 70
71 71
72 72 #region implemented abstract members of AbstractPromise
73 73
74 protected override void SignalSuccess(HandlerDescriptor handler) {
75 handler.SignalSuccess();
76 }
77
78 protected override void SignalError(HandlerDescriptor handler, Exception error) {
79 handler.SignalError(error);
80 }
81
82 protected override void SignalCancelled(HandlerDescriptor handler, Exception reason) {
83 handler.SignalCancel(reason);
74 protected override void SignalHandler(HandlerDescriptor handler, int signal) {
75 switch (signal) {
76 case SUCCEEDED_STATE:
77 handler.SignalSuccess();
78 break;
79 case REJECTED_STATE:
80 handler.SignalError(Error);
81 break;
82 case CANCELLED_STATE:
83 handler.SignalCancel(CancellationReason);
84 break;
85 default:
86 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", signal));
87 }
84 88 }
85 89
86 90 protected override Signal GetResolveSignal() {
87 91 var signal = new Signal();
88 92 On(signal.Set, PromiseEventType.All);
89 93 return signal;
90 94 }
91 95
92 96 #endregion
93 97
94 98 public Type PromiseType {
95 99 get {
96 100 return typeof(void);
97 101 }
98 102 }
99 103
100 104 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) {
101 105 AddHandler(new HandlerDescriptor(success, error, cancel));
102 106 return this;
103 107 }
104 108
105 109 public IPromise On(Action success, Action<Exception> error) {
106 110 AddHandler(new HandlerDescriptor(success, error, null));
107 111 return this;
108 112 }
109 113
110 114 public IPromise On(Action success) {
111 115 AddHandler(new HandlerDescriptor(success, null, null));
112 116 return this;
113 117 }
114 118
115 119 public IPromise On(Action handler, PromiseEventType events) {
116 120 AddHandler(new HandlerDescriptor(handler,events));
117 121 return this;
118 122 }
119 123
120 124 public IPromise<T> Cast<T>() {
121 125 throw new InvalidCastException();
122 126 }
123 127
124 128 public void Join() {
125 129 WaitResult(-1);
126 130 }
127 131
128 132 public void Join(int timeout) {
129 133 WaitResult(timeout);
130 134 }
131 135
132 136 protected void SetResult() {
133 137 BeginSetResult();
134 138 EndSetResult();
135 139 }
136 140 }
137 141 }
138 142
@@ -1,202 +1,206
1 1 using System;
2 2 using Implab.Parallels;
3 3
4 4 namespace Implab {
5 5 public abstract class AbstractPromise<T> : AbstractEvent<AbstractPromise<T>.HandlerDescriptor>, IPromise<T> {
6 6 public struct HandlerDescriptor {
7 7 readonly Action m_handler;
8 8 readonly Action<T> m_success;
9 9 readonly Action<Exception> m_error;
10 10 readonly Action<Exception> m_cancel;
11 11 readonly PromiseEventType m_mask;
12 12
13 13 public HandlerDescriptor(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
14 14 m_success = success;
15 15 m_error = error;
16 16 m_cancel = cancel;
17 17
18 18 m_handler = null;
19 19 m_mask = 0;
20 20 }
21 21
22 22 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel) {
23 23 m_handler = success;
24 24 m_success = null;
25 25 m_error = error;
26 26 m_cancel = cancel;
27 27 m_mask = PromiseEventType.Success;
28 28 }
29 29
30 30 public HandlerDescriptor(Action handler, PromiseEventType mask) {
31 31 m_handler = handler;
32 32 m_mask = mask;
33 33 m_success = null;
34 34 m_error = null;
35 35 m_cancel = null;
36 36 }
37 37
38 38 public void SignalSuccess(T result) {
39 39 if (m_success != null) {
40 40 try {
41 41 m_success(result);
42 42 } catch(Exception err) {
43 43 SignalError(err);
44 44 }
45 45 } else if ((m_mask & PromiseEventType.Success) != 0 && m_handler != null) {
46 46 try {
47 47 m_handler();
48 48 } catch(Exception err) {
49 49 // avoid calling handler twice in case of error
50 50 if (m_error != null)
51 51 SignalError(err);
52 52 }
53 53 }
54 54 }
55 55
56 56 public void SignalError(Exception err) {
57 57 if (m_error != null) {
58 58 try {
59 59 m_error(err);
60 60 // Analysis disable once EmptyGeneralCatchClause
61 61 } catch {
62 62 }
63 63 } else if ((m_mask & PromiseEventType.Error) != 0 && m_handler != null) {
64 64 try {
65 65 m_handler();
66 66 // Analysis disable once EmptyGeneralCatchClause
67 67 } catch {
68 68 }
69 69 }
70 70 }
71 71
72 72 public void SignalCancel(Exception reason) {
73 73 if (m_cancel != null) {
74 74 try {
75 75 m_cancel(reason);
76 76 } catch (Exception err) {
77 77 SignalError(err);
78 78 }
79 79 } else if ((m_mask & PromiseEventType.Cancelled) != 0 && m_handler != null) {
80 80 try {
81 81 m_handler();
82 82 // Analysis disable once EmptyGeneralCatchClause
83 83 } catch {
84 84 }
85 85 }
86 86 }
87 87 }
88 88
89 89 public Type PromiseType {
90 90 get {
91 91 return typeof(T);
92 92 }
93 93 }
94 94
95 95 public T Join() {
96 96 WaitResult(-1);
97 97 return m_result;
98 98 }
99 99 public T Join(int timeout) {
100 100 WaitResult(timeout);
101 101 return m_result;
102 102 }
103 103
104 104 void IPromise.Join() {
105 105 WaitResult(-1);
106 106 }
107 107 void IPromise.Join(int timeout) {
108 108 WaitResult(timeout);
109 109 }
110 110
111 111 public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
112 112 AddHandler(new HandlerDescriptor(success, error, cancel));
113 113 return this;
114 114 }
115 115
116 116 public IPromise<T> On(Action<T> success, Action<Exception> error) {
117 117 AddHandler(new HandlerDescriptor(success, error, null));
118 118 return this;
119 119 }
120 120
121 121 public IPromise<T> On(Action<T> success) {
122 122 AddHandler(new HandlerDescriptor(success, null, null));
123 123 return this;
124 124 }
125 125
126 126 public IPromise<T> On(Action handler, PromiseEventType events) {
127 127 AddHandler(new HandlerDescriptor(handler, events));
128 128 return this;
129 129 }
130 130
131 131 public IPromise<T> On(Action success, Action<Exception> error, Action<Exception> cancel) {
132 132 AddHandler(new HandlerDescriptor(success, error, cancel));
133 133 return this;
134 134 }
135 135
136 136 public IPromise<T> On(Action success, Action<Exception> error) {
137 137 AddHandler(new HandlerDescriptor(success, error, null));
138 138 return this;
139 139 }
140 140
141 141 public IPromise<T> On(Action success) {
142 142 AddHandler(new HandlerDescriptor(success, null, null));
143 143 return this;
144 144 }
145 145
146 146 IPromise IPromise.On(Action success, Action<Exception> error, Action<Exception> cancel) {
147 147 AddHandler(new HandlerDescriptor(success, error, cancel));
148 148 return this;
149 149 }
150 150
151 151 IPromise IPromise.On(Action success, Action<Exception> error) {
152 152 AddHandler(new HandlerDescriptor(success, error, null));
153 153 return this;
154 154 }
155 155
156 156 IPromise IPromise.On(Action success) {
157 157 AddHandler(new HandlerDescriptor(success, null, null));
158 158 return this;
159 159 }
160 160
161 161 IPromise IPromise.On(Action handler, PromiseEventType events) {
162 162 AddHandler(new HandlerDescriptor(handler, events));
163 163 return this;
164 164 }
165 165
166 166 public IPromise<T2> Cast<T2>() {
167 167 return (IPromise<T2>)this;
168 168 }
169 169
170 170 #region implemented abstract members of AbstractPromise
171 171
172 172 protected override Signal GetResolveSignal() {
173 173 var signal = new Signal();
174 174 AddHandler(new HandlerDescriptor(signal.Set, PromiseEventType.All));
175 175 return signal;
176 176 }
177 177
178 protected override void SignalSuccess(HandlerDescriptor handler) {
179 handler.SignalSuccess(m_result);
180 }
181
182 protected override void SignalError(HandlerDescriptor handler, Exception error) {
183 handler.SignalError(error);
184 }
185
186 protected override void SignalCancelled(HandlerDescriptor handler, Exception reason) {
187 handler.SignalCancel(reason);
178 protected override void SignalHandler(HandlerDescriptor handler, int signal) {
179 switch (signal) {
180 case SUCCEEDED_STATE:
181 handler.SignalSuccess(m_result);
182 break;
183 case REJECTED_STATE:
184 handler.SignalError(Error);
185 break;
186 case CANCELLED_STATE:
187 handler.SignalCancel(CancellationReason);
188 break;
189 default:
190 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", signal));
191 }
188 192 }
189 193
190 194 #endregion
191 195
192 196 T m_result;
193 197
194 198 protected void SetResult(T value) {
195 199 if (BeginSetResult()) {
196 200 m_result = value;
197 201 EndSetResult();
198 202 }
199 203 }
200 204 }
201 205 }
202 206
@@ -1,13 +1,14
1 1 namespace Implab.Components {
2 2
3 3 public enum ExecutionState {
4 Reserved = 0,
4 5 Uninitialized,
5 Initial,
6 Ready,
6 7 Starting,
7 8 Running,
8 9 Stopping,
9 10 Stopped,
10 11 Disposed,
11 12 Failed
12 13 }
13 14 } No newline at end of file
@@ -1,260 +1,262
1 1 ο»Ώ<?xml version="1.0" encoding="utf-8"?>
2 2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 3 <PropertyGroup>
4 4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
7 7 <OutputType>Library</OutputType>
8 8 <RootNamespace>Implab</RootNamespace>
9 9 <AssemblyName>Implab</AssemblyName>
10 10 <ProductVersion>8.0.30703</ProductVersion>
11 11 <SchemaVersion>2.0</SchemaVersion>
12 12 <ReleaseVersion>0.2</ReleaseVersion>
13 13 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
14 14 </PropertyGroup>
15 15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16 16 <DebugSymbols>true</DebugSymbols>
17 17 <DebugType>full</DebugType>
18 18 <Optimize>false</Optimize>
19 19 <OutputPath>bin\Debug</OutputPath>
20 20 <DefineConstants>TRACE;DEBUG;</DefineConstants>
21 21 <ErrorReport>prompt</ErrorReport>
22 22 <WarningLevel>4</WarningLevel>
23 23 <ConsolePause>false</ConsolePause>
24 24 <RunCodeAnalysis>true</RunCodeAnalysis>
25 25 </PropertyGroup>
26 26 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
27 27 <DebugType>full</DebugType>
28 28 <Optimize>true</Optimize>
29 29 <OutputPath>bin\Release</OutputPath>
30 30 <ErrorReport>prompt</ErrorReport>
31 31 <WarningLevel>4</WarningLevel>
32 32 <ConsolePause>false</ConsolePause>
33 33 </PropertyGroup>
34 34 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
35 35 <DebugSymbols>true</DebugSymbols>
36 36 <DebugType>full</DebugType>
37 37 <Optimize>false</Optimize>
38 38 <OutputPath>bin\Debug</OutputPath>
39 39 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
40 40 <ErrorReport>prompt</ErrorReport>
41 41 <WarningLevel>4</WarningLevel>
42 42 <RunCodeAnalysis>true</RunCodeAnalysis>
43 43 <ConsolePause>false</ConsolePause>
44 44 </PropertyGroup>
45 45 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
46 46 <Optimize>true</Optimize>
47 47 <OutputPath>bin\Release</OutputPath>
48 48 <ErrorReport>prompt</ErrorReport>
49 49 <WarningLevel>4</WarningLevel>
50 50 <ConsolePause>false</ConsolePause>
51 51 <DefineConstants>NET_4_5</DefineConstants>
52 52 </PropertyGroup>
53 53 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMono|AnyCPU' ">
54 54 <DebugSymbols>true</DebugSymbols>
55 55 <DebugType>full</DebugType>
56 56 <Optimize>false</Optimize>
57 57 <OutputPath>bin\Debug</OutputPath>
58 58 <DefineConstants>TRACE;DEBUG;NET_4_5;MONO</DefineConstants>
59 59 <ErrorReport>prompt</ErrorReport>
60 60 <WarningLevel>4</WarningLevel>
61 61 <RunCodeAnalysis>true</RunCodeAnalysis>
62 62 <ConsolePause>false</ConsolePause>
63 63 </PropertyGroup>
64 64 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMono|AnyCPU' ">
65 65 <Optimize>true</Optimize>
66 66 <OutputPath>bin\Release</OutputPath>
67 67 <DefineConstants>NET_4_5;MONO;</DefineConstants>
68 68 <ErrorReport>prompt</ErrorReport>
69 69 <WarningLevel>4</WarningLevel>
70 70 <ConsolePause>false</ConsolePause>
71 71 </PropertyGroup>
72 72 <ItemGroup>
73 73 <Reference Include="System" />
74 74 <Reference Include="System.Xml" />
75 75 <Reference Include="mscorlib" />
76 76 </ItemGroup>
77 77 <ItemGroup>
78 78 <Compile Include="CustomEqualityComparer.cs" />
79 79 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
80 80 <Compile Include="Diagnostics\EventText.cs" />
81 81 <Compile Include="Diagnostics\LogChannel.cs" />
82 82 <Compile Include="Diagnostics\LogicalOperation.cs" />
83 83 <Compile Include="Diagnostics\TextFileListener.cs" />
84 84 <Compile Include="Diagnostics\TraceLog.cs" />
85 85 <Compile Include="Diagnostics\TraceEvent.cs" />
86 86 <Compile Include="Diagnostics\TraceEventType.cs" />
87 87 <Compile Include="ICancellable.cs" />
88 88 <Compile Include="IProgressHandler.cs" />
89 89 <Compile Include="IProgressNotifier.cs" />
90 90 <Compile Include="IPromiseT.cs" />
91 91 <Compile Include="IPromise.cs" />
92 92 <Compile Include="IServiceLocator.cs" />
93 93 <Compile Include="ITaskController.cs" />
94 94 <Compile Include="JSON\JSONElementContext.cs" />
95 95 <Compile Include="JSON\JSONElementType.cs" />
96 96 <Compile Include="JSON\JSONGrammar.cs" />
97 97 <Compile Include="JSON\JSONParser.cs" />
98 98 <Compile Include="JSON\JSONScanner.cs" />
99 99 <Compile Include="JSON\JsonTokenType.cs" />
100 100 <Compile Include="JSON\JSONWriter.cs" />
101 101 <Compile Include="JSON\JSONXmlReader.cs" />
102 102 <Compile Include="JSON\JSONXmlReaderOptions.cs" />
103 103 <Compile Include="JSON\StringTranslator.cs" />
104 104 <Compile Include="Parallels\DispatchPool.cs" />
105 105 <Compile Include="Parallels\ArrayTraits.cs" />
106 106 <Compile Include="Parallels\MTQueue.cs" />
107 107 <Compile Include="Parallels\WorkerPool.cs" />
108 108 <Compile Include="Parsing\Alphabet.cs" />
109 109 <Compile Include="Parsing\AlphabetBase.cs" />
110 110 <Compile Include="Parsing\AltToken.cs" />
111 111 <Compile Include="Parsing\BinaryToken.cs" />
112 112 <Compile Include="Parsing\CatToken.cs" />
113 113 <Compile Include="Parsing\CDFADefinition.cs" />
114 114 <Compile Include="Parsing\DFABuilder.cs" />
115 115 <Compile Include="Parsing\DFADefinitionBase.cs" />
116 116 <Compile Include="Parsing\DFAStateDescriptor.cs" />
117 117 <Compile Include="Parsing\DFAutomaton.cs" />
118 118 <Compile Include="Parsing\EDFADefinition.cs" />
119 119 <Compile Include="Parsing\EmptyToken.cs" />
120 120 <Compile Include="Parsing\EndToken.cs" />
121 121 <Compile Include="Parsing\EnumAlphabet.cs" />
122 122 <Compile Include="Parsing\Grammar.cs" />
123 123 <Compile Include="Parsing\IAlphabet.cs" />
124 124 <Compile Include="Parsing\IDFADefinition.cs" />
125 125 <Compile Include="Parsing\IVisitor.cs" />
126 126 <Compile Include="Parsing\ParserException.cs" />
127 127 <Compile Include="Parsing\Scanner.cs" />
128 128 <Compile Include="Parsing\StarToken.cs" />
129 129 <Compile Include="Parsing\SymbolToken.cs" />
130 130 <Compile Include="Parsing\Token.cs" />
131 131 <Compile Include="ProgressInitEventArgs.cs" />
132 132 <Compile Include="Properties\AssemblyInfo.cs" />
133 133 <Compile Include="Parallels\AsyncPool.cs" />
134 134 <Compile Include="Safe.cs" />
135 135 <Compile Include="ValueEventArgs.cs" />
136 136 <Compile Include="PromiseExtensions.cs" />
137 137 <Compile Include="SyncContextPromise.cs" />
138 138 <Compile Include="Diagnostics\OperationContext.cs" />
139 139 <Compile Include="Diagnostics\TraceContext.cs" />
140 140 <Compile Include="Diagnostics\LogEventArgs.cs" />
141 141 <Compile Include="Diagnostics\LogEventArgsT.cs" />
142 142 <Compile Include="Diagnostics\Extensions.cs" />
143 143 <Compile Include="PromiseEventType.cs" />
144 144 <Compile Include="Parallels\AsyncQueue.cs" />
145 145 <Compile Include="PromiseT.cs" />
146 146 <Compile Include="IDeferred.cs" />
147 147 <Compile Include="IDeferredT.cs" />
148 148 <Compile Include="Promise.cs" />
149 149 <Compile Include="PromiseTransientException.cs" />
150 150 <Compile Include="Parallels\Signal.cs" />
151 151 <Compile Include="Parallels\SharedLock.cs" />
152 152 <Compile Include="Diagnostics\ILogWriter.cs" />
153 153 <Compile Include="Diagnostics\ListenerBase.cs" />
154 154 <Compile Include="Parallels\BlockingQueue.cs" />
155 155 <Compile Include="AbstractEvent.cs" />
156 156 <Compile Include="AbstractPromise.cs" />
157 157 <Compile Include="AbstractPromiseT.cs" />
158 158 <Compile Include="FuncTask.cs" />
159 159 <Compile Include="FuncTaskBase.cs" />
160 160 <Compile Include="FuncTaskT.cs" />
161 161 <Compile Include="ActionChainTaskBase.cs" />
162 162 <Compile Include="ActionChainTask.cs" />
163 163 <Compile Include="ActionChainTaskT.cs" />
164 164 <Compile Include="FuncChainTaskBase.cs" />
165 165 <Compile Include="FuncChainTask.cs" />
166 166 <Compile Include="FuncChainTaskT.cs" />
167 167 <Compile Include="ActionTaskBase.cs" />
168 168 <Compile Include="ActionTask.cs" />
169 169 <Compile Include="ActionTaskT.cs" />
170 170 <Compile Include="ICancellationToken.cs" />
171 171 <Compile Include="SuccessPromise.cs" />
172 172 <Compile Include="SuccessPromiseT.cs" />
173 173 <Compile Include="PromiseAwaiterT.cs" />
174 174 <Compile Include="PromiseAwaiter.cs" />
175 175 <Compile Include="Components\ComponentContainer.cs" />
176 176 <Compile Include="Components\Disposable.cs" />
177 177 <Compile Include="Components\DisposablePool.cs" />
178 178 <Compile Include="Components\ObjectPool.cs" />
179 179 <Compile Include="Components\ServiceLocator.cs" />
180 180 <Compile Include="Components\IInitializable.cs" />
181 181 <Compile Include="TaskController.cs" />
182 182 <Compile Include="Components\App.cs" />
183 183 <Compile Include="Components\IRunnable.cs" />
184 184 <Compile Include="Components\ExecutionState.cs" />
185 <Compile Include="Components\RunnableComponent.cs" />
186 <Compile Include="Components\IFactory.cs" />
185 187 </ItemGroup>
186 188 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
187 189 <ItemGroup />
188 190 <ProjectExtensions>
189 191 <MonoDevelop>
190 192 <Properties>
191 193 <Policies>
192 194 <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" />
193 195 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
194 196 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
195 197 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
196 198 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
197 199 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
198 200 <NameConventionPolicy>
199 201 <Rules>
200 202 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
201 203 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
202 204 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
203 205 <RequiredPrefixes>
204 206 <String>I</String>
205 207 </RequiredPrefixes>
206 208 </NamingRule>
207 209 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
208 210 <RequiredSuffixes>
209 211 <String>Attribute</String>
210 212 </RequiredSuffixes>
211 213 </NamingRule>
212 214 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
213 215 <RequiredSuffixes>
214 216 <String>EventArgs</String>
215 217 </RequiredSuffixes>
216 218 </NamingRule>
217 219 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
218 220 <RequiredSuffixes>
219 221 <String>Exception</String>
220 222 </RequiredSuffixes>
221 223 </NamingRule>
222 224 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
223 225 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
224 226 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
225 227 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
226 228 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
227 229 <RequiredPrefixes>
228 230 <String>m_</String>
229 231 </RequiredPrefixes>
230 232 </NamingRule>
231 233 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
232 234 <RequiredPrefixes>
233 235 <String>_</String>
234 236 </RequiredPrefixes>
235 237 </NamingRule>
236 238 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
237 239 <RequiredPrefixes>
238 240 <String>m_</String>
239 241 </RequiredPrefixes>
240 242 </NamingRule>
241 243 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
242 244 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
243 245 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
244 246 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
245 247 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
246 248 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
247 249 <RequiredPrefixes>
248 250 <String>T</String>
249 251 </RequiredPrefixes>
250 252 </NamingRule>
251 253 </Rules>
252 254 </NameConventionPolicy>
253 255 </Policies>
254 256 </Properties>
255 257 </MonoDevelop>
256 258 </ProjectExtensions>
257 259 <ItemGroup>
258 260 <Folder Include="Components\" />
259 261 </ItemGroup>
260 262 </Project> No newline at end of file
@@ -1,103 +1,99
1 1 using Implab.Parsing;
2 using System;
3 using System.Collections.Generic;
4 2 using System.Linq;
5 using System.Text;
6 using System.Threading.Tasks;
7 3
8 4 namespace Implab.JSON {
9 internal class JSONGrammar : Grammar<JSONGrammar> {
10 public enum TokenType : int {
5 class JSONGrammar : Grammar<JSONGrammar> {
6 public enum TokenType {
11 7 None,
12 8 BeginObject,
13 9 EndObject,
14 10 BeginArray,
15 11 EndArray,
16 12 String,
17 13 Number,
18 14 Literal,
19 15 NameSeparator,
20 16 ValueSeparator,
21 17
22 18 StringBound,
23 19 EscapedChar,
24 20 UnescapedChar,
25 21 EscapedUnicode,
26 22
27 23 Minus,
28 24 Plus,
29 25 Sign,
30 26 Integer,
31 27 Dot,
32 28 Exp
33 29 }
34 30
35 31 readonly CDFADefinition m_jsonDFA;
36 32 readonly CDFADefinition m_stringDFA;
37 33
38 34 public JSONGrammar() {
39 35 DefineAlphabet(Enumerable.Range(0, 0x20).Select(x => (char)x));
40 36 var hexDigit = SymbolRangeToken('a','f').Or(SymbolRangeToken('A','F')).Or(SymbolRangeToken('0','9'));
41 37 var digit9 = SymbolRangeToken('1', '9');
42 38 var zero = SymbolToken('0');
43 39 var digit = zero.Or(digit9);
44 40 var dot = SymbolToken('.');
45 41 var minus = SymbolToken('-');
46 42 var sign = SymbolSetToken('-', '+');
47 43 var expSign = SymbolSetToken('e', 'E');
48 44 var letters = SymbolRangeToken('a', 'z');
49 45 var integer = zero.Or(digit9.Cat(digit.EClosure()));
50 46 var frac = dot.Cat(digit.Closure());
51 47 var exp = expSign.Cat(sign.Optional()).Cat(digit.Closure());
52 48 var quote = SymbolToken('"');
53 49 var backSlash = SymbolToken('\\');
54 50 var specialEscapeChars = SymbolSetToken('\\', '"', '/', 'b', 'f', 't', 'n', 'r');
55 51 var unicodeEspace = SymbolToken('u').Cat(hexDigit.Repeat(4));
56 52 var whitespace = SymbolSetToken('\n', '\r', '\t', ' ').EClosure();
57 53 var beginObject = whitespace.Cat(SymbolToken('{')).Cat(whitespace);
58 54 var endObject = whitespace.Cat(SymbolToken('}')).Cat(whitespace);
59 55 var beginArray = whitespace.Cat(SymbolToken('[')).Cat(whitespace);
60 56 var endArray = whitespace.Cat(SymbolToken(']')).Cat(whitespace);
61 57 var nameSep = whitespace.Cat(SymbolToken(':')).Cat(whitespace);
62 58 var valueSep = whitespace.Cat(SymbolToken(',')).Cat(whitespace);
63 59
64 60 var number = minus.Optional().Cat(integer).Cat(frac.Optional()).Cat(exp.Optional());
65 61 var literal = letters.Closure();
66 62 var unescaped = SymbolTokenExcept(Enumerable.Range(0, 0x20).Union(new int[] { '\\', '"' }).Select(x => (char)x));
67 63
68 64 var jsonExpression =
69 65 number.Tag(TokenType.Number)
70 66 .Or(literal.Tag(TokenType.Literal))
71 67 .Or(quote.Tag(TokenType.StringBound))
72 68 .Or(beginObject.Tag(TokenType.BeginObject))
73 69 .Or(endObject.Tag(TokenType.EndObject))
74 70 .Or(beginArray.Tag(TokenType.BeginArray))
75 71 .Or(endArray.Tag(TokenType.EndArray))
76 72 .Or(nameSep.Tag(TokenType.NameSeparator))
77 73 .Or(valueSep.Tag(TokenType.ValueSeparator));
78 74
79 75
80 76 var jsonStringExpression =
81 77 quote.Tag(TokenType.StringBound)
82 78 .Or(backSlash.Cat(specialEscapeChars).Tag(TokenType.EscapedChar))
83 79 .Or(backSlash.Cat(unicodeEspace).Tag(TokenType.EscapedUnicode))
84 80 .Or(unescaped.Closure().Tag(TokenType.UnescapedChar));
85 81
86 82
87 83 m_jsonDFA = BuildDFA(jsonExpression);
88 84 m_stringDFA = BuildDFA(jsonStringExpression);
89 85 }
90 86
91 87 public CDFADefinition JsonDFA {
92 88 get {
93 89 return m_jsonDFA;
94 90 }
95 91 }
96 92
97 93 public CDFADefinition JsonStringDFA {
98 94 get {
99 95 return m_stringDFA;
100 96 }
101 97 }
102 98 }
103 99 }
@@ -1,283 +1,277
1 using Implab;
2 using Implab.Parsing;
1 using Implab.Parsing;
3 2 using System;
4 using System.Collections.Generic;
5 3 using System.Diagnostics;
6 4 using System.IO;
7 using System.Linq;
8 using System.Text;
9 using System.Threading.Tasks;
10 5
11 6 namespace Implab.JSON {
12 7 /// <summary>
13 8 /// internal
14 9 /// </summary>
15 10 public struct JSONParserContext {
16 11 public string memberName;
17 12 public JSONElementContext elementContext;
18 13 }
19 14
20 15 /// <summary>
21 16 /// Pull парсСр JSON Π΄Π°Π½Π½Ρ‹Ρ….
22 17 /// </summary>
23 18 /// <remarks>
24 19 /// Π‘Π»Π΅Π΄ΡƒΠ΅Ρ‚ ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚Π°Ρ†ΠΈΡŽ свойства <see cref="Level"/>,
25 20 /// ΠΎΠ½ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ влоТСнности ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ², ΠΎΠ΄Π½Π°ΠΊΠΎ Π·Π°ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ
26 21 /// элСмСнт ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° ΠΈ массива ΠΈΠΌΠ΅Π΅Ρ‚ ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ мСньшС, Ρ‡Π΅ΠΌ сам ΠΎΠ±ΡŠΠ΅ΠΊΡ‚.
27 22 /// <code>
28 23 /// { // Level = 1
29 24 /// "name" : "Peter", // Level = 1
30 25 /// "address" : { // Level = 2
31 26 /// city : "Stern" // Level = 2
32 27 /// } // Level = 1
33 28 /// } // Level = 0
34 29 /// </code>
35 30 /// </remarks>
36 31 public class JSONParser : DFAutomaton<JSONParserContext>, IDisposable {
37 32
38 33 enum MemberContext {
39 34 MemberName,
40 35 MemberValue
41 36 }
42 37
43 38 static readonly EnumAlphabet<JsonTokenType> _alphabet = EnumAlphabet<JsonTokenType>.FullAlphabet;
44 39 static readonly DFAStateDescriptior[] _jsonDFA;
45 40 static readonly DFAStateDescriptior[] _objectDFA;
46 41 static readonly DFAStateDescriptior[] _arrayDFA;
47 42
48 43 static JSONParser() {
49 44
50 45
51 46 var valueExpression = Token.New(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String);
52 47 var memberExpression = Token.New(JsonTokenType.String).Cat(Token.New(JsonTokenType.NameSeparator)).Cat(valueExpression);
53 48
54 49 var objectExpression = memberExpression
55 50 .Cat(
56 51 Token.New(JsonTokenType.ValueSeparator)
57 52 .Cat(memberExpression)
58 53 .EClosure()
59 54 )
60 55 .Optional()
61 56 .Cat(Token.New(JsonTokenType.EndObject))
62 57 .Tag(0);
63 58 var arrayExpression = valueExpression
64 59 .Cat(
65 60 Token.New(JsonTokenType.ValueSeparator)
66 61 .Cat(valueExpression)
67 62 .EClosure()
68 63 )
69 64 .Optional()
70 65 .Cat(Token.New(JsonTokenType.EndArray))
71 66 .Tag(0);
72 67
73 68 var jsonExpression = valueExpression.Tag(0);
74 69
75 70 _jsonDFA = BuildDFA(jsonExpression).States;
76 71 _objectDFA = BuildDFA(objectExpression).States;
77 72 _arrayDFA = BuildDFA(arrayExpression).States;
78 73 }
79 74
80 75 static EDFADefinition<JsonTokenType> BuildDFA(Token expr) {
81 76 var builder = new DFABuilder();
82 77 var dfa = new EDFADefinition<JsonTokenType>(_alphabet);
83 78 expr.Accept(builder);
84 79
85 80 builder.BuildDFA(dfa);
86 81 return dfa;
87 82 }
88 83
89 84 JSONScanner m_scanner;
90 85 MemberContext m_memberContext;
91 86
92 87 JSONElementType m_elementType;
93 88 object m_elementValue;
94 89
95 90 /// <summary>
96 91 /// Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ Π½ΠΎΠ²Ρ‹ΠΉ парсСр Π½Π° основС строки, содСрТащСй JSON
97 92 /// </summary>
98 93 /// <param name="text"></param>
99 94 public JSONParser(string text)
100 95 : base(_jsonDFA, INITIAL_STATE, new JSONParserContext { elementContext = JSONElementContext.None, memberName = String.Empty }) {
101 96 Safe.ArgumentNotEmpty(text, "text");
102 97 m_scanner = new JSONScanner();
103 98 m_scanner.Feed(text.ToCharArray());
104 99 }
105 100
106 101 /// <summary>
107 102 /// Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ Π½ΠΎΠ²Ρ‹ΠΉ экзСмпляр парсСра, Π½Π° основС тСкстового ΠΏΠΎΡ‚ΠΎΠΊΠ°.
108 103 /// </summary>
109 104 /// <param name="reader">ВСкстовый ΠΏΠΎΡ‚ΠΎΠΊ.</param>
110 105 /// <param name="dispose">ΠŸΡ€ΠΈΠ·Π½Π°ΠΊ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ парсСр Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΊΠΎΠ½Ρ€ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ врСмя ΠΆΠΈΠ·Π½ΠΈ Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°.</param>
111 106 public JSONParser(TextReader reader, bool dispose)
112 107 : base(_jsonDFA, INITIAL_STATE, new JSONParserContext { elementContext = JSONElementContext.None, memberName = String.Empty }) {
113 108 Safe.ArgumentNotNull(reader, "reader");
114 109 m_scanner = new JSONScanner();
115 110 m_scanner.Feed(reader, dispose);
116 111 }
117 112
118 113 /// <summary>
119 114 /// Π’ΠΈΠΏ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ элСмСнта Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ стоит парсСр.
120 115 /// </summary>
121 116 public JSONElementType ElementType {
122 117 get { return m_elementType; }
123 118 }
124 119
125 120 /// <summary>
126 121 /// Имя элСмСнта - имя свойства Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°. Для элСмСнтов массивов ΠΈ ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠ³ΠΎ всСгда
127 122 /// пустая строка.
128 123 /// </summary>
129 124 public string ElementName {
130 125 get { return m_context.info.memberName; }
131 126 }
132 127
133 128 /// <summary>
134 129 /// Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ элСмСнта. Волько для элСмСнтов Ρ‚ΠΈΠΏΠ° <see cref="JSONElementType.Value"/>, для ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Ρ… <c>null</c>
135 130 /// </summary>
136 131 public object ElementValue {
137 132 get { return m_elementValue; }
138 133 }
139 134
140 135 /// <summary>
141 136 /// Π§ΠΈΡ‚Π°Π΅Ρ‚ ΡΠ»Π΅ΡŽΡƒΠ΄ΡƒΡ‰ΠΈΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΈΠ· ΠΏΠΎΡ‚ΠΎΠΊΠ°
142 137 /// </summary>
143 138 /// <returns><c>true</c> - опСрация чтСния ΠΏΡ€ΠΎΡˆΠ»Π° ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ, <c>false</c> - ΠΊΠΎΠ½Π΅Ρ† Π΄Π°Π½Π½Ρ‹Ρ…</returns>
144 139 public bool Read() {
145 140 if (m_context.current == UNREACHEBLE_STATE)
146 141 throw new InvalidOperationException("The parser is in invalid state");
147 142 object tokenValue;
148 143 JsonTokenType tokenType;
149 144 m_context.info.memberName = String.Empty;
150 145 while (m_scanner.ReadToken(out tokenValue, out tokenType)) {
151 146 Move((int)tokenType);
152 147 if (m_context.current == UNREACHEBLE_STATE)
153 148 UnexpectedToken(tokenValue, tokenType);
154 149 switch (tokenType) {
155 150 case JsonTokenType.BeginObject:
156 151 Switch(
157 152 _objectDFA,
158 153 INITIAL_STATE,
159 154 new JSONParserContext {
160 155 memberName = m_context.info.memberName,
161 156 elementContext = JSONElementContext.Object
162 157 }
163 158 );
164 159 m_elementValue = null;
165 160 m_memberContext = MemberContext.MemberName;
166 161 m_elementType = JSONElementType.BeginObject;
167 162 return true;
168 163 case JsonTokenType.EndObject:
169 164 Restore();
170 165 m_elementValue = null;
171 166 m_elementType = JSONElementType.EndObject;
172 167 return true;
173 168 case JsonTokenType.BeginArray:
174 169 Switch(
175 170 _arrayDFA,
176 171 INITIAL_STATE,
177 172 new JSONParserContext {
178 173 memberName = m_context.info.memberName,
179 174 elementContext = JSONElementContext.Array
180 175 }
181 176 );
182 177 m_elementValue = null;
183 178 m_memberContext = MemberContext.MemberValue;
184 179 m_elementType = JSONElementType.BeginArray;
185 180 return true;
186 181 case JsonTokenType.EndArray:
187 182 Restore();
188 183 m_elementValue = null;
189 184 m_elementType = JSONElementType.EndArray;
190 185 return true;
191 186 case JsonTokenType.String:
192 187 if (m_memberContext == MemberContext.MemberName) {
193 188 m_context.info.memberName = (string)tokenValue;
194 189 break;
195 } else {
196 m_elementType = JSONElementType.Value;
197 m_elementValue = tokenValue;
198 return true;
199 190 }
191 m_elementType = JSONElementType.Value;
192 m_elementValue = tokenValue;
193 return true;
200 194 case JsonTokenType.Number:
201 195 m_elementType = JSONElementType.Value;
202 196 m_elementValue = tokenValue;
203 197 return true;
204 198 case JsonTokenType.Literal:
205 199 m_elementType = JSONElementType.Value;
206 200 m_elementValue = ParseLiteral((string)tokenValue);
207 201 return true;
208 202 case JsonTokenType.NameSeparator:
209 203 m_memberContext = MemberContext.MemberValue;
210 204 break;
211 205 case JsonTokenType.ValueSeparator:
212 206 m_memberContext = m_context.info.elementContext == JSONElementContext.Object ? MemberContext.MemberName : MemberContext.MemberValue;
213 207 break;
214 208 default:
215 209 UnexpectedToken(tokenValue, tokenType);
216 210 break;
217 211 }
218 212 }
219 213 if (m_context.info.elementContext != JSONElementContext.None)
220 214 throw new ParserException("Unexpedted end of data");
221 215 return false;
222 216 }
223 217
224 218 object ParseLiteral(string literal) {
225 219 switch (literal) {
226 220 case "null":
227 221 return null;
228 222 case "false":
229 223 return false;
230 224 case "true":
231 225 return true;
232 226 default:
233 227 UnexpectedToken(literal, JsonTokenType.Literal);
234 228 return null; // avoid compliler error
235 229 }
236 230 }
237 231
238 232 void UnexpectedToken(object value, JsonTokenType tokenType) {
239 233 throw new ParserException(String.Format("Unexpected token {0}: '{1}'", tokenType, value));
240 234 }
241 235
242 236
243 237 /// <summary>
244 238 /// ΠŸΡ€ΠΈΠ·Π½Π°ΠΊ ΠΊΠΎΠ½Ρ†Π° ΠΏΠΎΡ‚ΠΎΠΊΠ°
245 239 /// </summary>
246 240 public bool EOF {
247 241 get {
248 242 return m_scanner.EOF;
249 243 }
250 244 }
251 245
252 246 protected virtual void Dispose(bool disposing) {
253 247 if (disposing) {
254 248 m_scanner.Dispose();
255 249 }
256 250 }
257 251
258 252 /// <summary>
259 253 /// ΠžΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Π΅Ρ‚ парсСр ΠΈ связанный с Π½ΠΈΠΌ сканнСр.
260 254 /// </summary>
261 255 public void Dispose() {
262 256 Dispose(true);
263 257 GC.SuppressFinalize(this);
264 258 }
265 259
266 260 ~JSONParser() {
267 261 Dispose(false);
268 262 }
269 263
270 264 /// <summary>
271 265 /// ΠŸΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚ Π² ΠΊΠΎΠ½Π΅Ρ† Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°.
272 266 /// </summary>
273 267 public void SeekElementEnd() {
274 268 var level = Level - 1;
275 269
276 270 Debug.Assert(level >= 0);
277 271
278 272 while (Level != level)
279 273 Read();
280 274 }
281 275 }
282 276
283 277 }
@@ -1,100 +1,100
1 1 using Implab;
2 2 using System;
3 3 using System.Collections.Generic;
4 4 using System.Diagnostics;
5 5 using System.Linq;
6 6 using System.Text;
7 7 using System.Threading.Tasks;
8 8
9 9 namespace Implab.Parsing {
10 10 public abstract class AlphabetBase<T> : IAlphabet<T> {
11 11 public const int UNCLASSIFIED = 0;
12 12
13 13 int m_nextId = 1;
14 int[] m_map;
14 readonly int[] m_map;
15 15
16 16 public int Count {
17 17 get { return m_nextId; }
18 18 }
19 19
20 20 protected AlphabetBase(int mapSize) {
21 21 m_map = new int[mapSize];
22 22 }
23 23
24 24 protected AlphabetBase(int[] map) {
25 25 Debug.Assert(map != null);
26 26
27 27 m_map = map;
28 28 m_nextId = map.Max() + 1;
29 29 }
30 30
31 31 public int DefineSymbol(T symbol) {
32 32 var index = GetSymbolIndex(symbol);
33 33 if (m_map[index] == UNCLASSIFIED)
34 34 m_map[index] = m_nextId++;
35 35 return m_map[index];
36 36 }
37 37
38 38 public int DefineClass(IEnumerable<T> symbols) {
39 39 Safe.ArgumentNotNull(symbols, "symbols");
40 40 symbols = symbols.Distinct();
41 41
42 42 foreach (var symbol in symbols) {
43 43 var index = GetSymbolIndex(symbol);
44 44 if (m_map[index] == UNCLASSIFIED)
45 45 m_map[GetSymbolIndex(symbol)] = m_nextId;
46 46 else
47 47 throw new InvalidOperationException(String.Format("Symbol '{0}' already in use", symbol));
48 48 }
49 49 return m_nextId++;
50 50 }
51 51
52 52 public List<T>[] CreateReverseMap() {
53 53 return
54 54 Enumerable.Range(UNCLASSIFIED, Count)
55 55 .Select(
56 56 i => InputSymbols
57 57 .Where(x => i != UNCLASSIFIED && m_map[GetSymbolIndex(x)] == i)
58 58 .ToList()
59 59 )
60 60 .ToArray();
61 61 }
62 62
63 63 public int[] Reclassify(IAlphabet<T> newAlphabet, IEnumerable<ICollection<int>> classes) {
64 64 Safe.ArgumentNotNull(newAlphabet, "newAlphabet");
65 65 Safe.ArgumentNotNull(classes, "classes");
66 66 var reverseMap = CreateReverseMap();
67 67
68 68 int[] translationMap = new int[Count];
69 69
70 70 foreach (var scl in classes) {
71 71 // skip if the supper class contains the unclassified element
72 72 if (scl.Contains(UNCLASSIFIED))
73 73 continue;
74 74 var range = new List<T>();
75 75 foreach (var cl in scl) {
76 76 if (cl < 0 || cl >= reverseMap.Length)
77 77 throw new ArgumentOutOfRangeException(String.Format("Class {0} is not valid for the current alphabet", cl));
78 78 range.AddRange(reverseMap[cl]);
79 79 }
80 80 var newClass = newAlphabet.DefineClass(range);
81 81 foreach (var cl in scl)
82 82 translationMap[cl] = newClass;
83 83 }
84 84
85 85 return translationMap;
86 86 }
87 87
88 88 public int Translate(T symbol) {
89 89 return m_map[GetSymbolIndex(symbol)];
90 90 }
91 91
92 92 public abstract int GetSymbolIndex(T symbol);
93 93
94 94 public abstract IEnumerable<T> InputSymbols { get; }
95 95
96 96 public int[] GetTranslationMap() {
97 97 return m_map;
98 98 }
99 99 }
100 100 }
@@ -1,22 +1,17
1 using Implab;
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6 using System.Threading.Tasks;
1 using System;
7 2
8 3 namespace Implab.Parsing {
9 4 public class AltToken: BinaryToken {
10 5 public AltToken(Token left, Token right)
11 6 : base(left, right) {
12 7 }
13 8
14 9 public override void Accept(IVisitor visitor) {
15 10 Safe.ArgumentNotNull(visitor, "visitor");
16 11 visitor.Visit(this);
17 12 }
18 13 public override string ToString() {
19 14 return String.Format(Right is BinaryToken ? "{0}|({1})" : "{0}|{1}", Left, Right);
20 15 }
21 16 }
22 17 }
@@ -1,36 +1,36
1 1 using Implab;
2 2 using System;
3 3 using System.Collections.Generic;
4 4 using System.Linq;
5 5 using System.Text;
6 6 using System.Threading.Tasks;
7 7
8 8 namespace Implab.Parsing {
9 9 public class CDFADefinition : DFADefinitionBase {
10 Alphabet m_alphabet;
10 readonly Alphabet m_alphabet;
11 11
12 12 public Alphabet Alphabet {
13 13 get { return m_alphabet; }
14 14 }
15 15
16 16 public override int AlphabetSize {
17 17 get { return m_alphabet.Count; }
18 18 }
19 19
20 20 public CDFADefinition(Alphabet alphabet): base() {
21 21 Safe.ArgumentNotNull(alphabet, "alphabet");
22 22 m_alphabet = alphabet;
23 23 }
24 24
25 25 public CDFADefinition Optimize() {
26 26 var optimized = new CDFADefinition(new Alphabet());
27 27
28 28 Optimize(optimized, m_alphabet, optimized.Alphabet);
29 29 return optimized;
30 30 }
31 31
32 32 public void PrintDFA() {
33 33 PrintDFA(m_alphabet);
34 34 }
35 35 }
36 36 }
@@ -1,27 +1,22
1 using Implab;
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6 using System.Threading.Tasks;
1 using System;
7 2
8 3 namespace Implab.Parsing {
9 4 public class CatToken : BinaryToken {
10 5 public CatToken(Token left, Token right)
11 6 : base(left, right) {
12 7 }
13 8
14 9 public override void Accept(IVisitor visitor) {
15 10 Safe.ArgumentNotNull(visitor, "visitor");
16 11 visitor.Visit(this);
17 12 }
18 13
19 14 public override string ToString() {
20 15 return String.Format("{0}{1}", FormatToken(Left), FormatToken(Right));
21 16 }
22 17
23 18 string FormatToken(Token token) {
24 19 return String.Format(token is AltToken ? "({0})" : "{0}", token);
25 20 }
26 21 }
27 22 }
@@ -1,182 +1,182
1 1 using Implab;
2 2 using System;
3 3 using System.Collections.Generic;
4 4 using System.Diagnostics;
5 5 using System.Linq;
6 6 using System.Text;
7 7 using System.Threading.Tasks;
8 8
9 9 namespace Implab.Parsing {
10 10 /// <summary>
11 11 /// Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для построСния Π”ΠšΠ ΠΏΠΎ рСгулярному Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΡŽ, сначала ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΡ‚
12 12 /// рСгулярноС Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΈ вычисляСт followpos, Π·Π°Ρ‚Π΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΌΠ΅Ρ‚ΠΎΠ΄
13 13 /// <see cref="BuildDFA(IDFADefinition)"/> для построСния Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚Π°.
14 14 /// </summary>
15 15 public class DFABuilder : IVisitor {
16 16 int m_idx = 0;
17 17 Token m_root;
18 18 HashSet<int> m_firstpos;
19 19 HashSet<int> m_lastpos;
20 20
21 21 Dictionary<int, HashSet<int>> m_followpos = new Dictionary<int, HashSet<int>>();
22 22 Dictionary<int, int> m_indexes = new Dictionary<int, int>();
23 23 Dictionary<int, int> m_ends = new Dictionary<int, int>();
24 24
25 25 public Dictionary<int, HashSet<int>> FollowposMap {
26 26 get { return m_followpos; }
27 27 }
28 28
29 29 public HashSet<int> Followpos(int pos) {
30 30 HashSet<int> set;
31 31 if (m_followpos.TryGetValue(pos, out set))
32 32 return set;
33 33 return m_followpos[pos] = new HashSet<int>();
34 34 }
35 35
36 36 bool Nullable(object n) {
37 37 if (n is EmptyToken || n is StarToken)
38 38 return true;
39 39 if (n is AltToken)
40 40 return Nullable(((AltToken)n).Left) || Nullable(((AltToken)n).Right);
41 41 if (n is CatToken)
42 42 return Nullable(((CatToken)n).Left) && Nullable(((CatToken)n).Right);
43 43 return false;
44 44 }
45 45
46 46
47 47 public void Visit(AltToken token) {
48 48 if (m_root == null)
49 49 m_root = token;
50 50 var firtspos = new HashSet<int>();
51 51 var lastpos = new HashSet<int>();
52 52
53 53 token.Left.Accept(this);
54 54 firtspos.UnionWith(m_firstpos);
55 55 lastpos.UnionWith(m_lastpos);
56 56
57 57 token.Right.Accept(this);
58 58 firtspos.UnionWith(m_firstpos);
59 59 lastpos.UnionWith(m_lastpos);
60 60
61 61 m_firstpos = firtspos;
62 62 m_lastpos = lastpos;
63 63 }
64 64
65 65 public void Visit(StarToken token) {
66 66 if (m_root == null)
67 67 m_root = token;
68 68 token.Token.Accept(this);
69 69
70 70 foreach (var i in m_lastpos)
71 71 Followpos(i).UnionWith(m_firstpos);
72 72 }
73 73
74 74 public void Visit(CatToken token) {
75 75 if (m_root == null)
76 76 m_root = token;
77 77
78 78 var firtspos = new HashSet<int>();
79 79 var lastpos = new HashSet<int>();
80 80 token.Left.Accept(this);
81 81 firtspos.UnionWith(m_firstpos);
82 82 var leftLastpos = m_lastpos;
83 83
84 84 token.Right.Accept(this);
85 85 lastpos.UnionWith(m_lastpos);
86 86 var rightFirstpos = m_firstpos;
87 87
88 88 if (Nullable(token.Left))
89 89 firtspos.UnionWith(rightFirstpos);
90 90
91 91 if (Nullable(token.Right))
92 92 lastpos.UnionWith(leftLastpos);
93 93
94 94 m_firstpos = firtspos;
95 95 m_lastpos = lastpos;
96 96
97 97 foreach (var i in leftLastpos)
98 98 Followpos(i).UnionWith(rightFirstpos);
99 99
100 100 }
101 101
102 102 public void Visit(EmptyToken token) {
103 103 if (m_root == null)
104 104 m_root = token;
105 105 ;
106 106 }
107 107
108 108 public void Visit(SymbolToken token) {
109 109 if (m_root == null)
110 110 m_root = token;
111 111 m_idx++;
112 112 m_indexes[m_idx] = token.Value;
113 113 m_firstpos = new HashSet<int>(new[] { m_idx });
114 114 m_lastpos = new HashSet<int>(new[] { m_idx });
115 115 }
116 116
117 117 public void Visit(EndToken token) {
118 118 if (m_root == null)
119 119 m_root = token;
120 120 m_idx++;
121 121 m_indexes[m_idx] = Alphabet.UNCLASSIFIED;
122 122 m_firstpos = new HashSet<int>(new[] { m_idx });
123 123 m_lastpos = new HashSet<int>(new[] { m_idx });
124 124 Followpos(m_idx);
125 125 m_ends.Add(m_idx, token.Tag);
126 126 }
127 127
128 128 public void BuildDFA(IDFADefinition dfa) {
129 129 Safe.ArgumentNotNull(dfa,"dfa");
130 130
131 131 var stateMap = new Dictionary<HashSet<int>, int>(new CustomEqualityComparer<HashSet<int>>(
132 132 (x, y) => x.SetEquals(y),
133 133 (x) => x.Sum(n => n.GetHashCode())
134 134 ));
135 135
136 136 stateMap[m_firstpos] = DefineState( dfa, m_firstpos);
137 137 Debug.Assert(stateMap[m_firstpos] == DFADefinitionBase.INITIAL_STATE);
138 138
139 139 var queue = new Queue<HashSet<int>>();
140 140
141 141 queue.Enqueue(m_firstpos);
142 142
143 143 while (queue.Count > 0) {
144 144 var state = queue.Dequeue();
145 145 var s1 = stateMap[state];
146 146
147 147 for (int a = 0; a < dfa.AlphabetSize; a++) {
148 148 var next = new HashSet<int>();
149 149 foreach (var p in state) {
150 150 if (m_indexes[p] == a) {
151 151 next.UnionWith(Followpos(p));
152 152 }
153 153 }
154 154 if (next.Count > 0) {
155 155 int s2;
156 156 if (!stateMap.TryGetValue(next, out s2)) {
157 157 stateMap[next] = s2 = DefineState(dfa, next);
158 158 queue.Enqueue(next);
159 159 }
160 160 dfa.DefineTransition(s1, s2, a);
161 161 }
162 162 }
163 163
164 164 }
165 165 }
166 166
167 167 int[] GetStateTags(HashSet<int> state) {
168 168 Debug.Assert(state != null);
169 return state.Where(pos => m_ends.ContainsKey(pos)).Select(pos => m_ends[pos]).ToArray();
169 return state.Where(m_ends.ContainsKey).Select(pos => m_ends[pos]).ToArray();
170 170 }
171 171
172 172 int DefineState(IDFADefinition automa, HashSet<int> state) {
173 173 Debug.Assert(automa != null);
174 174 Debug.Assert(state != null);
175 175
176 176 var tags = GetStateTags(state);
177 177
178 178 return tags.Length > 0 ? automa.AddState(tags) : automa.AddState();
179 179 }
180 180
181 181 }
182 182 }
@@ -1,262 +1,260
1 1 using Implab;
2 2 using System;
3 3 using System.Collections.Generic;
4 4 using System.Diagnostics;
5 5 using System.Linq;
6 6 using System.Text;
7 7 using System.Threading.Tasks;
8 8
9 9 namespace Implab.Parsing {
10 10 public abstract class DFADefinitionBase : IDFADefinition {
11 11 readonly List<DFAStateDescriptior> m_states;
12 12
13 13 public const int INITIAL_STATE = 1;
14 14 public const int UNREACHEBLE_STATE = 0;
15 15
16 16 DFAStateDescriptior[] m_statesArray;
17 17
18 public DFADefinitionBase() {
18 protected DFADefinitionBase() {
19 19 m_states = new List<DFAStateDescriptior>();
20 20
21 21 m_states.Add(new DFAStateDescriptior());
22 22 }
23 23
24 24 public DFAStateDescriptior[] States {
25 25 get {
26 26 if (m_statesArray == null)
27 27 m_statesArray = m_states.ToArray();
28 28 return m_statesArray;
29 29 }
30 30 }
31 31
32 32 public bool InitialStateIsFinal {
33 33 get {
34 34 return m_states[INITIAL_STATE].final;
35 35 }
36 36 }
37 37
38 38 public int AddState() {
39 39 var index = m_states.Count;
40 40 m_states.Add(new DFAStateDescriptior {
41 41 final = false,
42 42 transitions = new int[AlphabetSize]
43 43 });
44 44
45 45 return index;
46 46 }
47 47
48 48 public int AddState(int[] tag) {
49 49 var index = m_states.Count;
50 bool final = tag == null || tag.Length == 0 ? false : true;
50 bool final = tag != null && tag.Length != 0;
51 51 m_states.Add(new DFAStateDescriptior {
52 52 final = final,
53 53 transitions = new int[AlphabetSize],
54 54 tag = final ? tag : null
55 55 });
56 56 return index;
57 57 }
58 58
59 59 public void DefineTransition(int s1,int s2, int symbol) {
60 60 Safe.ArgumentInRange(s1, 0, m_states.Count-1, "s1");
61 61 Safe.ArgumentInRange(s2, 0, m_states.Count-1, "s2");
62 62 Safe.ArgumentInRange(symbol, 0, AlphabetSize-1, "symbol");
63 63
64 64 m_states[s1].transitions[symbol] = s2;
65 65 }
66 66
67 67 protected void Optimize<TA>(IDFADefinition minimalDFA,IAlphabet<TA> sourceAlphabet, IAlphabet<TA> minimalAlphabet) {
68 68 Safe.ArgumentNotNull(minimalDFA, "minimalDFA");
69 69 Safe.ArgumentNotNull(minimalAlphabet, "minimalAlphabet");
70 70
71 71 var setComparer = new CustomEqualityComparer<HashSet<int>>(
72 72 (x, y) => x.SetEquals(y),
73 73 (s) => s.Sum(x => x.GetHashCode())
74 74 );
75 75
76 76 var arrayComparer = new CustomEqualityComparer<int[]>(
77 77 (x,y) => (new HashSet<int>(x)).SetEquals(new HashSet<int>(y)),
78 78 (a) => a.Sum(x => x.GetHashCode())
79 79 );
80 80
81 81 var optimalStates = new HashSet<HashSet<int>>(setComparer);
82 82 var queue = new HashSet<HashSet<int>>(setComparer);
83 83
84 84 foreach (var g in Enumerable
85 85 .Range(INITIAL_STATE, m_states.Count-1)
86 86 .Select(i => new {
87 87 index = i,
88 88 descriptor = m_states[i]
89 89 })
90 90 .Where(x => x.descriptor.final)
91 91 .GroupBy(x => x.descriptor.tag, arrayComparer)
92 92 ) {
93 93 optimalStates.Add(new HashSet<int>(g.Select(x => x.index)));
94 94 }
95 95
96 96 var state = new HashSet<int>(
97 97 Enumerable
98 98 .Range(INITIAL_STATE, m_states.Count - 1)
99 99 .Where(i => !m_states[i].final)
100 100 );
101 101 optimalStates.Add(state);
102 102 queue.Add(state);
103 103
104 104 while (queue.Count > 0) {
105 105 var stateA = queue.First();
106 106 queue.Remove(stateA);
107 107
108 108 for (int c = 0; c < AlphabetSize; c++) {
109 109 var stateX = new HashSet<int>();
110 110
111 111 for(int s = 1; s < m_states.Count; s++) {
112 112 if (stateA.Contains(m_states[s].transitions[c]))
113 113 stateX.Add(s);
114 114 }
115 115
116 116 foreach (var stateY in optimalStates.ToArray()) {
117 117 if (stateX.Overlaps(stateY) && !stateY.IsSubsetOf(stateX)) {
118 118 var stateR1 = new HashSet<int>(stateY);
119 119 var stateR2 = new HashSet<int>(stateY);
120 120
121 121 stateR1.IntersectWith(stateX);
122 122 stateR2.ExceptWith(stateX);
123 123
124 124 optimalStates.Remove(stateY);
125 125 optimalStates.Add(stateR1);
126 126 optimalStates.Add(stateR2);
127 127
128 128 if (queue.Contains(stateY)) {
129 129 queue.Remove(stateY);
130 130 queue.Add(stateR1);
131 131 queue.Add(stateR2);
132 132 } else {
133 133 queue.Add(stateR1.Count <= stateR2.Count ? stateR1 : stateR2);
134 134 }
135 135 }
136 136 }
137 137 }
138 138 }
139 139
140 140 // строим ΠΊΠ°Ρ€Ρ‚Ρ‹ соотвСствия ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹Ρ… состояний с ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½Ρ‹ΠΌΠΈ
141 141
142 var initialState = optimalStates.Where(x => x.Contains(INITIAL_STATE)).Single();
142 var initialState = optimalStates.Single(x => x.Contains(INITIAL_STATE));
143 143
144 144 // ΠΊΠ°Ρ€Ρ‚Π° получСния ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ состояния ΠΏΠΎ ΡΠΎΠΎΡ‚Π²Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΌΡƒ Π΅ΠΌΡƒ простому ΡΠΎΡΡ‚ΠΎΡΠ½ΠΈΡŽ
145 145 int[] reveseOptimalMap = new int[m_states.Count];
146 146 // ΠΊΠ°Ρ€Ρ‚Π° с индСксами ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹Ρ… состояний
147 147 HashSet<int>[] optimalMap = new HashSet<int>[optimalStates.Count + 1];
148 148 {
149 149 optimalMap[0] = new HashSet<int>(); // unreachable state
150 150 optimalMap[1] = initialState; // initial state
151 151 foreach (var ss in initialState)
152 152 reveseOptimalMap[ss] = 1;
153 153
154 154 int i = 2;
155 155 foreach (var s in optimalStates) {
156 156 if (s.SetEquals(initialState))
157 157 continue;
158 158 optimalMap[i] = s;
159 159 foreach (var ss in s)
160 160 reveseOptimalMap[ss] = i;
161 161 i++;
162 162 }
163 163 }
164 164
165 165 // ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ Π°Π»Ρ„Π°Π²ΠΈΡ‚
166 166
167 167 var minClasses = new HashSet<HashSet<int>>(setComparer);
168 168 var alphaQueue = new Queue<HashSet<int>>();
169 169 alphaQueue.Enqueue(new HashSet<int>(Enumerable.Range(0,AlphabetSize)));
170 170
171 171 for (int s = 1 ; s < optimalMap.Length; s++) {
172 172 var newQueue = new Queue<HashSet<int>>();
173 173
174 174 foreach (var A in alphaQueue) {
175 175 if (A.Count == 1) {
176 176 minClasses.Add(A);
177 177 continue;
178 178 }
179 179
180 180 // Ρ€Π°Π·Π»ΠΈΡ‡Π°Π΅ΠΌ классы символов, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ пСрСводят Π² Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹Π΅ состояния
181 181 // optimalState -> alphaClass
182 182 var classes = new Dictionary<int, HashSet<int>>();
183 183
184 184 foreach (var term in A) {
185 185 // ΠΈΡ‰Π΅ΠΌ всС ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Ρ‹ класса ΠΏΠΎ символу term
186 186 var s2 = reveseOptimalMap[
187 optimalMap[s].Select(x => m_states[x].transitions[term]) // всС элСмСнтарныС состояния, ΠΊΡƒΠ΄Π° ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚ класс s
188 .Where(x => x != 0) // Ρ‚ΠΎΠ»ΡŒΠΊΠΎ допустимыС
189 .FirstOrDefault() // ΠΏΠ΅Ρ€Π²ΠΎΠ΅ допустимоС элСмСнтарноС состояниС, Ссли Π΅ΡΡ‚ΡŒ
190 ];
187 optimalMap[s].Select(x => m_states[x].transitions[term]).FirstOrDefault(x => x != 0) // ΠΏΠ΅Ρ€Π²ΠΎΠ΅ допустимоС элСмСнтарноС состояниС, Ссли Π΅ΡΡ‚ΡŒ
188 ];
191 189
192 190 HashSet<int> A2;
193 191 if (!classes.TryGetValue(s2, out A2)) {
194 192 A2 = new HashSet<int>();
195 193 newQueue.Enqueue(A2);
196 194 classes[s2] = A2;
197 195 }
198 196 A2.Add(term);
199 197 }
200 198 }
201 199
202 200 if (newQueue.Count == 0)
203 201 break;
204 202 alphaQueue = newQueue;
205 203 }
206 204
207 205 foreach (var A in alphaQueue)
208 206 minClasses.Add(A);
209 207
210 208 var alphabetMap = sourceAlphabet.Reclassify(minimalAlphabet, minClasses);
211 209
212 210 // построСниС Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚Π°
213 211
214 212 var states = new int[ optimalMap.Length ];
215 213 states[0] = UNREACHEBLE_STATE;
216 214
217 215 for(var s = INITIAL_STATE; s < states.Length; s++) {
218 216 var tags = optimalMap[s].SelectMany(x => m_states[x].tag ?? Enumerable.Empty<int>()).Distinct().ToArray();
219 217 if (tags.Length > 0)
220 218 states[s] = minimalDFA.AddState(tags);
221 219 else
222 220 states[s] = minimalDFA.AddState();
223 221 }
224 222
225 223 Debug.Assert(states[INITIAL_STATE] == INITIAL_STATE);
226 224
227 225 for (int s1 = 1; s1 < m_states.Count; s1++) {
228 226 for (int c = 0; c < AlphabetSize; c++) {
229 227 var s2 = m_states[s1].transitions[c];
230 228 if (s2 != UNREACHEBLE_STATE) {
231 229 minimalDFA.DefineTransition(
232 230 reveseOptimalMap[s1],
233 231 reveseOptimalMap[s2],
234 232 alphabetMap[c]
235 233 );
236 234 }
237 235 }
238 236 }
239 237
240 238 }
241 239
242 240 protected void PrintDFA<TA>(IAlphabet<TA> alphabet) {
243 241
244 242 var reverseMap = alphabet.CreateReverseMap();
245 243
246 244 for (int i = 1; i < reverseMap.Length; i++) {
247 245 Console.WriteLine("C{0}: {1}", i, String.Join(",", reverseMap[i]));
248 246 }
249 247
250 248 for (int i = 1; i < m_states.Count; i++) {
251 249 var s = m_states[i];
252 250 for (int c = 0; c < AlphabetSize; c++)
253 251 if (s.transitions[c] != UNREACHEBLE_STATE)
254 252 Console.WriteLine("S{0} -{1}-> S{2}{3}", i, String.Join(",", reverseMap[c]), s.transitions[c], m_states[s.transitions[c]].final ? "$" : "");
255 253 }
256 254 }
257 255
258 256 public abstract int AlphabetSize {
259 257 get;
260 258 }
261 259 }
262 260 }
@@ -1,56 +1,61
1 1 using Implab;
2 2 using System;
3 3 using System.Collections.Generic;
4 4 using System.Diagnostics;
5 5 using System.Linq;
6 6 using System.Text;
7 7 using System.Threading.Tasks;
8 8
9 9 namespace Implab.Parsing {
10 10 public abstract class DFAutomaton<T> {
11 11 protected struct ContextFrame {
12 12 public DFAStateDescriptior[] states;
13 13 public int current;
14 14 public T info;
15 15 }
16 16
17 17 public const int INITIAL_STATE = DFADefinitionBase.INITIAL_STATE;
18 18 public const int UNREACHEBLE_STATE = DFADefinitionBase.UNREACHEBLE_STATE;
19 19
20 20 protected ContextFrame m_context;
21 21 Stack<ContextFrame> m_contextStack = new Stack<ContextFrame>();
22 22
23 23 protected int Level {
24 24 get { return m_contextStack.Count; }
25 25 }
26 26
27 27 protected DFAutomaton(DFAStateDescriptior[] states, int startState, T info) {
28 28 Safe.ArgumentNotNull(states, "states");
29 29 Safe.ArgumentInRange(startState, 0, states.Length - 1, "startState");
30 30
31 31 m_context.states = states;
32 32 m_context.current = startState;
33 33 m_context.info = info;
34 34 }
35 35
36 36 protected void Switch(DFAStateDescriptior[] states, int current, T info) {
37 37 Debug.Assert(states != null);
38 38 Debug.Assert(current >= 0 && current < states.Length);
39 39 m_contextStack.Push(m_context);
40 m_context. states = states;
40 m_context.states = states;
41 41 m_context.current = current;
42 42 m_context.info = info;
43 43 }
44 44
45 45 protected void Restore() {
46 46 Debug.Assert(m_contextStack.Count > 0);
47 47
48 48 m_context = m_contextStack.Pop();
49 49 }
50 50
51 51 protected void Move(int input) {
52 52 Debug.Assert(input > 0 && input < m_context.states[m_context.current].transitions.Length);
53 53 m_context.current = m_context.states[m_context.current].transitions[input];
54 54 }
55
56 protected bool CanMove(int input) {
57 Debug.Assert(input > 0 && input < m_context.states[m_context.current].transitions.Length);
58 return m_context.states[m_context.current].transitions[input] != UNREACHEBLE_STATE;
59 }
55 60 }
56 61 }
@@ -1,37 +1,32
1 1 using Implab;
2 2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6 using System.Threading.Tasks;
7 3
8 4 namespace Implab.Parsing {
9 5 public class EDFADefinition<T> : DFADefinitionBase where T : struct, IConvertible {
10 EnumAlphabet<T> m_alphabet;
6 readonly EnumAlphabet<T> m_alphabet;
11 7
12 8 public EnumAlphabet<T> Alphabet {
13 9 get { return m_alphabet; }
14 10 }
15 11
16 public EDFADefinition(EnumAlphabet<T> alphabet)
17 : base() {
12 public EDFADefinition(EnumAlphabet<T> alphabet) {
18 13 Safe.ArgumentNotNull(alphabet, "alphabet");
19 14 m_alphabet = alphabet;
20 15 }
21 16
22 17 public override int AlphabetSize {
23 18 get { return m_alphabet.Count; }
24 19 }
25 20
26 21 public EDFADefinition<T> Optimize() {
27 22 var optimized = new EDFADefinition<T>(new EnumAlphabet<T>());
28 23 Optimize(optimized, m_alphabet, optimized.Alphabet);
29 24
30 25 return optimized;
31 26 }
32 27
33 28 public void PrintDFA() {
34 29 PrintDFA(m_alphabet);
35 30 }
36 31 }
37 32 }
@@ -1,68 +1,67
1 using Implab;
2 using System;
1 using System;
3 2 using System.Collections.Generic;
4 3 using System.Diagnostics;
5 4 using System.Globalization;
6 5 using System.Linq;
7 using System.Text;
8 using System.Threading.Tasks;
6 using System.Diagnostics.CodeAnalysis;
9 7
10 8 namespace Implab.Parsing {
11 9 /// <summary>
12 10 /// Алфавит символами ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ ΡΠ²Π»ΡΡŽΡ‚ΡΡ элСмСнты пСрСчислСний.
13 11 /// </summary>
14 12 /// <typeparam name="T">Π’ΠΈΠΏ пСрСчислСний</typeparam>
15 13 public class EnumAlphabet<T> : AlphabetBase<T> where T : struct, IConvertible {
14 [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
16 15 static readonly T[] _symbols;
17 16 static readonly EnumAlphabet<T> _fullAlphabet;
18 17
19 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
18 [SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
20 19 static EnumAlphabet() {
21 20 if (!typeof(T).IsEnum)
22 21 throw new InvalidOperationException("Invalid generic parameter, enumeration is required");
23 22
24 23 if (Enum.GetUnderlyingType(typeof(T)) != typeof(Int32))
25 24 throw new InvalidOperationException("Only enums based on Int32 are supported");
26 25
27 26 _symbols = ((T[])Enum.GetValues(typeof(T)))
28 27 .OrderBy(x => x.ToInt32(CultureInfo.InvariantCulture))
29 28 .ToArray();
30 29
31 30 if (
32 31 _symbols[_symbols.Length - 1].ToInt32(CultureInfo.InvariantCulture) >= _symbols.Length
33 32 || _symbols[0].ToInt32(CultureInfo.InvariantCulture) != 0
34 33 )
35 34 throw new InvalidOperationException("The specified enumeration must be zero-based and continuously numbered");
36 35
37 36 _fullAlphabet = new EnumAlphabet<T>(_symbols.Select(x => x.ToInt32(CultureInfo.InvariantCulture)).ToArray());
38 37 }
39 38
40 39
41 40
42 41 public static EnumAlphabet<T> FullAlphabet {
43 42 get {
44 43 return _fullAlphabet;
45 44 }
46 45 }
47 46
48 47
49 48 public EnumAlphabet()
50 49 : base(_symbols.Length) {
51 50 }
52 51
53 52 public EnumAlphabet(int[] map)
54 53 : base(map) {
55 54 Debug.Assert(map.Length == _symbols.Length);
56 55 }
57 56
58 57
59 58 public override int GetSymbolIndex(T symbol) {
60 59 return symbol.ToInt32(CultureInfo.InvariantCulture);
61 60 }
62 61
63 62 public override IEnumerable<T> InputSymbols {
64 63 get { return _symbols; }
65 64 }
66 65
67 66 }
68 67 }
@@ -1,26 +1,18
1 1 using System.Threading;
2 2 using System;
3 3
4 4 namespace Implab {
5 5 public class SyncContextPromise<T> : Promise<T> {
6 6 readonly SynchronizationContext m_context;
7 7
8 8 public SyncContextPromise(SynchronizationContext context) {
9 9 Safe.ArgumentNotNull(context, "context");
10 10 m_context = context;
11 11 }
12 12
13 protected override void SignalSuccess(Promise<T>.HandlerDescriptor handler) {
14 m_context.Post(x => base.SignalSuccess(handler), null);
15 }
16
17 protected override void SignalError(Promise<T>.HandlerDescriptor handler, Exception error) {
18 m_context.Post(x => base.SignalError(handler, error), null);
19 }
20
21 protected override void SignalCancelled(Promise<T>.HandlerDescriptor handler, Exception reason) {
22 m_context.Post(x => base.SignalCancelled(handler, reason), null);
13 protected override void SignalHandler(HandlerDescriptor handler, int signal) {
14 m_context.Post(x => base.SignalHandler(handler, signal), null);
23 15 }
24 16 }
25 17 }
26 18
@@ -1,41 +1,37
1 1 using System;
2 using Implab.Diagnostics;
3 using Implab.Parallels;
4 2 using Implab;
5 using System.Collections.Generic;
6 using System.Collections.Concurrent;
7 using System.Threading;
8 using Implab.JSON;
9 using System.IO;
10 3 using System.Threading.Tasks;
11 4
12 5 namespace MonoPlay {
13 6 class MainClass {
14 7
15 8
16 9 public static void Main(string[] args) {
17 10 if (args == null)
18 11 throw new ArgumentNullException("args");
19 12
20 13 var t1 = Environment.TickCount;
21 14
22 15 DoWork().GetAwaiter().GetResult();
23 16
24 17 var t2 = Environment.TickCount;
25 18 Console.WriteLine("done: {0} ms, {1:.00} Mb, {2} GC", t2 - t1, GC.GetTotalMemory(false) / (1024*1024), GC.CollectionCount(0) );
26 19
27 20 }
28 21
29 22 static IPromise<int> DoItem(int x) {
30 return Promise<int>.FromResult(x + 1);
23 //return Promise<int>.FromResult(x + 1);
24 var p = new Promise<int>();
25 p.Resolve(x+1);
26 return p;
31 27 }
32 28
33 29 static async Task<int> DoWork() {
34 30 var c = 0;
35 31 for (int i = 0; i < 10000000; i++)
36 32 c = await DoItem(c);
37 33 return c;
38 34 }
39 35
40 36 }
41 37 }
General Comments 0
You need to be logged in to leave comments. Login now