/// <summary>
        /// Main DSL code file parser. Uses the Parser state machine to read the code file and process the program.
        /// </summary>
        /// <param name="content">text containing DSL program code</param>
        /// <returns>StateMachine</returns>
        private StateMachine ParseDSL(string content)
        {
            StateMachine stateMachine = null;
            State currentState = null;
            Command command = null;
            Event anEvent = null;
            State state = null;
            Transition transition = null;

            // Encode strings before parsing.
            content = Utility.PreProcess(content);

            string separators = " \r\n\t";
            string[] tokens = content.Split(separators.ToCharArray());

            foreach (string token in tokens)
            {
                // Decode strings from token.
                string tokenValue = Utility.PostProcess(token);

                string tokenLwr = tokenValue.ToLower();

                // Pass the token to our state machine to handle.
                bool handled = _controller.Handle(tokenLwr);

                if (!handled && tokenLwr.Length > 0)
                {
                    // Process the token under our current state.
                    switch (_controller.CurrentState.Name)
                    {
                        case "waitingForCommand":
                        {
                            // Read a Command Name.
                            command = new Command();
                            command.Name = tokenValue;

                            // Move state to read Command Code.
                            _controller.Handle(_startCode);

                            break;
                        }
                        case "waitingForCommandCode":
                        {
                            // Read a Command Code.
                            command.Code = tokenValue;

                            _commandList.Add(command.Name, command);

                            // Move state back to read Command Name.
                            _controller.Handle(_endCode);

                            break;
                        }
                        case "waitingForEvent":
                        {
                            // Read an Event Name.
                            anEvent = new Event();
                            anEvent.Name = tokenValue;

                            // Move state to read an Event Code.
                            _controller.Handle(_startCode);

                            break;
                        }
                        case "waitingForEventCode":
                        {
                            // Read an Event Code.
                            anEvent.Code = tokenValue;

                            _eventList.Add(anEvent.Name, anEvent);

                            // Move state back to read an Event Name.
                            _controller.Handle(_endCode);

                            break;
                        }
                        case "waitingForState":
                        {
                            // Read a State Name, stay in this state until next command read.
                            state = new State(tokenValue);
                            currentState = state;

                            _stateList.Add(tokenValue, state);

                            break;
                        }
                        case "waitingForAction":
                        {
                            // Read an Action Name.
                            state.AddAction(_commandList[tokenValue]);

                            // Move state back to reading a State.
                            _controller.Handle(_endCode);

                            break;
                        }
                        case "waitingForTransition":
                        {
                            // Read a Transition Trigger, stay in this state until symbol read for transition Target.
                            transition = new Transition();
                            transition.Source = currentState;
                            transition.Trigger = _eventList[tokenValue];

                            break;
                        }
                        case "waitingForTransitionState":
                        {
                            // Read a Transition Target, if the target state is known, assign it now. Otherwise, store it in the symbol table for mapping later.
                            if (_stateList.ContainsKey(tokenValue))
                            {
                                transition.Target = _stateList[tokenValue];
                                currentState.AddTransition(transition.Trigger, transition.Target);
                            }
                            else
                            {
                                // Add reference to bind later.
                                _symbolTableForStateList.Add(new Utility.SymbolTableForState(currentState, transition, "Target", _stateList, tokenValue));
                            }

                            // Move state back to reading a Transition.
                            _controller.Handle(_endCode);

                            break;
                        }
                    }
                }
            }

            // Resolve any references to unknown states.
            Utility.ResolveReferences(_symbolTableForStateList);

            // Create the state machine with the starting state.
            stateMachine = new StateMachine(_stateList["idle"]);

            return stateMachine;
        }
        public Parser()
        {
            // Setup a state machine with an internal DSL to handle parsing our code file.
            // You could actually create an external DSL code file to program the Parser itself, but for this example, we'll just utilize the code with an internal DSL.

            #region Setup Parser State Machine

            // States
            State idle = new State("idle");
            State waitingForCommand = new State("waitingForCommand");
            State waitingForCommandCode = new State("waitingForCommandCode");
            State waitingForEvent = new State("waitingForEvent");
            State waitingForEventCode = new State("waitingForEventCode");
            State waitingForState = new State("waitingForState");
            State waitingForAction = new State("waitingForAction");
            State waitingForTransition = new State("waitingForTransition");
            State waitingForTransitionState = new State("waitingForTransitionState");

            // Events
            Event readCommandStart = new Event("readCommandStart", _commandsToken);
            Event readCommandCodeStart = new Event("readCommandCodeStart", _startCode);
            Event readCommandCodeEnd = new Event("readCommandCodeEnd", _endCode);

            Event readEventStart = new Event("readEventStart", _eventsToken);
            Event readEventCodeStart = new Event("readEventCodeStart", _startCode);
            Event readEventCodeEnd = new Event("readEventCodeEnd", _endCode);

            Event readActionStart = new Event("readActionStart", _actionsToken);
            Event readActionEnd = new Event("readActionEnd", _endCode);

            Event readStateStart = new Event("readStateStart", _stateToken);

            Event readTransitionStart = new Event("readTransitionEvent", _transitionsToken);
            Event readTransitionState = new Event("readTransitionState", "=>");
            Event readTransitionStateEnd = new Event("readTransitionStateEnd", _endCode);
            Event endTransition = new Event("endTransition", ".");

            Event resetEvent = new Event("resetEvent", _resetToken);

            // Transitions
            idle.AddTransition(readCommandStart, waitingForCommand);
            idle.AddTransition(readEventStart, waitingForEvent);
            idle.AddTransition(readStateStart, waitingForState);

            waitingForCommand.AddTransition(readCommandCodeStart, waitingForCommandCode);
            waitingForCommandCode.AddTransition(readCommandCodeEnd, waitingForCommand);

            waitingForEvent.AddTransition(readEventCodeStart, waitingForEventCode);
            waitingForEventCode.AddTransition(readEventCodeEnd, waitingForEvent);

            waitingForState.AddTransition(readActionStart, waitingForAction);
            waitingForState.AddTransition(readTransitionStart, waitingForTransition);

            waitingForAction.AddTransition(readActionEnd, waitingForState);

            waitingForTransition.AddTransition(readTransitionState, waitingForTransitionState);
            waitingForTransition.AddTransition(endTransition, waitingForState);
            waitingForTransitionState.AddTransition(readTransitionStateEnd, waitingForTransition);

            // Setup state machine.
            _stateMachine = new StateMachine(idle);

            _stateMachine.AddResetEvent(resetEvent);

            // Setup controller.
            _controller = new Controller(_stateMachine);

            #endregion
        }
 public Controller(StateMachine stateMachine)
 {
     _stateMachine = stateMachine;
     _state = stateMachine.Start;
 }