private Stack <TraceryNode[]> GetRulesStack(string key)
        {
            // TODO: Put this magic values (random, repeat and discreate), as constants somewhere
            if (key.StartsWith("random"))
            {
                Stack <TraceryNode[]> s     = new Stack <TraceryNode[]>();
                TraceryNode[]         array = new TraceryNode[1];
                array[0] = new RandomNode(key);
                s.Push(array);
                return(s);
            }
            if (key.StartsWith("discrete"))
            {
                Stack <TraceryNode[]> s     = new Stack <TraceryNode[]>();
                TraceryNode[]         array = new TraceryNode[1];
                array[0] = new DiscreteNode(key);
                s.Push(array);
                return(s);
            }

            Stack <TraceryNode[]> stack;

            if (!symbols.TryGetValue(key, out stack))
            {
                throw new Exception("No registered symbol named " + key);
            }
            return(stack);
        }
        public TraceryNode Parse()
        {
            PushContext();
            IList <TraceryNode> nodes = new List <TraceryNode>();

            while (!Eof())
            {
                switch (CurrentChar())
                {
                case '<':
                    Advance();
                    int    startIndex = rawRule.IndexOf(' ', pos);
                    int    endIndex   = rawRule.IndexOf('>', pos);
                    string strCount   = rawRule.Substring(pos, startIndex - pos);
                    int    count;
                    bool   parseSuccess = int.TryParse(strCount, out count);

                    if (!parseSuccess)
                    {
                        string newCount = Tracery.g_Grammar.Flatten(strCount);
                        count = int.Parse(newCount);
                    }

                    // Skip the space
                    startIndex += 1;
                    string      sub          = rawRule.Substring(startIndex, endIndex - startIndex);
                    Parser      repeatParser = new Parser(sub);
                    TraceryNode toRepeat     = repeatParser.Parse();
                    for (int i = 0; i < count; i++)
                    {
                        nodes.Add((TraceryNode)toRepeat.Clone());
                    }
                    bool reached = false;
                    while (!reached)
                    {
                        if (CurrentChar() == '>')
                        {
                            reached = true;
                        }
                        Advance();
                    }
                    break;

                case '[':
                    nodes.Add(ParseAction());
                    break;

                case '#':
                    nodes.Add(ParseTag());
                    break;

                default:
                    nodes.Add(ParsePlaintext());
                    break;
                }
            }

            return(new RuleNode(nodes.ToArray(), PopContext()));
        }
        public string Flatten(string rawRule)
        {
            TraceryNode rule = Tracery.ParseRule(rawRule);

            return(rule.Flatten(this));
        }