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"); }