/// <summary> /// Tries to parse a collection of function parameters. Allows path and filter to share the core algorithm while representing parameters differently. /// </summary> /// <param name="lexer">The lexer to read from.</param> /// <param name="endTokenKind">The token kind that marks the end of the parameters.</param> /// <param name="splitParameters">The parameters if they were successfully split.</param> /// <returns>Whether the parameters could be split.</returns> private static bool TrySplitFunctionParameters(this ExpressionLexer lexer, ExpressionTokenKind endTokenKind, out ICollection <FunctionParameterToken> splitParameters) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(lexer != null, "lexer != null"); var parameters = new List <FunctionParameterToken>(); splitParameters = parameters; ExpressionToken currentToken = lexer.CurrentToken; if (currentToken.Kind == endTokenKind) { return(true); } if (currentToken.Kind != ExpressionTokenKind.Identifier || lexer.PeekNextToken().Kind != ExpressionTokenKind.Equal) { return(false); } while (currentToken.Kind != endTokenKind) { lexer.ValidateToken(ExpressionTokenKind.Identifier); string identifier = lexer.CurrentToken.GetIdentifier(); lexer.NextToken(); lexer.ValidateToken(ExpressionTokenKind.Equal); lexer.NextToken(); QueryToken parameterValue; if (!TryCreateParameterValueToken(lexer.CurrentToken, out parameterValue)) { throw new ODataException(ODataErrorStrings.ExpressionLexer_SyntaxError(lexer.Position, lexer.ExpressionText)); } parameters.Add(new FunctionParameterToken(identifier, parameterValue)); // Read the next parameterToken. We should be at the end, or find // we have a comma followed by something. lexer.NextToken(); currentToken = lexer.CurrentToken; if (currentToken.Kind == ExpressionTokenKind.Comma) { lexer.NextToken(); currentToken = lexer.CurrentToken; if (currentToken.Kind == endTokenKind) { // Trailing comma. throw new ODataException(ODataErrorStrings.ExpressionLexer_SyntaxError(lexer.Position, lexer.ExpressionText)); } } } return(true); }