Ejemplo n.º 1
0
        /// <summary>
        /// Print the state machine as DOT notation suitable for drawing graphs.
        /// This is a useful debug functionality!!
        /// </summary>
        /// <param name="automata">Automata to generate graph for</param>
        /// <param name="input">Input to highlight the current state with</param>
        /// <param name="graphName">Graph name as specified in notation</param>
        /// <returns></returns>
        internal static string AsDotNotation <TState>(this FiniteAutomata <TState> automata, string input, string graphName = "automata") where TState : FiniteAutomata <TState> .BaseState
        {
            // Draw the *FA as a directed graph with the state numbers in circles
            // Use a double circle for accepting states
            //
            // digraph graphname {
            // digraph G {
            //   [node shape="circle"]
            //   1 [shape="doublecircle"]
            //  1 -> 2 [label=a]
            //}

            StringBuilder sb = new StringBuilder();

            sb.Append("digraph " + graphName + " {\n");
            sb.Append("\t[node shape=\"circle\"]\n");
            sb.Append("\tgraph [rankdir=\"LR\"]\n");

            IEnumerable <TState> currentStates = Enumerable.Empty <TState>();

            bool matchSuccessful = false;

            if (!string.IsNullOrEmpty(input))
            {
                StimulateResult <TState> stimulateResult = automata.Stimulate(input);

                matchSuccessful = (input == stimulateResult.Matched);

                sb.AppendFormat("\tlabel=\"Matched: {0}\"\n", stimulateResult.Matched.Replace("\"", "\\\""));
                sb.Append("\tlabelloc=top;\n");
                sb.Append("\tlabeljust=center;\n");

                currentStates = stimulateResult.ActiveStates;
            }

            foreach (Transition <TState> transition in automata.Transitions)
            {
                sb.Append(string.Format("\t{0} -> {1} [label=\"{2}\"]\n",
                                        transition.From.StateNumber,
                                        transition.To.StateNumber,
                                        transition.TransitionLabel().Replace("\\", "\\\\").Replace("\"", "\\\"")));
            }

            foreach (TState state in automata.States.Where(f => f.AcceptState || currentStates.Contains(f)))
            {
                sb.AppendFormat("\t{0} [{1}{2}]\n",
                                state.StateNumber,
                                state.AcceptState ? "shape=\"doublecircle\"" : "",
                                currentStates.Contains(state) ?
                                string.Format(" fillcolor=\"{0}\" style=\"filled\"", matchSuccessful ? "green" : "red")
                    : "");
            }

            sb.Append("}");

            return(sb.ToString());
        }