internal static ForEachDefinition FromExpression(String expression)
        {
            List<string> tokens = expression.TrimmedSplit(" in ");

            if (tokens.Count != 2)
                throw new InvalidForeachPathException(expression);

            return new ForEachDefinition(tokens[0], tokens[1]);
        }
        /// <summary>
        /// Creates a filter argument definition from the filter argument expression
        /// </summary>
        /// <param name="argumentExpression">Expression from which to create the argument definition</param>
        /// <returns>A filter argument definition read from the expression</returns>
        internal static FilterArgumentDefinition FromArgumentExpression(String argumentExpression)
        {
            List<string> tokens = argumentExpression.TrimmedSplit(":");

            if (tokens.Count == 0 || tokens.Count >= 3)
                throw new InvalidFilterDefinitionException(
                    InvalidFilterDefinitionException.ErrorCause.NamedArgumentInvalid);

            String argument = tokens.First();

            if (tokens.Count == 1)
            {
                if (argument.ContainsWhitespace())
                    throw new InvalidFilterDefinitionException(
                        InvalidFilterDefinitionException.ErrorCause.ArgumentContainsWhitespace,
                        argument: argument);

                return new FilterArgumentDefinition(null, argument);
            }

            return new FilterArgumentDefinition(argument, tokens[1]);
        }
        /// <summary>
        /// Retrieves the filter definition from the expression
        /// </summary>
        /// <param name="expression">Filter expression</param>
        /// <returns>A filter definition based on an expression</returns>
        internal static FilterDefinition FromExpression(String expression)
        {
            List<string> filterTokens = expression.TrimmedSplit("|");

            // Invalid number of segments
            if (filterTokens.Count != 1 && filterTokens.Count != 2)
                throw new InvalidFilterDefinitionException(
                    InvalidFilterDefinitionException.ErrorCause.InvalidNumberOfDefinitionElements);

            // Missing function name or arguments
            if (filterTokens.Count == 1 && expression.Contains("|"))
                throw new InvalidFilterDefinitionException(
                    InvalidFilterDefinitionException.ErrorCause.FunctionNameOrArgumentMissing);

            string functionName = filterTokens.First();

            if (functionName.ContainsWhitespace())
                throw new InvalidFilterDefinitionException(
                    InvalidFilterDefinitionException.ErrorCause.FunctionNameContainsWhitespace,
                    functionName);

            FilterDefinition definition = new FilterDefinition(functionName);

            if (filterTokens.Count == 2)
            {
                List<string> arguments = filterTokens[1].TrimmedSplit(",");

                List<FilterArgumentDefinition> argumentDefinitions =
                    arguments
                    .Select(a => FilterArgumentDefinition.FromArgumentExpression(a))
                    .ToList();

                definition.Arguments.AddRange(argumentDefinitions);
            }

            return definition;
        }
 /// <summary>
 /// Gets the object at the specified path
 /// </summary>
 /// <param name="path">Path from which to get the object</param>
 /// <returns>The object at specified path</returns>
 internal object GetObject(String path)
 {
     return GetObject(path.TrimmedSplit());
 }
 private ForEachDefinition(String variable, String collection)
 {
     CollectionPath = collection.TrimmedSplit();
     Variable = variable;
     Collection = collection;
 }