/// <summary> /// Simply finds index of lowest priority Operator Token among all tokens /// </summary> private static int FindLowestPriorityOperatorTokenIndex(ListSegment <Token> tokens) { OperatorToken operatorToken = null; int operatorTokenIndex = -1; for (int i = 0; i < tokens.Count; ++i) { OperatorToken opToken = tokens[i] as OperatorToken; if (opToken != null && (operatorToken == null || opToken.Priority < operatorToken.Priority)) { operatorTokenIndex = i; operatorToken = opToken; } } return(operatorTokenIndex); }
/// <summary> /// Builds expression based on provided list of Tokens. Uses contexts to access parameters that will be passed externally. /// </summary> /// <param name="tokens">Tokens list</param> /// <param name="contexts">List of ParameterExpressions - variables which will be passed as Funtor's arguments</param> /// <param name="recommendedType">If not null, tryes to convert resulted type of expression to recommendedType (no 100% guarantee)</param> /// <returns>Expression</returns> private static Expression BuildExpression(ListSegment <Token> tokens, List <Expression> contexts, Type recommendedType) { if (tokens == null || tokens.Count == 0) { return(null); } Expression result = null; int operatorTokenIndex = FindLowestPriorityOperatorTokenIndex(tokens); if (operatorTokenIndex != -1) { OperatorToken operatorToken = tokens[operatorTokenIndex] as OperatorToken; if (operatorToken.IsBinary) { if (operatorTokenIndex == 0) { throw new BuilderException(operatorToken.Position, BuilderException.BuilderExceptionType.NoLeftOperand); } if (operatorTokenIndex == tokens.Count - 1) { throw new BuilderException(operatorToken.Position, BuilderException.BuilderExceptionType.NoRightOperand); } ListSegment <Token> leftArgTokens = tokens.GetSegment(0, operatorTokenIndex); ListSegment <Token> rightArgTokens = tokens.GetSegment(operatorTokenIndex + 1, tokens.Count - operatorTokenIndex - 1); Expression argLeft = null; Expression argRight = null; switch (operatorToken.RecommendedInputTypes) { case RecommendedInputTypes.Boolean: TryAssignBinaryOpArgs(leftArgTokens, rightArgTokens, contexts, typeof(bool), out argLeft, out argRight); break; case RecommendedInputTypes.Comparable: case RecommendedInputTypes.Numeric: if (TryAssignBinaryOpArgs(leftArgTokens, rightArgTokens, contexts, null, out argLeft, out argRight)) { break; } if (TryAssignBinaryOpArgs(rightArgTokens, leftArgTokens, contexts, null, out argLeft, out argRight)) { ListSegment <Token> temp = leftArgTokens; leftArgTokens = rightArgTokens; rightArgTokens = temp; break; } if (TryAssignBinaryOpArgs(leftArgTokens, rightArgTokens, contexts, typeof(int), out argLeft, out argRight)) { break; } if (TryAssignBinaryOpArgs(leftArgTokens, rightArgTokens, contexts, typeof(float), out argLeft, out argRight)) { break; } if (TryAssignBinaryOpArgs(leftArgTokens, rightArgTokens, contexts, typeof(bool), out argLeft, out argRight)) { break; } if (TryAssignBinaryOpArgs(leftArgTokens, rightArgTokens, contexts, typeof(DateTime), out argLeft, out argRight)) { break; } if (TryAssignBinaryOpArgs(leftArgTokens, rightArgTokens, contexts, typeof(string), out argLeft, out argRight)) { break; } break; default: if (TryAssignBinaryOpArgs(leftArgTokens, rightArgTokens, contexts, null, out argLeft, out argRight)) { break; } break; } result = operatorToken.CreateBinaryExpression(argLeft, argRight); } else { if (operatorTokenIndex != 0 || tokens.Count != 2) { throw new BuilderException(operatorToken.Position, BuilderException.BuilderExceptionType.IncorrectUnaryOperatorPosition); } Expression arg = BuildExpression(tokens.GetSegment(1, 1), contexts, null); result = operatorToken.CreateUnaryExpression(arg); } } else { result = BuildMembersExpression(tokens, contexts, recommendedType); } if (recommendedType != null && result.Type != recommendedType) { throw new ExpressionTypeException(operatorTokenIndex == -1 ? tokens[0].Position : tokens[operatorTokenIndex].Position, recommendedType, result.Type); } return(result); }