/// <summary> /// Evaluate the expression using provided variables /// </summary> /// <param name="expression">The expression to evaluate</param> /// <returns></returns> public bool Evaluate(string expression) { var stack = new Stack <bool>(); bool result = false; foreach (ITypedToken exp in ExpressionParser.Parse(expression)) { switch (exp.TokenType) { case TokenType.Value: result = ((ConstantToken)exp).Value; break; case TokenType.Variable: var var = (VariableToken)exp; if (!variables.TryGetValue((ignoreCase ? var.Name.ToUpper() : var.Name), out result)) { throw new InvalidOperationException("Trying to evaluate an unknown variable named '" + var.Name + "', please check your variable dictionary!"); } break; case TokenType.Operator: var op = (OperatorToken)exp; if (op.IsUnary) { result = OperatorHelper.EvaluateUnary(op.Operator, stack.Pop()); } else // binary operator { bool p2 = stack.Pop(); bool p1 = stack.Pop(); result = OperatorHelper.EvaluateBinary(op.Operator, p1, p2); } break; } stack.Push(result); } return(stack.Pop()); }
/// <summary> /// Converts the input infix expression into the postfix and creates the list /// of token in that order /// </summary> /// <param name="expression">Infix expression (e.g. (A && C) || B)</param> /// <returns>List of atomic expressions sorted in the postfix order</returns> public static IEnumerable <ITypedToken> Parse(string expression) { var expressions = new List <ITypedToken>(); string variable = string.Empty; var operatorStack = new Stack <string>(); try { for (int i = 0; i < expression.Length; i++) { char c = expression[i]; if (IgnoredCharsList.Contains(c)) { continue; // ignore some characters } // variable or number if (IsVariableNameCharacter(c)) { variable += c; } else { switch (c) { case '(': operatorStack.Push(Constant.LeftParenthesis); break; case ')': CheckVariable(variable, expressions); variable = string.Empty; while (!operatorStack.Peek().Equals(Constant.LeftParenthesis)) { expressions.Add(new OperatorToken { Operator = operatorStack.Pop() }); } operatorStack.Pop(); break; default: string sc = c.ToString(CultureInfo.InvariantCulture); CheckVariable(variable, expressions); variable = string.Empty; if (i < expression.Length - 1) { char next = expression[i + 1]; if (!IgnoredCharsList.Contains(c) && !IsVariableNameCharacter(next) && next != '(' && next != ')') { sc += next; i++; } } while (operatorStack.Count > 0 && OperatorHelper.Priority(operatorStack.Peek()) >= OperatorHelper.Priority(sc)) { expressions.Add(new OperatorToken { Operator = operatorStack.Pop() }); } operatorStack.Push(sc); break; } } } CheckVariable(variable, expressions); while (operatorStack.Count > 0) { expressions.Add(new OperatorToken { Operator = operatorStack.Pop() }); } } catch (Exception) { throw new InvalidOperationException("Cannot parse the current expression '" + expression + "'!"); } if (expressions.Count == 0) { throw new InvalidOperationException("Cannot evaluate an empty expression!"); } return(expressions); }