Design Pattern Examples
Overview of object-oriented design patterns
State_Class.cs
Go to the documentation of this file.
1
6
7using System;
8using System.Collections.Generic;
9using System.Text;
10
11
13{
18 {
19 Initial,
29 Done
30 }
31
32
33 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
34 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
35 // Interface definitions
36 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
37 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38
46 internal class State_Constants
47 {
51 public const char EOF = (char)0xff;
52 }
53
54
55 //########################################################################
56 //########################################################################
57
58
65 internal interface IStateContext
66 {
73
79 void OutputCharacter(char character);
80 }
81
82
83 //########################################################################
84 //########################################################################
85
86
97 internal interface IStateBehavior
98 {
100 }
101
102
103 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
104 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
105 // State class definitions
106 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
107 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
108
109
120 {
131 {
132 CurrentState nextState = CurrentState.NormalText;
133 char character = context.GetNextCharacter();
134
135 switch(character)
136 {
137 case State_Constants.EOF:
138 nextState = CurrentState.Done;
139 break;
140
141 case '"':
142 context.OutputCharacter(character);
143 nextState = CurrentState.DoubleQuotedText;
144 break;
145
146 case '\'':
147 context.OutputCharacter(character);
148 nextState = CurrentState.SingleQuotedText;
149 break;
150
151 case '/':
152 nextState = CurrentState.StartComment;
153 break;
154
155 default:
156 context.OutputCharacter(character);
157 break;
158 }
159
160 return nextState;
161 }
162 }
163
164
165 //########################################################################
166 //########################################################################
167
168
179 {
190 {
191 CurrentState nextState = CurrentState.DoubleQuotedText;
192
193 char character = context.GetNextCharacter();
194
195 switch(character)
196 {
197 case State_Constants.EOF:
198 nextState = CurrentState.Done;
199 break;
200
201 case '"':
202 context.OutputCharacter(character);
203 nextState = CurrentState.NormalText;
204 break;
205
206 case '\\':
207 context.OutputCharacter(character);
208 nextState = CurrentState.EscapedDoubleQuoteText;
209 break;
210
211 default:
212 context.OutputCharacter(character);
213 break;
214 }
215
216 return nextState;
217 }
218 }
219
220
221 //########################################################################
222 //########################################################################
223
224
235 {
246 {
247 CurrentState nextState = CurrentState.SingleQuotedText;
248
249 char character = context.GetNextCharacter();
250
251 switch (character)
252 {
253 case State_Constants.EOF:
254 nextState = CurrentState.Done;
255 break;
256
257 case '\'':
258 context.OutputCharacter(character);
259 nextState = CurrentState.NormalText;
260 break;
261
262 case '\\':
263 context.OutputCharacter(character);
264 nextState = CurrentState.EscapedSingleQuoteText;
265 break;
266
267 default:
268 context.OutputCharacter(character);
269 break;
270 }
271
272 return nextState;
273 }
274 }
275
276
277 //########################################################################
278 //########################################################################
279
280
292 {
303 {
304 CurrentState nextState = CurrentState.DoubleQuotedText;
305
306 char character = context.GetNextCharacter();
307
308 switch (character)
309 {
310 case State_Constants.EOF:
311 nextState = CurrentState.Done;
312 break;
313
314 default:
315 context.OutputCharacter(character);
316 break;
317 }
318
319 return nextState;
320 }
321 }
322
323
324 //########################################################################
325 //########################################################################
326
327
339 {
350 {
351 CurrentState nextState = CurrentState.SingleQuotedText;
352
353 char character = context.GetNextCharacter();
354
355 switch (character)
356 {
357 case State_Constants.EOF:
358 nextState = CurrentState.Done;
359 break;
360
361 default:
362 context.OutputCharacter(character);
363 break;
364 }
365
366 return nextState;
367 }
368 }
369
370
371 //########################################################################
372 //########################################################################
373
374
385 {
396 {
397 CurrentState nextState = CurrentState.StartComment;
398
399 char character = context.GetNextCharacter();
400
401 switch (character)
402 {
403 case State_Constants.EOF:
404 nextState = CurrentState.Done;
405 break;
406
407 case '/':
408 nextState = CurrentState.LineComment;
409 break;
410
411 case '*':
412 nextState = CurrentState.BlockComment;
413 break;
414
415 default:
416 // Not the start of a comment so output the leading slash
417 // that led to the state followed by the character we just
418 // processed.
419 context.OutputCharacter('/');
420 context.OutputCharacter(character);
421 nextState = CurrentState.NormalText;
422 break;
423 }
424
425 return nextState;
426 }
427 }
428
429
430 //########################################################################
431 //########################################################################
432
433
442 {
453 {
454 CurrentState nextState = CurrentState.LineComment;
455
456 char character = context.GetNextCharacter();
457
458 switch (character)
459 {
460 case State_Constants.EOF:
461 nextState = CurrentState.Done;
462 break;
463
464 case '\n':
465 context.OutputCharacter(character);
466 nextState = CurrentState.NormalText;
467 break;
468
469 default:
470 // We are in a comment to be removed, so do nothing here.
471 break;
472 }
473
474 return nextState;
475 }
476 }
477
478
479 //########################################################################
480 //########################################################################
481
482
491 {
502 {
503 CurrentState nextState = CurrentState.BlockComment;
504
505 char character = context.GetNextCharacter();
506
507 switch (character)
508 {
509 case State_Constants.EOF:
510 nextState = CurrentState.Done;
511 break;
512
513 case '*':
514 nextState = CurrentState.EndBlockComment;
515 break;
516
517 default:
518 // We are in a comment to be removed, so do nothing here.
519 break;
520 }
521
522 return nextState;
523 }
524 }
525
526
527 //########################################################################
528 //########################################################################
529
530
540 {
551 {
552 CurrentState nextState = CurrentState.BlockComment;
553
554 char character = context.GetNextCharacter();
555
556 switch (character)
557 {
558 case State_Constants.EOF:
559 nextState = CurrentState.Done;
560 break;
561
562 case '/':
563 nextState = CurrentState.NormalText;
564 break;
565
566 default:
567 // We are still in a block comment to be removed, so do nothing here.
568 break;
569 }
570
571 return nextState;
572 }
573 }
574
575
576 //########################################################################
577 //########################################################################
578
579
586 internal class State_Done : IStateBehavior
587 {
598 {
599 // Do nothing (Yes! Another Null Object example!)
600 return CurrentState.Done;
601 }
602 }
603
604
605 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
606 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
607 // State class factory definition
608 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
609 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
610
611
615 static internal class State_Factory
616 {
624 {
625 IStateBehavior stateBehavior;
626 switch(state)
627 {
628 case CurrentState.NormalText:
629 stateBehavior = new State_NormalText();
630 break;
631
632 case CurrentState.DoubleQuotedText:
633 stateBehavior = new State_DoubleQuotedText();
634 break;
635
636 case CurrentState.SingleQuotedText:
637 stateBehavior = new State_SingleQuotedText();
638 break;
639
640 case CurrentState.EscapedDoubleQuoteText:
641 stateBehavior = new State_EscapedDoubleQuoteText();
642 break;
643
644 case CurrentState.EscapedSingleQuoteText:
645 stateBehavior = new State_EscapedSingleQuoteText();
646 break;
647
648 case CurrentState.StartComment:
649 stateBehavior = new State_StartComment();
650 break;
651
652 case CurrentState.LineComment:
653 stateBehavior = new State_LineComment();
654 break;
655
656 case CurrentState.BlockComment:
657 stateBehavior = new State_BlockComment();
658 break;
659
660 case CurrentState.EndBlockComment:
661 stateBehavior = new State_EndBlockComment();
662 break;
663
664 case CurrentState.Done:
665 stateBehavior = new State_Done();
666 break;
667
668 default:
669 throw new ApplicationException(string.Format("Unknown state: {0}. Cannot create a state class.", state));
670 }
671
672 return stateBehavior;
673 }
674 }
675
676
677 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
678 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
679 // State context definition
680 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
681 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
682
683
696 {
700 private string _inputText = string.Empty;
701
705 private int _textIndex = 0;
706
710 private StringBuilder _outputText = new StringBuilder();
711
716 private Dictionary<CurrentState, IStateBehavior> _stateBehaviors = new Dictionary<CurrentState, IStateBehavior>();
717
722
728
729
730 //--------------------------------------------------------------------
731 // StateContext_Class implementation.
732 //--------------------------------------------------------------------
733
742 private void _SetNextState(CurrentState newState)
743 {
744 if (newState != _currentState)
745 {
746 if (!_stateBehaviors.ContainsKey(newState))
747 {
748 _stateBehaviors[newState] = State_Factory.CreateState(newState);
749 }
750
751 Console.WriteLine(" --> State Transition: {0} -> {1}", _currentState, newState);
752
754 _currentState = newState;
755 }
756 }
757
758
759 //--------------------------------------------------------------------
760 // StateContext_Class public entry points.
761 //--------------------------------------------------------------------
762
769 public string RemoveComments(string text)
770 {
771 _inputText = text;
772 _textIndex = 0;
773 _outputText = new StringBuilder();
774 _currentState = CurrentState.Initial;
775 _SetNextState(CurrentState.NormalText);
776
777 while (_currentState != CurrentState.Done)
778 {
779 CurrentState nextState = _currentStateBehavior.GoNext(this);
780 _SetNextState(nextState);
781 }
782
783 return _outputText.ToString();
784 }
785
786
787 //--------------------------------------------------------------------
788 // IStateContext interface implementation.
789 //--------------------------------------------------------------------
790 // Note: These methods are accessible only through the IStateContext
791 // interface so are not directly available on the StateContext_Class
792 // instance.
793
800 {
801 char character = State_Constants.EOF;
802
803 if (_textIndex < _inputText.Length)
804 {
805 character = _inputText[_textIndex];
806 ++_textIndex;
807 }
808 return character;
809 }
810
815 void IStateContext.OutputCharacter(char character)
816 {
817 if (character != State_Constants.EOF)
818 {
819 _outputText.Append(character);
820 }
821 }
822 }
823}
Represents being in a block comment.
Definition: State_Class.cs:491
Represents constants used in the State machine. This is needed in a separate class because 1) C# requ...
Definition: State_Class.cs:47
const char EOF
Indicates End-of-file (no more data available).
Definition: State_Class.cs:51
Represents being done with input.
Definition: State_Class.cs:587
Represents being inside a double-quote string where filtering is essentially turned off until the end...
Definition: State_Class.cs:179
Represents possibly being at the end of a block comment.
Definition: State_Class.cs:540
Represents being in an escaped character sequence inside a double- quoted string. We don't do anythin...
Definition: State_Class.cs:292
Represents being in an escaped character sequence inside a single- quoted string. We don't do anythin...
Definition: State_Class.cs:339
Class factory for generating the state class instances.
Definition: State_Class.cs:616
static IStateBehavior CreateState(CurrentState state)
Create an instance of the specified state class.
Definition: State_Class.cs:623
Represents being in a line comment.
Definition: State_Class.cs:442
Represents normal text behavior.
Definition: State_Class.cs:120
Represents being inside a single-quoted string where filtering is effectively turned off until the en...
Definition: State_Class.cs:235
Represents the possible start of a line or block comment.
Definition: State_Class.cs:385
Represents the state machine. This maintains the context in which the state machine runs.
Definition: State_Class.cs:696
Dictionary< CurrentState, IStateBehavior > _stateBehaviors
Maps values from the CurrentState enumeration to instances of the IStateBehavior representing the beh...
Definition: State_Class.cs:716
int _textIndex
Index into the text to be filtered.
Definition: State_Class.cs:705
string _inputText
The text to be filtered.
Definition: State_Class.cs:700
CurrentState _currentState
The current state of the machine.
Definition: State_Class.cs:721
string RemoveComments(string text)
Entry point for callers to filter text. Removes C++-style line and block comments from the text.
Definition: State_Class.cs:769
IStateBehavior _currentStateBehavior
The current behavior (that is, a reference to the state behavior class) for the current state.
Definition: State_Class.cs:727
void _SetNextState(CurrentState newState)
Helper method to transition the state machine to the specified state. Does nothing if the new state i...
Definition: State_Class.cs:742
StringBuilder _outputText
The results of the filtering.
Definition: State_Class.cs:710
Represents a class that implements one state of the state machine.
Definition: State_Class.cs:98
CurrentState GoNext(IStateContext context)
Represents the context as passed to each state class.
Definition: State_Class.cs:66
char GetNextCharacter()
Get the next character from the input.
void OutputCharacter(char character)
Write the character to the context. This is how the parser accumulates the filtered text.
The namespace containing all Design Pattern Examples implemented in C#.
CurrentState
Represents the current state of the state machine.
Definition: State_Class.cs:18
@ StartComment
/ transitions to LineComment, * transitions to BlockComment, EOF transitions to Done,...
@ BlockComment
* transitions to EndBlockComment, EOF transitions to Done
@ Initial
State before the state machine actually starts. transitions to NormalText.
@ DoubleQuotedText
\ transitions to EscapedDoubleQuoteText, " transitions to NormalText, EOF transitions to Done
@ EscapedDoubleQuoteText
\ transitions to QuotedText, EOF transitions to Done
@ EscapedSingleQuoteText
\ transitions to SingleQuotedText, EOF transitions to Done
@ SingleQuotedText
‘’` transitions to EscapedSingleQuoteText, \ transitions to NormalText, EOF transitions to Done
@ EndBlockComment
/ transitions to NormalText, EOF transitions to Done, all else transitions to BlockComment
@ LineComment
\\n transitions to NormalText, EOF transitions to Done
@ NormalText
" transitions to QuotedText, / transitions to StartComment, EOF transitions to Done
@ Done
Indicates processing is done.