Example #1
0
        public static int Evaluate(string postfixNotationString)
        {
            if (string.IsNullOrWhiteSpace(postfixNotationString))
            {
                throw new ArgumentException("Argument postfixNotationString must not be null, empty or whitespace.", "postfixNotationString");
            }

            Stack <string> stack                   = new Stack <string>();
            string         sanitizedString         = new string(postfixNotationString.Where(c => AllowedCharacters.Contains(c)).ToArray());
            List <string>  enumerablePostfixTokens = sanitizedString.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();

            foreach (string token in enumerablePostfixTokens)
            {
                if (token.Length > 0)
                {
                    if (token.Length > 1)
                    {
                        if (ParserTokens.IsNumeric(token))
                        {
                            stack.Push(token);
                        }
                        else
                        {
                            throw new Exception("Operators and operands must be separated by a space.");
                        }
                    }
                    else
                    {
                        char tokenChar = token[0];

                        if (ParserTokens.Numbers.Contains(tokenChar))
                        {
                            stack.Push(tokenChar.ToString());
                        }
                        else if (ParserTokens.Operators.Contains(tokenChar))
                        {
                            if (stack.Count < 2)
                            {
                                if (tokenChar == '-')
                                {
                                    string val = $"-{stack.Pop()}";
                                    stack.Push(val);
                                    continue;
                                }
                                else
                                {
                                    throw new FormatException("The algebraic string has not sufficient values in the expression for the number of operators.");
                                }
                            }

                            string r = stack.Pop();
                            string l = stack.Pop();

                            int rhs = int.MinValue;
                            int lhs = int.MinValue;

                            bool parseSuccess = int.TryParse(r, out rhs);
                            parseSuccess &= int.TryParse(l, out lhs);

                            if (!parseSuccess)
                            {
                                throw new Exception("Unable to parse valueStack characters to Int32.");
                            }

                            int value = int.MinValue;
                            if (tokenChar == '+')
                            {
                                value = lhs + rhs;
                            }
                            else if (tokenChar == '-')
                            {
                                value = lhs - rhs;
                            }
                            else if (tokenChar == '*')
                            {
                                value = lhs * rhs;
                            }
                            else if (tokenChar == '/')
                            {
                                value = lhs / rhs;
                            }
                            else if (tokenChar == '^')
                            {
                                value = (int)Math.Pow(lhs, rhs);
                            }
                            else
                            {
                                throw new Exception(string.Format("Unrecognized token '{0}'.", tokenChar));
                            }


                            if (value != int.MinValue)
                            {
                                stack.Push(value.ToString());
                            }
                            else
                            {
                                throw new Exception("Value never got set.");
                            }
                        }
                        else
                        {
                            throw new Exception(string.Format("Unrecognized character '{0}'.", tokenChar));
                        }
                    }
                }
                else
                {
                    throw new Exception("Token length is less than one.");
                }
            }

            if (stack.Count == 1)
            {
                int result = 0;
                if (!int.TryParse(stack.Pop(), out result))
                {
                    throw new Exception("Last value on stack could not be parsed into an integer.");
                }
                return(result);
            }
            else
            {
                throw new Exception("The input has too many values for the number of operators.");
            }
        }         // method
        public static string Convert(string infixNotationString)
        {
            if (string.IsNullOrWhiteSpace(infixNotationString))
            {
                throw new ArgumentException("Argument infixNotationString must not be null, empty or whitespace.", "infixNotationString");
            }

            ExpectingType expectingType = ExpectingType.UnaryOrNumber;

            char          lastChar = '\0';
            string        number   = string.Empty;
            List <string> enumerableInfixTokens = new List <string>();
            string        inputString           = new string(infixNotationString.Where(c => ParserTokens.AllowedCharacters.Contains(c)).ToArray());

            foreach (char c in inputString)
            {
                if (ParserTokens.IsOperatorOrNull(lastChar))
                {
                    expectingType = ExpectingType.UnaryOrNumber;
                }
                else if (ParserTokens.IsNumericOrUnary(lastChar))
                {
                    expectingType = ExpectingType.BinaryOperator;
                }
                else
                {
                    throw new Exception($"Unexpected type '{(string.IsNullOrWhiteSpace(enumerableInfixTokens.LastOrDefault()) ? "" : enumerableInfixTokens.Last())}'.");
                }

                if (ParserTokens.Numbers.Contains(c))
                {
                    number += c.ToString();
                }
                else if (c == '-' && expectingType == ExpectingType.UnaryOrNumber)
                {
                    number += c.ToString();
                }
                else if (c == '+' && expectingType == ExpectingType.UnaryOrNumber)
                {
                    // Do nothing
                }
                else if (c == '(')
                {
                    if (number.Length > 0)
                    {
                        enumerableInfixTokens.Add(number);
                        number = string.Empty;
                    }
                    enumerableInfixTokens.Add(c.ToString());
                }
                else if (expectingType == ExpectingType.BinaryOperator)
                {
                    if (ParserTokens.Operators.Contains(c) || ")".Contains(c))
                    {
                        if (number.Length > 0)
                        {
                            enumerableInfixTokens.Add(number);
                            number = string.Empty;
                        }
                        enumerableInfixTokens.Add(c.ToString());
                    }
                    else
                    {
                        throw new Exception($"Unexpected character '{c}'. Was expecting: BinaryOperator");
                    }
                }
                else
                {
                    throw new Exception($"Unexpected character '{c}'. Was expecting: UnaryOrNumber");
                }

                lastChar = c;
            }

            if (number.Length > 0)
            {
                enumerableInfixTokens.Add(number);
                number = string.Empty;
            }

            List <char>  outputQueue   = new List <char>();
            Stack <char> operatorStack = new Stack <char>();

            foreach (string token in enumerableInfixTokens)
            {
                if (ParserTokens.IsNumeric(token))
                {
                    AddToOutput(outputQueue, token.ToArray());
                }
                else if (token.Length == 1)
                {
                    char c = token[0];

                    if (ParserTokens.Numbers.Contains(c))
                    {
                        AddToOutput(outputQueue, c);
                    }
                    else if (ParserTokens.Operators.Contains(c))
                    {
                        if (operatorStack.Count > 0)
                        {
                            char o = operatorStack.Peek();
                            if (
                                (ParserTokens.AssociativityDictionary[c] == ParserTokens.Associativity.Left &&
                                 ParserTokens.PrecedenceDictionary[c] <= ParserTokens.PrecedenceDictionary[o])
                                ||
                                (ParserTokens.AssociativityDictionary[c] == ParserTokens.Associativity.Right &&
                                 ParserTokens.PrecedenceDictionary[c] < ParserTokens.PrecedenceDictionary[o])
                                )
                            {
                                AddToOutput(outputQueue, operatorStack.Pop());
                            }
                        }
                        operatorStack.Push(c);
                    }
                    else if (c == '(')
                    {
                        operatorStack.Push(c);
                    }
                    else if (c == ')')
                    {
                        bool leftParenthesisFound = false;
                        while (operatorStack.Count > 0)
                        {
                            char o = operatorStack.Peek();
                            if (o == '(')
                            {
                                operatorStack.Pop();
                                leftParenthesisFound = true;
                                break;
                            }
                            AddToOutput(outputQueue, operatorStack.Pop());
                        }

                        if (!leftParenthesisFound)
                        {
                            throw new FormatException("The algebraic string contains mismatched parentheses (missing a left parenthesis).");
                        }
                    }
                    else
                    {
                        throw new Exception("Unrecognized character " + c.ToString());
                    }
                }
                else
                {
                    throw new Exception(token + " is not numeric or has a length greater than 1.");
                }
            }             // end foreach

            while (operatorStack.Count > 0)
            {
                char o = operatorStack.Pop();
                if ("()".Contains(o))
                {
                    throw new FormatException("The algebraic string contains mismatched parentheses (extra " + (o == '(' ? "left" : "right") + " parenthesis).");
                }

                AddToOutput(outputQueue, o);
            }

            return(new string(outputQueue.ToArray()).TrimEnd());
        }