ccmny

Evaluator

Jun 13th, 2011
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.34 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6.  
  7. namespace ExpressionEvaluator
  8. {
  9.     delegate double ExecuteDelegate(double number1, double number2);
  10.  
  11.     static class Evaluator
  12.     {
  13.         static readonly char[] singleOperators = { '+', '-', '*', '/', '%', '^' };        
  14.         enum TokenType { OPERAND, OPERATOR, LEFT_BRACKET, RIGHT_BRACKET, ERROR };
  15.         enum OperatorType { ADD, SUBTRACT, MULTIPLY, DIVIDE, MODULO, POWER };
  16.  
  17.         private class Token
  18.         {
  19.             public readonly TokenType type;
  20.             public readonly string valueStr;
  21.  
  22.             public Token(TokenType type, string valueStr)
  23.             {
  24.                 this.type = type;
  25.                 this.valueStr = valueStr;
  26.             }
  27.         }
  28.  
  29.         private class OperandToken : Token
  30.         {
  31.             public readonly double value;
  32.  
  33.             public OperandToken(string valueStr)
  34.                 : base(TokenType.OPERAND, valueStr)
  35.             {
  36.                 if (double.TryParse(valueStr, System.Globalization.NumberStyles.Any,
  37.                     System.Globalization.CultureInfo.CurrentCulture, out value)) { }
  38.                 else
  39.                     throw new FormatException();                
  40.             }
  41.         }
  42.  
  43.         private class OperatorToken : Token
  44.         {
  45.             public int priority;
  46.             public ExecuteDelegate Execute;
  47.  
  48.             public OperatorToken(string valueStr, int priority, ExecuteDelegate executionMethod)
  49.                 : base(TokenType.OPERATOR, valueStr)
  50.             {
  51.                 this.priority = priority;
  52.                 this.Execute = executionMethod;
  53.             }
  54.  
  55.             public static ExecuteDelegate GetExecutionMethod(string operatorString)
  56.             {
  57.                 OperatorType oper = parseOperator(operatorString);
  58.  
  59.                 switch (oper)
  60.                 {
  61.                     case OperatorType.ADD:
  62.                         return (x, y) => x + y;
  63.                     case OperatorType.SUBTRACT:
  64.                         return (x, y) => x - y;
  65.                     case OperatorType.MULTIPLY:
  66.                         return (x, y) => x * y;
  67.                     case OperatorType.DIVIDE:
  68.                         return (x, y) => x / y;
  69.                     case OperatorType.MODULO:
  70.                         return (x, y) => x % y;
  71.                     case OperatorType.POWER:
  72.                         return (x, y) => Math.Pow(x,y);
  73.                     default:
  74.                         throw new ArgumentException();
  75.                 }
  76.             }
  77.  
  78.             public static int GetOperatorPriority(string operatorString)
  79.             {
  80.                 OperatorType oper = parseOperator(operatorString);
  81.                 switch (oper)
  82.                 {
  83.                     case OperatorType.ADD:
  84.                         return 0;
  85.                     case OperatorType.SUBTRACT:
  86.                         return 0;
  87.                     case OperatorType.MULTIPLY:
  88.                         return 1;
  89.                     case OperatorType.DIVIDE:
  90.                         return 1;
  91.                     case OperatorType.MODULO:
  92.                         return 1;
  93.                     case OperatorType.POWER:
  94.                         return 2;
  95.                     default:
  96.                         throw new NotSupportedException();
  97.                 }
  98.             }
  99.  
  100.             private static OperatorType parseOperator(string operatorString)
  101.             {
  102.                 switch (operatorString)
  103.                 {  
  104.                     case "+":
  105.                         return OperatorType.ADD;
  106.                     case "-":
  107.                         return OperatorType.SUBTRACT;
  108.                     case "*":
  109.                         return OperatorType.MULTIPLY;
  110.                     case "/":
  111.                         return OperatorType.DIVIDE;
  112.                     case "%":
  113.                         return OperatorType.MODULO;
  114.                     case "^":
  115.                         return OperatorType.POWER;
  116.                     default:
  117.                         throw new FormatException();                        
  118.                 }
  119.             }            
  120.         }
  121.  
  122.         public static string getPostfixString(string infixString)
  123.         {
  124.             string postfixString = "";
  125.             foreach (Token token in infixToPostfix(infixString))
  126.             {
  127.                 postfixString += token.valueStr + " ";
  128.             }
  129.             return postfixString;
  130.         }
  131.  
  132.         public static double Evaluate(string infixString)
  133.         {
  134.             Token[] tokens = infixToPostfix(infixString);
  135.             Stack<double> stack = new Stack<double>();
  136.             double tempValue;
  137.  
  138.             foreach (Token token in tokens)
  139.             {
  140.                 if (token.type == TokenType.OPERAND)
  141.                 {
  142.                     stack.Push(((OperandToken)token).value);
  143.                 }
  144.                 else if (token.type == TokenType.OPERATOR)
  145.                 {
  146.                     tempValue = stack.Pop();
  147.                     stack.Push(((OperatorToken)token).Execute(stack.Pop(), tempValue));
  148.                 }
  149.             }
  150.             return stack.Pop();
  151.         }
  152.  
  153.  
  154.         private static Token[] infixToPostfix(string infixExpr)
  155.         {
  156.             Token[] tokenArray = stringToToken(infixExpr);
  157.             Stack<OperatorToken> operators = new Stack<OperatorToken>();
  158.             Queue<Token> postfixQueue = new Queue<Token>();
  159.  
  160.             OperatorToken tempOperatorToken;
  161.  
  162.             foreach (Token token in tokenArray)
  163.             {
  164.                 if (token.type == TokenType.OPERATOR)
  165.                 {
  166.                     tempOperatorToken = (OperatorToken)token;
  167.  
  168.                     if (operators.Count == 0)
  169.                     {
  170.                         operators.Push(tempOperatorToken);
  171.                     }
  172.                     else
  173.                     {
  174.                         while (operators.Count != 0)
  175.                         {
  176.                             if (tempOperatorToken.priority <= operators.Peek().priority)
  177.                             {
  178.                                 postfixQueue.Enqueue(operators.Pop());
  179.                             }
  180.                             else break;                            
  181.                         }
  182.                         operators.Push(tempOperatorToken);
  183.                     }
  184.                 }
  185.                 else if(token.type == TokenType.OPERAND)
  186.                 {
  187.                     postfixQueue.Enqueue(token);
  188.                 }
  189.             }
  190.             while (operators.Count != 0)
  191.             {
  192.                 postfixQueue.Enqueue(operators.Pop());
  193.             }
  194.            
  195.             return postfixQueue.ToArray();
  196.         }
  197.  
  198.         private static Token[] stringToToken(string stringToCut)
  199.         {
  200.             List<Token> tokenList = new List<Token>();
  201.             TokenType previousTokenType = TokenType.OPERAND;
  202.             TokenType currentTokenType = TokenType.OPERAND;
  203.             string currentValue = "";
  204.             int priorityAdjust = 0;
  205.             int priorityStep = 3;
  206.             stringToCut = removeDelimitersAndDots(stringToCut);
  207.  
  208.             foreach (char character in stringToCut)
  209.             {
  210.                 currentTokenType = getTokenType(character);
  211.  
  212.                 if (previousTokenType != currentTokenType && currentValue != "")
  213.                 {
  214.                     if (previousTokenType == TokenType.OPERAND)
  215.                     {
  216.                         tokenList.Add(new OperandToken(currentValue));
  217.                     }
  218.                     else if (previousTokenType == TokenType.OPERATOR)
  219.                     {
  220.                         tokenList.Add((new OperatorToken(currentValue,
  221.                             OperatorToken.GetOperatorPriority(currentValue) + priorityAdjust,
  222.                             OperatorToken.GetExecutionMethod(currentValue))));
  223.                     }
  224.                     currentValue = "";
  225.                 }
  226.  
  227.                 switch (currentTokenType)
  228.                 {
  229.                     case TokenType.OPERAND:
  230.                         if (previousTokenType == TokenType.OPERAND)
  231.                         {
  232.                             currentValue += character;
  233.                         }
  234.                         else
  235.                         {
  236.                             currentValue = character.ToString();
  237.                         }
  238.                         break;
  239.                     case TokenType.OPERATOR:
  240.                         currentValue = character.ToString();
  241.                         break;
  242.                     case TokenType.LEFT_BRACKET:
  243.                         priorityAdjust += priorityStep;
  244.                         break;
  245.                     case TokenType.RIGHT_BRACKET:
  246.                         priorityAdjust -= priorityStep;
  247.                         break;
  248.                     case TokenType.ERROR:
  249.                         throw new FormatException();
  250.                 }          
  251.  
  252.                 previousTokenType = currentTokenType;
  253.             }
  254.             if (currentTokenType == TokenType.OPERAND)
  255.             {
  256.                 tokenList.Add(new OperandToken(currentValue));
  257.             }
  258.             else if (currentTokenType == TokenType.OPERATOR)
  259.             {
  260.                 tokenList.Add(new OperatorToken(currentValue,
  261.                     OperatorToken.GetOperatorPriority(currentValue) + priorityAdjust,
  262.                     OperatorToken.GetExecutionMethod(currentValue)));
  263.             }
  264.  
  265.             if (priorityAdjust != 0)
  266.             {
  267.                 throw new FormatException("Uneven number of brackets!");
  268.             }
  269.  
  270.             return tokenList.ToArray();
  271.         }
  272.  
  273.         private static TokenType getTokenType(char character){
  274.  
  275.             if ((int)character < 58 && (int)character > 47)
  276.                 return TokenType.OPERAND;
  277.             else if (character == ',')
  278.                 return TokenType.OPERAND;
  279.             else if (character == '(')
  280.                 return TokenType.LEFT_BRACKET;
  281.             else if (character == ')')
  282.                 return TokenType.RIGHT_BRACKET;
  283.             else
  284.                 foreach (char oper in singleOperators)
  285.                 {
  286.                     if (character == oper)
  287.                         return TokenType.OPERATOR;
  288.                 }                          
  289.             return TokenType.ERROR;
  290.         }
  291.  
  292.         private static string removeDelimitersAndDots(string str)
  293.         {
  294.             return str.Replace(" ", "").Replace(".", ",");
  295.         }
  296.        
  297.     }
  298. }
Advertisement
Add Comment
Please, Sign In to add comment