private void ProcessOperator(StringScanner steve, Stack<string> opStack, List<Token> output, bool lastTokenWasNumber, ref bool tokenIsNumber) { string op = steve.Read ().ToString(); if (lastTokenWasNumber) { PushOperatorToStack (op, opStack, output); } else if (op.Equals ("-")) { // The last token wasn't a number, but we encountered an operator, so this must be a negative sign steve.skipWhitespace (); if (!steve.HasNext ()) { throw new InvalidExpressionException("misplaced operator: " + op); } BigInteger num = 1; // if there's an expression after the minus sign, just process it and negate it if (steve.TryReadLong (ref num) || Char.ToLower (steve.Peek ()) == 'd' || steve.Peek() == '(' || steve.Peek() == '[') { output.Add (new NumToken(-num)); // if the next token is a diedef, paren, or formula, iterativelyAdd will detect the -1 and use it to negate the expression tokenIsNumber = true; } else { // there is no number after the minus sign, so it can't be negating a number, and it can't be doing subtraction throw new InvalidExpressionException ("misplaced operator: " + op); } } else { throw new InvalidExpressionException ("misplaced operator" + op); } }
private Token ProcessDieDef( StringScanner steve, Stack<string> opStack, List<Token> output, bool lastTokenWasNumber) { steve.TrySkip(); // move past the d\ if (!steve.HasNext()) throw new InvalidExpressionException("no die type given"); if (Char.IsDigit (steve.Peek ())) { // check that the syntax is valid before just trying to read it Token dieCount = new NumToken(1); if (lastTokenWasNumber) { // the last number was the die count, because it was followed by a 'd' dieCount = output.Last(); output.RemoveAt (output.Count - 1); } BigInteger dieType = steve.ReadLong(); // this is safe because we checked that the next char is a digit // we now know that die type and the die count, now we need to see if there are extra instructions for the roll long keepCount = 1; KeepStrategy keepstrat = KeepStrategy.ALL; if (steve.HasNext () && char.IsLetter (steve.Peek ()) && Char.ToLower (steve.Peek ()) != 'd') { char extension = Char.ToLower (steve.Read ()); if (extension == 'h') { keepstrat = KeepStrategy.HIGHEST; BigInteger temp = null; if (steve.TryReadLong (ref temp)) { if (temp > MAX_DIECOUNT) { throw new InvalidExpressionException (temp.ToString () + " is too many dice"); } else { keepCount = temp.LongValue (); } } } else if (extension == 'l') { keepstrat = KeepStrategy.LOWEST; BigInteger temp = null; if (steve.TryReadLong (ref temp)) { if (temp > MAX_DIECOUNT) { throw new InvalidExpressionException (temp.ToString () + " is too many dice"); } else { keepCount = temp.LongValue (); } } } else { throw new InvalidExpressionException("invalid die extension " + extension); } } var countList = new List<Token> (); countList.Add (dieCount); return new DiceToken (countList, dieType, keepCount, keepstrat, this); } else { throw new InvalidExpressionException("no die type given"); } }