public ArgumentMismatchException(IExpressionElement element) : this(element, null) { }
public ElementParsingException(IExpressionElement element) : this(element, null) { }
public ElementParsingException(IExpressionElement element, Exception inner) : base("Parsing exception. Can't parse element - error occured while parsing element.", inner, element) { }
public ElementEvaluationException(IExpressionElement element) : this(element, null) { }
public ElementEvaluationException(IExpressionElement element, Exception inner) : base("Evaluation exception. Can't evaluate operation - error occured while evaluating operation.", inner, element) { }
public IAstTreeNode CreateAstNode(IExpressionElement value, IList<IAstTreeNode> children) { var n = new AstNode(this, value); n.Children.AddRange(children); return n; }
public EvaluatorException(String message, Exception exception, IExpressionElement element) : base(message, exception) { Element = element; }
public NullArgumentsException(IExpressionElement element) : this(element, null) { }
public NullArgumentsException(IExpressionElement element, Exception inner) : base("Evaluation exception. No arguments recieved (null).", inner, element) { }
public bool IsInEquality() { IExpressionElement e = _expression.Last(); return((e is Less) || (e is Greater)); }
public Expression Append(IExpressionElement element) { _expression.Add(element); return(this); }
private IList <IExpressionElement> Tokenize(string expression) { Dictionary <string, List <IExpressionElement> > dict = new Dictionary <string, List <IExpressionElement> >(); foreach (IExpressionElement element in Constants.Cast <IExpressionElement>(). Concat(Variables.Cast <IExpressionElement>()). Concat(Operators.Cast <IExpressionElement>()). Concat(Functions.Cast <IExpressionElement>()). Concat(Statements.Cast <IExpressionElement>())) { string name = element.Name; if (!dict.ContainsKey(name)) { dict[name] = new List <IExpressionElement>(); } if (dict[name].Count > 0) { if (!(element is IOperator || element is IFunction)) { throw new ArgumentException("Only operators and functions can be overloaded."); } IExpressionElement elem = dict[name][0]; if ((elem is IOperator && element is IFunction) || (elem is IFunction && element is IOperator)) { throw new ArgumentException("Function and operator cannot have the same name."); } if (element is IOperator) { foreach (IExpressionElement eelem in dict[name]) { if ((element is IUnaryOperator && eelem is IUnaryOperator) || (element is IBinaryOperator && eelem is IBinaryOperator)) { throw new ArgumentException("There cannot be two identical operators."); } } } if (element is IFunction) { IFunction felement = element as IFunction; foreach (IExpressionElement eelem in dict[name]) { IFunction felem = eelem as IFunction; if (felem != null && felem.Name == felement.Name && felem.ParametersCount == felement.ParametersCount) { throw new ArgumentException("There cannot be two identical functions."); } } } } dict[name].Add(element); } List <IExpressionElement> tokens = new List <IExpressionElement>(); int i = 0; int l = expression.Length; while (i < l) { char c = expression[i]; if (char.IsWhiteSpace(c)) /* eat */ } {
public ParsedExpression Parse(string expression) { IList <IExpressionElement> tokens = Tokenize(expression); if (tokens.Count == 0) { throw new ArgumentException("Empty expression."); } List <IExpressionElement> output = new List <IExpressionElement>(); Stack <IExpressionElement> stack = new Stack <IExpressionElement>(); Stack <int> argumentsStack = new Stack <int>(); Stack <bool> insideFunctionStack = new Stack <bool>(); bool afterFunction = false; bool afterFnParenthesis = false; bool afterNonFnParenthesis = false; bool afterClosingParenthesis = false; bool afterSeparator = false; bool insideFunction = false; int arguments = 0; bool mustBeUnary = true; int tokenIndex = -1; foreach (IExpressionElement token in tokens) { tokenIndex++; IExpressionElement nextToken = tokenIndex + 1 < tokens.Count ? tokens[tokenIndex + 1] : null; // If the token is a number, then add it to the output queue. if (!afterFunction && !afterClosingParenthesis && (token is ILiteral || token is IConstant || token is IVariable)) { output.Add(token); mustBeUnary = false; afterClosingParenthesis = afterNonFnParenthesis = afterFnParenthesis = afterSeparator = false; } // If the token is a function token, then push it onto the stack. else if (!afterFunction && !afterClosingParenthesis && (token is IFunction || (token is MultipleElements && (token as MultipleElements).Elements[0] is IFunction))) { stack.Push(token); afterFunction = true; afterClosingParenthesis = afterNonFnParenthesis = afterFnParenthesis = afterSeparator = false; } // If the token is a function argument separator (e.g., a comma): // • Until the topmost element of the stack is a left parenthesis, pop the element onto the output queue. // If no left parentheses are encountered, either the separator was misplaced or parentheses were mismatched. else if (!afterFunction && insideFunction && token == Symbol.FunctionArgumentSeparator) { if (afterFnParenthesis) { throw new ArgumentException("Missing argument."); } while (stack.Peek() != Symbol.LeftParenthesis) { output.Add(stack.Pop()); } if (stack.Peek() != Symbol.LeftParenthesis) { throw new ArgumentException("Either the separator is misplaced or parentheses are mismatched."); } arguments++; afterClosingParenthesis = afterNonFnParenthesis = afterFnParenthesis = false; afterSeparator = true; } // If the token is an operator, o1, then: // • while there is an operator, o2, at the top of the stack, and either // o1 is associative or left-associative and its precedence is less than (lower precedence) or equal to that of o2, or // o1 is right-associative and its precedence is less than (lower precedence) that of o2, // pop o2 off the stack, onto the output queue; // • push o1 onto the stack. else if (!afterFunction && (token is IOperator || (token is MultipleElements && (token as MultipleElements).Elements[0] is IOperator))) { IOperator op = null; if ((mustBeUnary && token is IUnaryOperator) || (!mustBeUnary && token is IBinaryOperator)) { op = token as IOperator; } else if (token is MultipleElements) { foreach (IExpressionElement elem in (token as MultipleElements).Elements) { if ((mustBeUnary && elem is IUnaryOperator) || (!mustBeUnary && elem is IBinaryOperator)) { op = elem as IOperator; break; } } } if (op == null) { throw new ArgumentException(string.Format("{0} is not {1} operator.", token.Name, mustBeUnary ? "an unary" : "a binary")); } IOperator sop = stack.Count > 0 ? stack.Peek() as IOperator : null; while (sop != null && ( ( op is IBinaryOperator && (op as IBinaryOperator).Associativity != OperatorAssociativity.RightAssociative && op.Precedence <= sop.Precedence ) || ( ( (op is IBinaryOperator && (op as IBinaryOperator).Associativity == OperatorAssociativity.RightAssociative) || op is IUnaryOperator ) && op.Precedence < sop.Precedence ))) { output.Add(stack.Pop()); sop = stack.Count > 0 ? stack.Peek() as IOperator : null; } stack.Push(op); mustBeUnary = true; afterClosingParenthesis = afterFnParenthesis = afterNonFnParenthesis = afterSeparator = false; } // If the token is a left parenthesis, then push it onto the stack. else if (!afterClosingParenthesis && token == Symbol.LeftParenthesis) { stack.Push(token); argumentsStack.Push(arguments); insideFunctionStack.Push(insideFunction); // initial argument count arguments = nextToken == Symbol.RightParenthesis ? 0 : 1; if (afterFunction) { afterNonFnParenthesis = afterFunction = false; insideFunction = afterFnParenthesis = true; } else { afterNonFnParenthesis = true; insideFunction = afterFnParenthesis = false; } mustBeUnary = true; afterClosingParenthesis = afterSeparator = false; } // If the token is a right parenthesis: // • Until the token at the top of the stack is a left parenthesis, pop operators off the stack onto the output queue. // • Pop the left parenthesis from the stack, but not onto the output queue. // • If the token at the top of the stack is a function token, pop it and onto the output queue. // • If the stack runs out without finding a left parenthesis, then there are mismatched parentheses. else if (!afterFunction && !afterSeparator && token == Symbol.RightParenthesis) { if (afterNonFnParenthesis) { throw new ArgumentException("Unexpected token: '()'."); } if (stack.Count == 0) { throw new ArgumentException("There are mismatched parentheses."); } while (stack.Peek() != Symbol.LeftParenthesis) { output.Add(stack.Pop()); if (stack.Count == 0) { throw new ArgumentException("There are mismatched parentheses."); } } IExpressionElement parenthesis = stack.Pop(); // parenthesis if (stack.Count > 0) { IExpressionElement elem = stack.Peek(); if (elem is IFunction || (elem is MultipleElements && (elem as MultipleElements).Elements[0] is IFunction)) { elem = stack.Pop(); IExpressionElement func = null; if (elem is IFunction) { if ((elem as IFunction).ParametersCount != arguments) { UndefinedFunctionFoundEventArgs args = new UndefinedFunctionFoundEventArgs(elem.Name, arguments); if (UndefinedFunctionFound != null) { UndefinedFunctionFound(this, args); } if (!args.Handled) { throw new ArgumentException(string.Format("There is no function ‘{0}’ with {1} parameters defined.", elem.Name, arguments)); } elem = new UnknownFunction(elem.Name); (elem as UnknownFunction).ParametersCount = arguments; } func = elem; } else { foreach (IFunction f in (elem as MultipleElements).Elements) { if (f.ParametersCount == arguments) { func = f; break; } } if (func == null) { UndefinedFunctionFoundEventArgs args = new UndefinedFunctionFoundEventArgs((elem as MultipleElements).Elements[0].Name, arguments); if (UndefinedFunctionFound != null) { UndefinedFunctionFound(this, args); } if (!args.Handled) { throw new ArgumentException(string.Format("There is no function ‘{0}’ with {1} parameters defined.", args.Name, arguments)); } func = new UnknownFunction(args.Name); (func as UnknownFunction).ParametersCount = arguments; } } output.Add(func); } } arguments = argumentsStack.Count > 0 ? argumentsStack.Pop() : 0; insideFunction = insideFunctionStack.Pop(); afterFnParenthesis = afterNonFnParenthesis = mustBeUnary = afterSeparator = false; afterClosingParenthesis = true; } else { IExpressionElement elem = token; if (token is MultipleElements) { elem = (token as MultipleElements).Elements[0]; } throw new ArgumentException(string.Format("Unexpected token: ‘{0}’", elem.Name)); } } // When there are no more tokens to read: // • While there are still operator tokens in the stack: // • If the operator token on the top of the stack is a parenthesis, then there are mismatched parentheses. // • Pop the operator onto the output queue. while (stack.Count > 0) { if (stack.Peek() == Symbol.LeftParenthesis || stack.Peek() == Symbol.RightParenthesis) { var r = stack.Peek(); throw new ArgumentException("There are mismatched parentheses."); } output.Add(stack.Pop()); } return(new ParsedExpression(output, ZeroOnError)); }
public AstNode(ParsedExpression parsedExpression, IExpressionElement value) { _parsedExpression = parsedExpression; Value = value; Children = new List<IAstTreeNode>(); }
public ArgumentMismatchException(IExpressionElement element, Exception inner) : base("Evaluation exception. Operands number mismatched - two operands needed for evaluation.", inner, element) { }
double GetDynamicValue(IExpressionElement element) { return(((IDynamicNumber)element).Value); }
public Expression Append( IExpressionElement element ) { _expression.Add( element ); return this; }
internal ParsedExpression(IList <IExpressionElement> elements, bool zeroOnError) { this.ZeroOnError = zeroOnError; this.Elements = elements; // validate the expression and create the AST tree Stack <KeyValuePair <int, IExpressionElement> > stack = new Stack <KeyValuePair <int, IExpressionElement> >(); Stack <AstNode> tree = new Stack <AstNode>(); int l = elements.Count; for (int i = 0; i < l; i++) { IExpressionElement element = elements[i]; if (element is AssignmentOperator) { stack.Pop(); KeyValuePair <int, IExpressionElement> var = stack.Pop(); if (!(var.Value is IVariable)) { throw new InvalidOperationException("The left-hand side of an assignment must be a variable."); } elements[var.Key] = new VariableReference((IVariable)var.Value); stack.Push(new KeyValuePair <int, IExpressionElement>(-1, null)); AstNode node = new AstNode(this, element); node.Children.Add(tree.Pop()); node.Children.Insert(0, tree.Pop()); tree.Push(node); } else if (element is ILiteral) { tree.Push(new AstNode(this, element)); stack.Push(new KeyValuePair <int, IExpressionElement>(i, element)); } else if (element is IConstant) { tree.Push(new AstNode(this, element)); stack.Push(new KeyValuePair <int, IExpressionElement>(i, element)); } else if (element is IVariable) { tree.Push(new AstNode(this, element)); stack.Push(new KeyValuePair <int, IExpressionElement>(i, element)); } else if (element is IUnaryOperator) { stack.Pop(); stack.Push(new KeyValuePair <int, IExpressionElement>(-1, null)); AstNode node = new AstNode(this, element); node.Children.Add(tree.Pop()); tree.Push(node); } else if (element is IBinaryOperator) { stack.Pop(); stack.Pop(); stack.Push(new KeyValuePair <int, IExpressionElement>(-1, null)); AstNode node = new AstNode(this, element); node.Children.Add(tree.Pop()); node.Children.Insert(0, tree.Pop()); tree.Push(node); } else if (element is IFunction) { AstNode node = new AstNode(this, element); IFunction func = element as IFunction; int _l = func.ParametersCount; for (int _i = 0; _i < _l; _i++) { stack.Pop(); node.Children.Insert(0, tree.Pop()); } stack.Push(new KeyValuePair <int, IExpressionElement>(-1, null)); tree.Push(node); } else { throw new ArgumentException(string.Format("Unexpected element: ‘{0}’.", element.Name)); } } this.ExpressionTree = tree.Pop(); if (tree.Count > 0) { throw new ArgumentException(string.Format("Unexpected element: ‘{0}’.", tree.Pop().Value.Name)); } }