static List <Token> ValidateAndTokenize(string expression, out ExpressionType expressionType) { expressionType = ExpressionEvaluator.PeekExpressionType(expression); if (expressionType == ExpressionType.Literal) { return(new List <Token>()); } List <Token> tokens = new List <Token>(); string workingInput = expression; int tokenEndIndex; if (expressionType == ExpressionType.Composite) { if (expression[expression.Length - 1] != '}') { throw new InvalidDataContractException(SRClient.ExpressionMissingClosingParenthesesNoToken(expression)); } workingInput = expression.Substring(1, expression.Length - 2).TrimEnd(); } while (true) { Token token = new Token(); workingInput = workingInput.TrimStart(); if (workingInput.Length < 3) { throw new InvalidDataContractException(SRClient.ExpressionInvalidToken(expression, workingInput)); } switch (workingInput[0]) { case '.': token.Type = TokenType.Dot; tokenEndIndex = ExpressionEvaluator.ExtractToken(expression, workingInput, token); break; case '%': token.Type = TokenType.Percentage; tokenEndIndex = ExpressionEvaluator.ExtractToken(expression, workingInput, token); break; case '\'': token.Type = TokenType.SingleLiteral; tokenEndIndex = ExpressionEvaluator.ExtractLiteral(expression, workingInput, token); break; case '"': token.Type = TokenType.DoubleLiteral; tokenEndIndex = ExpressionEvaluator.ExtractLiteral(expression, workingInput, token); break; case '#': token.Type = TokenType.Hash; tokenEndIndex = ExpressionEvaluator.ExtractToken(expression, workingInput, token); break; case '$': if (workingInput.ToLowerInvariant().StartsWith(BodyExpression, StringComparison.OrdinalIgnoreCase)) { tokenEndIndex = BodyExpression.Length - 1; token.Type = TokenType.Body; } else { token.Type = TokenType.Dollar; tokenEndIndex = ExpressionEvaluator.ExtractToken(expression, workingInput, token); } break; default: throw new InvalidDataContractException(SRClient.ExpressionInvalidTokenType(expression, workingInput)); } if (token.Type != TokenType.SingleLiteral && token.Type != TokenType.DoubleLiteral && token.Type != TokenType.Body && !string.Equals(token.Property, ExpressionEvaluator.BodyExpression, StringComparison.OrdinalIgnoreCase)) { if (!ExpressionEvaluator.PropertyNameRegEx.IsMatch(token.Property)) { throw new InvalidDataContractException(SRClient.PropertyNameIsBad(token.Property)); } if (token.Property.Length > ExpressionEvaluator.MaxLengthOfPropertyName) { throw new InvalidDataContractException(SRClient.PropertyTooLong(token.Property.Length, ExpressionEvaluator.MaxLengthOfPropertyName)); } } tokens.Add(token); if (workingInput.Length == tokenEndIndex + 1) { break; } workingInput = workingInput.Substring(tokenEndIndex + 1).TrimStart(); if (workingInput[0] != '+') { throw new InvalidDataContractException(SRClient.ExpressionInvalidCompositionOperator(expression, workingInput)); } workingInput = workingInput.Substring(1); } if (tokens.Count > 1 && tokens.Find((token) => token.Type == TokenType.Hash) != null) { throw new InvalidDataContractException(SRClient.ExpressionHashInComposite); } return(tokens); }