public void ParserParse() { Parser parser = new Parser(); ExpressionQueue output = parser.Parse("3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3"); Assert.AreEqual(13, output.Count); Token t = output.Dequeue(); Assert.IsInstanceOfType(t, typeof(Operand)); Assert.AreEqual(3L, ((Operand)t).Value); t = output.Dequeue(); Assert.IsInstanceOfType(t, typeof(Operand)); Assert.AreEqual(4L, ((Operand)t).Value); t = output.Dequeue(); Assert.IsInstanceOfType(t, typeof(Operand)); Assert.AreEqual(2L, ((Operand)t).Value); t = output.Dequeue(); Assert.IsInstanceOfType(t, typeof(RaspyOperator)); Assert.AreEqual('*', ((RaspyOperator)t).Symbol); t = output.Dequeue(); Assert.IsInstanceOfType(t, typeof(Operand)); Assert.AreEqual(1L, ((Operand)t).Value); t = output.Dequeue(); Assert.IsInstanceOfType(t, typeof(Operand)); Assert.AreEqual(5L, ((Operand)t).Value); t = output.Dequeue(); Assert.IsInstanceOfType(t, typeof(RaspyOperator)); Assert.AreEqual('-', ((RaspyOperator)t).Symbol); t = output.Dequeue(); Assert.IsInstanceOfType(t, typeof(Operand)); Assert.AreEqual(2L, ((Operand)t).Value); t = output.Dequeue(); Assert.IsInstanceOfType(t, typeof(Operand)); Assert.AreEqual(3L, ((Operand)t).Value); t = output.Dequeue(); Assert.IsInstanceOfType(t, typeof(RaspyOperator)); Assert.AreEqual('^', ((RaspyOperator)t).Symbol); t = output.Dequeue(); Assert.IsInstanceOfType(t, typeof(RaspyOperator)); Assert.AreEqual('^', ((RaspyOperator)t).Symbol); t = output.Dequeue(); Assert.IsInstanceOfType(t, typeof(RaspyOperator)); Assert.AreEqual('/', ((RaspyOperator)t).Symbol); t = output.Dequeue(); Assert.IsInstanceOfType(t, typeof(RaspyOperator)); Assert.AreEqual('+', ((RaspyOperator)t).Symbol); }
public void EvaluatorInvalidFail() { Evaluator evaluator = new Evaluator(); ExpressionQueue expression = new ExpressionQueue("4 + 5 +"); expression.Enqueue(new Operand(4)); expression.Enqueue(new Operand(5)); expression.Enqueue(new RaspyOperator('+', Associativity.Left, 2, 2)); expression.Enqueue(new RaspyOperator('+', Associativity.Left, 2, 2)); evaluator.Evaluate(expression); }
public void ParseEmpty() { Parser parser = new Parser(); ExpressionQueue result = parser.Parse(null); Assert.IsNotNull(result); Assert.AreEqual(0, result.Count); result = parser.Parse(string.Empty); Assert.IsNotNull(result); Assert.AreEqual(0, result.Count); result = parser.Parse(" \t"); Assert.IsNotNull(result); Assert.AreEqual(0, result.Count); }
public static IExpression <T> BuildBlockExpression <T>(string str, ExpressionQueue <T> root) { ExpressionQueue <T> result = root; bool firstExpressionCreated = false; int bracketsCount = 0; int lastIndex = 0; for (int i = 0; i < str.Length; i++) { char current = str[i]; bool isEOF = str.Length == i + 1; if (current == '(') { bracketsCount++; } else if (current == ')') { bracketsCount--; } if (bracketsCount == 0 && (isEOF || result.IsExpressionEdge(str, i))) { string substring = str.Substring(lastIndex, i + 1 - lastIndex); lastIndex = i + 1; if (!firstExpressionCreated) { result.Handle(substring); firstExpressionCreated = true; } else { substring = substring.TrimStart(' '); result.Handle(substring); } } } return(result); }
public void ExtensionsParse() { ExpressionQueue output = "3+4".Parse(); Assert.IsNotNull(output); }
/// <summary> /// Parses an infix expression into a an RPN token queue. /// </summary> /// <param name="expression">The expression to parse.</param> /// <returns>An RPN token queue.</returns> public ExpressionQueue Parse(string expression) { ExpressionQueue output = new ExpressionQueue(expression); Stack<Token> stack = new Stack<Token>(); if (!string.IsNullOrEmpty(expression)) { int i = 0; ReadResult result; while (i < expression.Length) { result = this.ReadOperand(expression, i); if (result.Success) { output.Enqueue(result.Token); i = result.Position; } else { result = this.ReadOperator(expression, i); if (result.Success) { RaspyOperator op1 = (RaspyOperator)result.Token; while (stack.Count > 0 && stack.Peek().IsOperator) { RaspyOperator op2 = (RaspyOperator)stack.Peek(); if ((op1.Associativity == Associativity.Left && op1.Precedence <= op2.Precedence) || (op1.Associativity == Associativity.Right && op1.Precedence < op2.Precedence)) { output.Enqueue(stack.Pop()); } else { break; } } stack.Push(result.Token); i = result.Position; } else if (expression[i] == '(') { stack.Push(new Parenthesis(ParenthesisType.Left)); i++; } else if (expression[i] == ')') { bool foundLeft = false; while (stack.Count > 0) { Token token = stack.Peek(); if (token.IsOperator) { output.Enqueue(stack.Pop()); } else if (token.IsParenthesis) { if (((Parenthesis)token).ParenthesisType == ParenthesisType.Left) { stack.Pop(); foundLeft = true; break; } } } i++; if (!foundLeft) { throw new RaspyParseException("The expression contains mismatched parentheses.", expression); } } else if (!char.IsWhiteSpace(expression[i])) { throw new RaspyParseException(string.Format(CultureInfo.InvariantCulture, "The expression contains an invalid character, '{0}'.", expression[i]), expression); } else { i++; } } } while (stack.Count > 0) { Token token = stack.Peek(); if (!token.IsParenthesis) { output.Enqueue(stack.Pop()); } else { throw new RaspyParseException("The expression contains mismatched parentheses.", expression); } } } return output; }
/// <summary> /// Evaluates a parsed arithmetic expression. /// </summary> /// <param name="expression">The expression to evaluate.</param> /// <returns>The result of the evaluation.</returns> public object Evaluate(ExpressionQueue expression) { if (expression == null) { throw new ArgumentNullException("expression", "expression cannot be null."); } string infixExpression = expression.InfixExpression; string parsedExpression = expression.ToString(); Stack<Token> stack = new Stack<Token>(); try { while (expression.Count > 0) { Token token = expression.Dequeue(); if (token.IsOperator) { RaspyOperator op = (RaspyOperator)token; IOperationProvider provider = this.providerFactory.GetProvider(op.Symbol); if (provider != null) { List<Token> args = new List<Token>(); int i = op.ArgumentCount; while (i-- > 0) { args.Add(stack.Pop()); } args.Reverse(); stack.Push(provider.Operate(op, args.ToArray())); } else { throw new RaspyEvaluationException( string.Format(CultureInfo.InvariantCulture, "No provider could be found for operator '{0}'.", op.Symbol), infixExpression, parsedExpression); } } else { stack.Push(token); } } if (stack.Count != 1 || !stack.Peek().IsOperand) { throw new RaspyEvaluationException( string.Format(CultureInfo.InvariantCulture, "Invalid expression: '{0}'.", parsedExpression), infixExpression, parsedExpression); } return ((Operand)stack.Pop()).Value; } catch (RaspyException) { throw; } catch (Exception ex) { throw new RaspyEvaluationException( string.Format(CultureInfo.InvariantCulture, "An error occurred while evaluating the expression '{0}'.", parsedExpression), ex, infixExpression, parsedExpression); } }