Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Text.RegularExpressions;
- namespace ExpressionEvaluator
- {
- delegate double ExecuteDelegate(double number1, double number2);
- static class Evaluator
- {
- static readonly char[] singleOperators = { '+', '-', '*', '/', '%', '^' };
- enum TokenType { OPERAND, OPERATOR, LEFT_BRACKET, RIGHT_BRACKET, ERROR };
- enum OperatorType { ADD, SUBTRACT, MULTIPLY, DIVIDE, MODULO, POWER };
- private class Token
- {
- public readonly TokenType type;
- public readonly string valueStr;
- public Token(TokenType type, string valueStr)
- {
- this.type = type;
- this.valueStr = valueStr;
- }
- }
- private class OperandToken : Token
- {
- public readonly double value;
- public OperandToken(string valueStr)
- : base(TokenType.OPERAND, valueStr)
- {
- if (double.TryParse(valueStr, System.Globalization.NumberStyles.Any,
- System.Globalization.CultureInfo.CurrentCulture, out value)) { }
- else
- throw new FormatException();
- }
- }
- private class OperatorToken : Token
- {
- public int priority;
- public ExecuteDelegate Execute;
- public OperatorToken(string valueStr, int priority, ExecuteDelegate executionMethod)
- : base(TokenType.OPERATOR, valueStr)
- {
- this.priority = priority;
- this.Execute = executionMethod;
- }
- public static ExecuteDelegate GetExecutionMethod(string operatorString)
- {
- OperatorType oper = parseOperator(operatorString);
- switch (oper)
- {
- case OperatorType.ADD:
- return (x, y) => x + y;
- case OperatorType.SUBTRACT:
- return (x, y) => x - y;
- case OperatorType.MULTIPLY:
- return (x, y) => x * y;
- case OperatorType.DIVIDE:
- return (x, y) => x / y;
- case OperatorType.MODULO:
- return (x, y) => x % y;
- case OperatorType.POWER:
- return (x, y) => Math.Pow(x,y);
- default:
- throw new ArgumentException();
- }
- }
- public static int GetOperatorPriority(string operatorString)
- {
- OperatorType oper = parseOperator(operatorString);
- switch (oper)
- {
- case OperatorType.ADD:
- return 0;
- case OperatorType.SUBTRACT:
- return 0;
- case OperatorType.MULTIPLY:
- return 1;
- case OperatorType.DIVIDE:
- return 1;
- case OperatorType.MODULO:
- return 1;
- case OperatorType.POWER:
- return 2;
- default:
- throw new NotSupportedException();
- }
- }
- private static OperatorType parseOperator(string operatorString)
- {
- switch (operatorString)
- {
- case "+":
- return OperatorType.ADD;
- case "-":
- return OperatorType.SUBTRACT;
- case "*":
- return OperatorType.MULTIPLY;
- case "/":
- return OperatorType.DIVIDE;
- case "%":
- return OperatorType.MODULO;
- case "^":
- return OperatorType.POWER;
- default:
- throw new FormatException();
- }
- }
- }
- public static string getPostfixString(string infixString)
- {
- string postfixString = "";
- foreach (Token token in infixToPostfix(infixString))
- {
- postfixString += token.valueStr + " ";
- }
- return postfixString;
- }
- public static double Evaluate(string infixString)
- {
- Token[] tokens = infixToPostfix(infixString);
- Stack<double> stack = new Stack<double>();
- double tempValue;
- foreach (Token token in tokens)
- {
- if (token.type == TokenType.OPERAND)
- {
- stack.Push(((OperandToken)token).value);
- }
- else if (token.type == TokenType.OPERATOR)
- {
- tempValue = stack.Pop();
- stack.Push(((OperatorToken)token).Execute(stack.Pop(), tempValue));
- }
- }
- return stack.Pop();
- }
- private static Token[] infixToPostfix(string infixExpr)
- {
- Token[] tokenArray = stringToToken(infixExpr);
- Stack<OperatorToken> operators = new Stack<OperatorToken>();
- Queue<Token> postfixQueue = new Queue<Token>();
- OperatorToken tempOperatorToken;
- foreach (Token token in tokenArray)
- {
- if (token.type == TokenType.OPERATOR)
- {
- tempOperatorToken = (OperatorToken)token;
- if (operators.Count == 0)
- {
- operators.Push(tempOperatorToken);
- }
- else
- {
- while (operators.Count != 0)
- {
- if (tempOperatorToken.priority <= operators.Peek().priority)
- {
- postfixQueue.Enqueue(operators.Pop());
- }
- else break;
- }
- operators.Push(tempOperatorToken);
- }
- }
- else if(token.type == TokenType.OPERAND)
- {
- postfixQueue.Enqueue(token);
- }
- }
- while (operators.Count != 0)
- {
- postfixQueue.Enqueue(operators.Pop());
- }
- return postfixQueue.ToArray();
- }
- private static Token[] stringToToken(string stringToCut)
- {
- List<Token> tokenList = new List<Token>();
- TokenType previousTokenType = TokenType.OPERAND;
- TokenType currentTokenType = TokenType.OPERAND;
- string currentValue = "";
- int priorityAdjust = 0;
- int priorityStep = 3;
- stringToCut = removeDelimitersAndDots(stringToCut);
- foreach (char character in stringToCut)
- {
- currentTokenType = getTokenType(character);
- if (previousTokenType != currentTokenType && currentValue != "")
- {
- if (previousTokenType == TokenType.OPERAND)
- {
- tokenList.Add(new OperandToken(currentValue));
- }
- else if (previousTokenType == TokenType.OPERATOR)
- {
- tokenList.Add((new OperatorToken(currentValue,
- OperatorToken.GetOperatorPriority(currentValue) + priorityAdjust,
- OperatorToken.GetExecutionMethod(currentValue))));
- }
- currentValue = "";
- }
- switch (currentTokenType)
- {
- case TokenType.OPERAND:
- if (previousTokenType == TokenType.OPERAND)
- {
- currentValue += character;
- }
- else
- {
- currentValue = character.ToString();
- }
- break;
- case TokenType.OPERATOR:
- currentValue = character.ToString();
- break;
- case TokenType.LEFT_BRACKET:
- priorityAdjust += priorityStep;
- break;
- case TokenType.RIGHT_BRACKET:
- priorityAdjust -= priorityStep;
- break;
- case TokenType.ERROR:
- throw new FormatException();
- }
- previousTokenType = currentTokenType;
- }
- if (currentTokenType == TokenType.OPERAND)
- {
- tokenList.Add(new OperandToken(currentValue));
- }
- else if (currentTokenType == TokenType.OPERATOR)
- {
- tokenList.Add(new OperatorToken(currentValue,
- OperatorToken.GetOperatorPriority(currentValue) + priorityAdjust,
- OperatorToken.GetExecutionMethod(currentValue)));
- }
- if (priorityAdjust != 0)
- {
- throw new FormatException("Uneven number of brackets!");
- }
- return tokenList.ToArray();
- }
- private static TokenType getTokenType(char character){
- if ((int)character < 58 && (int)character > 47)
- return TokenType.OPERAND;
- else if (character == ',')
- return TokenType.OPERAND;
- else if (character == '(')
- return TokenType.LEFT_BRACKET;
- else if (character == ')')
- return TokenType.RIGHT_BRACKET;
- else
- foreach (char oper in singleOperators)
- {
- if (character == oper)
- return TokenType.OPERATOR;
- }
- return TokenType.ERROR;
- }
- private static string removeDelimitersAndDots(string str)
- {
- return str.Replace(" ", "").Replace(".", ",");
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment