public override void ExitRollFudge([NotNull] DiceGrammarParser.RollFudgeContext context)
        {
            // we'll have 1 or 2 + # of extras nodes on the stack, bottom-most 2 nodes are the number of dice and sides
            List <DiceAST> extras = new List <DiceAST>();
            DiceAST        numSides = null, numDice;

            for (int i = 0; i < context.basic_extras().Length + context.basic_function().Length; i++)
            {
                extras.Add(Stack.Pop());
            }

            extras.Reverse();
            if (context.unary_expr().Length > 1)
            {
                numSides = Stack.Pop();
            }

            numDice = Stack.Pop();
            var partial = new RollPartialNode(new RollNode(RollType.Fudge, numDice, numSides));

            foreach (var node in extras)
            {
                if (node is RerollNode)
                {
                    partial.AddReroll((RerollNode)node);
                }
                else if (node is ExplodeNode)
                {
                    partial.AddExplode((ExplodeNode)node);
                }
                else if (node is KeepNode)
                {
                    partial.AddKeep((KeepNode)node);
                }
                else if (node is SuccessNode)
                {
                    partial.AddSuccess((SuccessNode)node);
                }
                else if (node is CritNode)
                {
                    partial.AddCritical((CritNode)node);
                }
                else if (node is SortNode)
                {
                    partial.AddSort((SortNode)node);
                }
                else if (node is FunctionNode)
                {
                    partial.AddFunction((FunctionNode)node);
                }
            }

            Stack.Push(partial.CreateRollNode());
        }
        public void Successfully_ToAST()
        {
            RollData data = new RollData()
            {
                Config = new RollerConfig()
            };

            data.Config.FunctionRegistry.RegisterFunction("foo", Foo, FunctionScope.Roll, FunctionTiming.BeforeCrit);
            data.Config.GetRandomBytes = GetRNG(0, 1);
            var partial = new RollPartialNode(new RollNode(RollType.Normal, One, Twenty));

            partial.AddCritical(new CritNode(equal20, equal1));
            partial.AddFunction(new FunctionNode(FunctionScope.Basic, "foo", new List <DiceAST>(), data));
            partial.AddReroll(new RerollNode(0, equal1));

            EvaluateNode(partial.CreateRollNode(), data, 2, "1d20.reroll(=1).foo().critical(=20).fumble(=1) => 1!* + 2 => 2");
        }