예제 #1
0
 public static object ConvertFromUriLiteral(string value, ODataVersion version, IEdmModel model, IEdmTypeReference typeReference)
 {
     Exception exception;
     ExpressionToken token;
     ExceptionUtils.CheckArgumentNotNull<string>(value, "value");
     if ((typeReference != null) && (model == null))
     {
         throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralTypeRefWithoutModel);
     }
     if (model == null)
     {
         model = EdmCoreModel.Instance;
     }
     ExpressionLexer lexer = new ExpressionLexer(value, false);
     if (!lexer.TryPeekNextToken(out token, out exception))
     {
         return ODataUriConversionUtils.ConvertFromComplexOrCollectionValue(value, version, model, typeReference);
     }
     object primitiveValue = lexer.ReadLiteralToken();
     if (typeReference != null)
     {
         primitiveValue = ODataUriConversionUtils.VerifyAndCoerceUriPrimitiveLiteral(primitiveValue, model, typeReference, version);
     }
     if (primitiveValue is ISpatial)
     {
         ODataVersionChecker.CheckSpatialValue(version);
     }
     return primitiveValue;
 }
예제 #2
0
 /// <summary>
 /// Parse an Identifier into the right QueryToken
 /// </summary>
 /// <param name="parameters">parameters passed in to the UriQueryExpressionParser</param>
 /// <param name="functionCallParser">Object to use to handle parsing function calls.</param>
 public IdentifierTokenizer(HashSet <string> parameters, IFunctionCallParser functionCallParser)
 {
     ExceptionUtils.CheckArgumentNotNull(parameters, "parameters");
     ExceptionUtils.CheckArgumentNotNull(functionCallParser, "functionCallParser");
     this.lexer              = functionCallParser.Lexer;
     this.parameters         = parameters;
     this.functionCallParser = functionCallParser;
 }
예제 #3
0
 internal string GetIdentifier()
 {
     if (this.Kind != ExpressionTokenKind.Identifier)
     {
         throw ExpressionLexer.ParseError(Strings.ExpressionToken_IdentifierExpected(this.Position));
     }
     return(this.Text);
 }
예제 #4
0
        /// <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);
        }
예제 #5
0
        /// <summary>
        /// Parses a literal.
        /// </summary>
        /// <param name="lexer">The lexer to use.</param>
        /// <returns>The literal query token or null if something else was found.</returns>
        internal static LiteralToken TryParseLiteral(ExpressionLexer lexer)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(lexer != null, "lexer != null");

            switch (lexer.CurrentToken.Kind)
            {
            case ExpressionTokenKind.BooleanLiteral:
                return(ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetBoolean(false), Microsoft.Data.OData.Metadata.EdmConstants.EdmBooleanTypeName));

            case ExpressionTokenKind.DateTimeLiteral:
                return(ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetTemporal(EdmPrimitiveTypeKind.DateTime, false), Microsoft.Data.OData.Metadata.EdmConstants.EdmDateTimeTypeName));

            case ExpressionTokenKind.DateTimeOffsetLiteral:
                return(ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetTemporal(EdmPrimitiveTypeKind.DateTimeOffset, false), Microsoft.Data.OData.Metadata.EdmConstants.EdmDateTimeOffsetTypeName));

            case ExpressionTokenKind.TimeLiteral:
                return(ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetTemporal(EdmPrimitiveTypeKind.Time, false), Microsoft.Data.OData.Metadata.EdmConstants.EdmTimeTypeName));

            case ExpressionTokenKind.DecimalLiteral:
                return(ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetDecimal(false), Microsoft.Data.OData.Metadata.EdmConstants.EdmDecimalTypeName));

            case ExpressionTokenKind.NullLiteral:
                return(ParseNullLiteral(lexer));

            case ExpressionTokenKind.StringLiteral:
                return(ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetString(true), Microsoft.Data.OData.Metadata.EdmConstants.EdmStringTypeName));

            case ExpressionTokenKind.Int64Literal:
                return(ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetInt64(false), Microsoft.Data.OData.Metadata.EdmConstants.EdmInt64TypeName));

            case ExpressionTokenKind.IntegerLiteral:
                return(ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetInt32(false), Microsoft.Data.OData.Metadata.EdmConstants.EdmInt32TypeName));

            case ExpressionTokenKind.DoubleLiteral:
                return(ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetDouble(false), Microsoft.Data.OData.Metadata.EdmConstants.EdmDoubleTypeName));

            case ExpressionTokenKind.SingleLiteral:
                return(ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetSingle(false), Microsoft.Data.OData.Metadata.EdmConstants.EdmSingleTypeName));

            case ExpressionTokenKind.GuidLiteral:
                return(ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetGuid(false), Microsoft.Data.OData.Metadata.EdmConstants.EdmGuidTypeName));

            case ExpressionTokenKind.BinaryLiteral:
                return(ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetBinary(true), Microsoft.Data.OData.Metadata.EdmConstants.EdmBinaryTypeName));

            case ExpressionTokenKind.GeographyLiteral:
                return(ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.Geography, false), Microsoft.Data.OData.Metadata.EdmConstants.EdmGeographyTypeName));

            case ExpressionTokenKind.GeometryLiteral:
                return(ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.Geometry, false), Microsoft.Data.OData.Metadata.EdmConstants.EdmGeometryTypeName));

            default:
                return(null);
            }
        }
예제 #6
0
        /// <summary>
        /// Parses null literals.
        /// </summary>
        /// <param name="lexer">The lexer to use.</param>
        /// <returns>The literal token produced by building the given literal.</returns>
        private static LiteralToken ParseNullLiteral(ExpressionLexer lexer)
        {
            Debug.Assert(lexer != null, "lexer != null");
            Debug.Assert(lexer.CurrentToken.Kind == ExpressionTokenKind.NullLiteral, "this.lexer.CurrentToken.InternalKind == ExpressionTokenKind.NullLiteral");

            LiteralToken result = new LiteralToken(null, lexer.CurrentToken.Text);

            lexer.NextToken();
            return(result);
        }
예제 #7
0
        /// <summary>
        /// Parses a literal.
        /// Precondition: lexer is at a literal token type: Boolean, DateTime, Decimal, Null, String, Int64, Integer, Double, Single, Guid, Binary.
        /// </summary>
        /// <returns>The literal query token or null if something else was found.</returns>
        private object TryParseLiteral()
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(ExpressionLexer.IsLiteralType(this.CurrentToken.Kind), "TryParseLiteral called when not at a literal type token");

            switch (this.CurrentToken.Kind)
            {
            case ExpressionTokenKind.BooleanLiteral:
                return(this.ParseTypedLiteral(EdmCoreModel.Instance.GetBoolean(false)));

            case ExpressionTokenKind.DateTimeLiteral:
                return(this.ParseTypedLiteral(EdmCoreModel.Instance.GetTemporal(EdmPrimitiveTypeKind.DateTime, false)));

            case ExpressionTokenKind.DecimalLiteral:
                return(this.ParseTypedLiteral(EdmCoreModel.Instance.GetDecimal(false)));

            case ExpressionTokenKind.NullLiteral:
                return(this.ParseNullLiteral());

            case ExpressionTokenKind.StringLiteral:
                return(this.ParseTypedLiteral(EdmCoreModel.Instance.GetString(true)));

            case ExpressionTokenKind.Int64Literal:
                return(this.ParseTypedLiteral(EdmCoreModel.Instance.GetInt64(false)));

            case ExpressionTokenKind.IntegerLiteral:
                return(this.ParseTypedLiteral(EdmCoreModel.Instance.GetInt32(false)));

            case ExpressionTokenKind.DoubleLiteral:
                return(this.ParseTypedLiteral(EdmCoreModel.Instance.GetDouble(false)));

            case ExpressionTokenKind.SingleLiteral:
                return(this.ParseTypedLiteral(EdmCoreModel.Instance.GetSingle(false)));

            case ExpressionTokenKind.GuidLiteral:
                return(this.ParseTypedLiteral(EdmCoreModel.Instance.GetGuid(false)));

            case ExpressionTokenKind.BinaryLiteral:
                return(this.ParseTypedLiteral(EdmCoreModel.Instance.GetBinary(true)));

            case ExpressionTokenKind.DateTimeOffsetLiteral:
                return(this.ParseTypedLiteral(EdmCoreModel.Instance.GetDateTimeOffset(false)));

            case ExpressionTokenKind.TimeLiteral:
                return(this.ParseTypedLiteral(EdmCoreModel.Instance.GetTemporal(EdmPrimitiveTypeKind.Time, false)));

            case ExpressionTokenKind.GeographyLiteral:
                return(this.ParseTypedLiteral(EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.Geography, false)));

            case ExpressionTokenKind.GeometryLiteral:
                return(this.ParseTypedLiteral(EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.Geometry, false)));
            }

            return(null);
        }
예제 #8
0
        /// <summary>Gets the current identifier text.</summary>
        /// <returns>The current identifier text.</returns>
        internal string GetIdentifier()
        {
            DebugUtils.CheckNoExternalCallers();

            if (this.Kind != ExpressionTokenKind.Identifier)
            {
                throw ExpressionLexer.ParseError(Strings.ExpressionToken_IdentifierExpected(this.Position));
            }

            Debug.Assert(this.Text != null, "Text is null");
            return(this.Text);
        }
예제 #9
0
        /// <summary>
        /// Parses the key value literal.
        /// </summary>
        /// <param name="lexer">The lexer positioned on the key value.</param>
        /// <returns>The literal query token.</returns>
        private static LiteralQueryToken ParseKeyValueLiteral(ExpressionLexer lexer)
        {
            Debug.Assert(lexer != null, "lexer != null");

            LiteralQueryToken result = UriQueryExpressionParser.TryParseLiteral(lexer);

            if (result == null)
            {
                throw new ODataException(Strings.UriQueryPathParser_InvalidKeyValueLiteral(lexer.CurrentToken.Text));
            }

            return(result);
        }
예제 #10
0
        /// <summary>
        /// Parses the $filter expression.
        /// </summary>
        /// <param name="filter">The $filter expression string to parse.</param>
        /// <returns>The lexical token representing the filter.</returns>
        internal QueryToken ParseFilter(string filter)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(filter != null, "filter != null");

            this.recursionDepth = 0;
            this.lexer          = new ExpressionLexer(filter, true /*moveToFirstToken*/);
            QueryToken result = this.ParseExpression();

            this.lexer.ValidateToken(ExpressionTokenKind.End);

            return(result);
        }
예제 #11
0
        /// <summary>Reads the next token, checks that it is a literal token type, converts to to a Common Language Runtime value as appropriate, and returns the value.</summary>
        /// <param name="expressionLexer">The expression lexer.</param>
        /// <returns>The value represented by the next token.</returns>
        internal static object ReadLiteralToken(this ExpressionLexer expressionLexer)
        {
            DebugUtils.CheckNoExternalCallers();

            expressionLexer.NextToken();

            if (expressionLexer.CurrentToken.Kind.IsLiteralType())
            {
                return(TryParseLiteral(expressionLexer));
            }

            throw new ODataException(ODataErrorStrings.ExpressionLexer_ExpectedLiteralToken(expressionLexer.CurrentToken.Text));
        }
예제 #12
0
        /// <summary>Reads the next token, checks that it is a literal token type, converts to to a Common Language Runtime value as appropriate, and returns the value.</summary>
        /// <returns>The value represented by the next token.</returns>
        internal object ReadLiteralToken()
        {
            DebugUtils.CheckNoExternalCallers();

            this.NextToken();

            if (ExpressionLexer.IsLiteralType(this.CurrentToken.Kind))
            {
                return(this.TryParseLiteral());
            }

            throw new ODataException(o.Strings.ExpressionLexer_ExpectedLiteralToken(this.CurrentToken.Text));
        }
예제 #13
0
        /// <summary>
        /// Parses the $filter expression.
        /// </summary>
        /// <param name="filter">The $filter expression string to parse.</param>
        /// <returns>The lexical token representing the filter.</returns>
        internal QueryToken ParseFilter(string filter)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(filter != null, "filter != null");

            this.recursionDepth = 0;
            this.lexer          = CreateLexerForFilterOrOrderByExpression(filter);
            QueryToken result = this.ParseExpression();

            this.lexer.ValidateToken(ExpressionTokenKind.End);

            return(result);
        }
예제 #14
0
        /// <summary>
        /// Tries to parse a collection of function parameters for path.
        /// </summary>
        /// <param name="functionName">The function name to use in error messages.</param>
        /// <param name="parenthesisExpression">The contents of the parentheses portion of the current path segment.</param>
        /// <param name="splitParameters">The parameters if they were successfully split.</param>
        /// <returns>Whether the parameters could be split.</returns>
        internal static bool TrySplitFunctionParameters(string functionName, string parenthesisExpression, out ICollection <FunctionParameterToken> splitParameters)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(!string.IsNullOrEmpty(parenthesisExpression), "!string.IsNullOrEmpty(parenthesisExpression)");
            var lexer = new ExpressionLexer(parenthesisExpression, true /*moveToFirstToken*/, false /*useSemicolonDelimiter*/, true /*parsingFunctionParameters*/);

            if (lexer.CurrentToken.IsFunctionParameterToken)
            {
                splitParameters = null;
                return(false);
            }

            return(TrySplitFunctionParameters(lexer, ExpressionTokenKind.End, out splitParameters));
        }
예제 #15
0
        /// <summary>
        /// Parses typed literals.
        /// </summary>
        /// <param name="expressionLexer">The expression lexer.</param>
        /// <param name="targetTypeReference">Expected type to be parsed.</param>
        /// <returns>The literal token produced by building the given literal.</returns>
        private static object ParseTypedLiteral(this ExpressionLexer expressionLexer, IEdmPrimitiveTypeReference targetTypeReference)
        {
            object targetValue;

            if (!UriPrimitiveTypeParser.TryUriStringToPrimitive(expressionLexer.CurrentToken.Text, targetTypeReference, out targetValue))
            {
                string message = ODataErrorStrings.UriQueryExpressionParser_UnrecognizedLiteral(
                    targetTypeReference.FullName(),
                    expressionLexer.CurrentToken.Text,
                    expressionLexer.CurrentToken.Position,
                    expressionLexer.ExpressionText);
                throw new ODataException(message);
            }

            expressionLexer.NextToken();
            return(targetValue);
        }
예제 #16
0
        /// <summary>
        /// Parses null literals.
        /// </summary>
        /// <param name="expressionLexer">The expression lexer.</param>
        /// <returns>The literal token produced by building the given literal.</returns>
        private static object ParseNullLiteral(this ExpressionLexer expressionLexer)
        {
            Debug.Assert(expressionLexer.CurrentToken.Kind == ExpressionTokenKind.NullLiteral, "this.lexer.CurrentToken.InternalKind == ExpressionTokenKind.NullLiteral");

            expressionLexer.NextToken();
            ODataUriNullValue nullValue = new ODataUriNullValue();

            if (expressionLexer.ExpressionText == ExpressionConstants.KeywordNull)
            {
                return(nullValue);
            }

            int nullLiteralLength = ExpressionConstants.LiteralSingleQuote.Length * 2 + ExpressionConstants.KeywordNull.Length;
            int startOfTypeIndex  = ExpressionConstants.LiteralSingleQuote.Length + ExpressionConstants.KeywordNull.Length;

            nullValue.TypeName = expressionLexer.ExpressionText.Substring(startOfTypeIndex, expressionLexer.ExpressionText.Length - nullLiteralLength);
            return(nullValue);
        }
        /// <summary>
        /// Parses a literal.
        /// </summary>
        /// <param name="lexer">The lexer to use.</param>
        /// <returns>The literal query token or null if something else was found.</returns>
        internal static LiteralQueryToken TryParseLiteral(ExpressionLexer lexer)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(lexer != null, "lexer != null");

            switch (lexer.CurrentToken.Kind)
            {
                case ExpressionTokenKind.BooleanLiteral:
                    return ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetBoolean(false), Microsoft.Data.OData.Metadata.EdmConstants.EdmBooleanTypeName);
                case ExpressionTokenKind.DateTimeLiteral:
                    return ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetTemporal(EdmPrimitiveTypeKind.DateTime, false), Microsoft.Data.OData.Metadata.EdmConstants.EdmDateTimeTypeName);
                case ExpressionTokenKind.DateTimeOffsetLiteral:
                    return ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetTemporal(EdmPrimitiveTypeKind.DateTimeOffset, false), Microsoft.Data.OData.Metadata.EdmConstants.EdmDateTimeOffsetTypeName);
                case ExpressionTokenKind.TimeLiteral:
                    return ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetTemporal(EdmPrimitiveTypeKind.Time, false), Microsoft.Data.OData.Metadata.EdmConstants.EdmTimeTypeName);
                case ExpressionTokenKind.DecimalLiteral:
                    return ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetDecimal(false), Microsoft.Data.OData.Metadata.EdmConstants.EdmDecimalTypeName);
                case ExpressionTokenKind.NullLiteral:
                    return ParseNullLiteral(lexer);
                case ExpressionTokenKind.StringLiteral:
                    return ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetString(true), Microsoft.Data.OData.Metadata.EdmConstants.EdmStringTypeName);
                case ExpressionTokenKind.Int64Literal:
                    return ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetInt64(false), Microsoft.Data.OData.Metadata.EdmConstants.EdmInt64TypeName);
                case ExpressionTokenKind.IntegerLiteral:
                    return ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetInt32(false), Microsoft.Data.OData.Metadata.EdmConstants.EdmInt32TypeName);
                case ExpressionTokenKind.DoubleLiteral:
                    return ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetDouble(false), Microsoft.Data.OData.Metadata.EdmConstants.EdmDoubleTypeName);
                case ExpressionTokenKind.SingleLiteral:
                    return ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetSingle(false), Microsoft.Data.OData.Metadata.EdmConstants.EdmSingleTypeName);
                case ExpressionTokenKind.GuidLiteral:
                    return ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetGuid(false), Microsoft.Data.OData.Metadata.EdmConstants.EdmGuidTypeName);
                case ExpressionTokenKind.BinaryLiteral:
                    return ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetBinary(true), Microsoft.Data.OData.Metadata.EdmConstants.EdmBinaryTypeName);
                case ExpressionTokenKind.GeographyLiteral:
                    return ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.Geography, false), Microsoft.Data.OData.Metadata.EdmConstants.EdmGeographyTypeName);
                case ExpressionTokenKind.GeometryLiteral:
                    return ParseTypedLiteral(lexer, EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.Geometry, false), Microsoft.Data.OData.Metadata.EdmConstants.EdmGeometryTypeName);
                default:
                    return null;
            }
        }
예제 #18
0
        /// <summary>
        /// Converts the given <paramref name="value"/> to a corresponding CLR type. Expects the
        /// <paramref name="value"/> to have already been properly unescaped from an actual Uri.
        /// </summary>
        /// <param name="value">Value from a Uri to be converted.</param>
        /// <param name="version">Version to be compliant with.</param>
        /// <param name="model">Optional model to perform verification against.</param>
        /// <param name="typeReference">Optional IEdmTypeReference to perform verification against.
        ///  Callers must provide a <paramref name="model"/> containing this type if it is specified.</param>
        /// <returns>A CLR object that the <paramref name="value"/> represents.</returns>
        public static object ConvertFromUriLiteral(string value, ODataVersion version, IEdmModel model, IEdmTypeReference typeReference)
        {
            ExceptionUtils.CheckArgumentNotNull(value, "value");
            if (typeReference != null && model == null)
            {
                throw new ODataException(ODataErrorStrings.ODataUriUtils_ConvertFromUriLiteralTypeRefWithoutModel);
            }

            if (model == null)
            {
                model = Microsoft.Data.Edm.Library.EdmCoreModel.Instance;
            }

            // Let ExpressionLexer try to get a primitive
            ExpressionLexer lexer = new ExpressionLexer(value, false /*moveToFirstToken*/, false /*useSemicolonDelimeter*/);
            Exception       error;
            ExpressionToken token;

            lexer.TryPeekNextToken(out token, out error);

            if (token.Kind == ExpressionTokenKind.BracketedExpression)
            {
                // Should be a complex or collection value
                return(ODataUriConversionUtils.ConvertFromComplexOrCollectionValue(value, version, model, typeReference));
            }

            object result = lexer.ReadLiteralToken();

            // If we have a typeReference then perform verification and convert if necessary
            if (typeReference != null)
            {
                result = ODataUriConversionUtils.VerifyAndCoerceUriPrimitiveLiteral(result, model, typeReference, version);
            }

            if (result is ISpatial)
            {
                ODataVersionChecker.CheckSpatialValue(version);
            }

            return(result);
        }
예제 #19
0
        /// <summary>
        /// Parses typed literals.
        /// </summary>
        /// <param name="lexer">The lexer to use.</param>
        /// <param name="targetTypeReference">Expected type to be parsed.</param>
        /// <param name="targetTypeName">The EDM type name of the expected type to be parsed.</param>
        /// <returns>The literal token produced by building the given literal.</returns>
        private static LiteralToken ParseTypedLiteral(ExpressionLexer lexer, IEdmPrimitiveTypeReference targetTypeReference, string targetTypeName)
        {
            Debug.Assert(lexer != null, "lexer != null");

            object targetValue;

            if (!UriPrimitiveTypeParser.TryUriStringToPrimitive(lexer.CurrentToken.Text, targetTypeReference, out targetValue))
            {
                string message = ODataErrorStrings.UriQueryExpressionParser_UnrecognizedLiteral(
                    targetTypeName,
                    lexer.CurrentToken.Text,
                    lexer.CurrentToken.Position,
                    lexer.ExpressionText);
                throw ParseError(message);
            }

            LiteralToken result = new LiteralToken(targetValue, lexer.CurrentToken.Text);

            lexer.NextToken();
            return(result);
        }
예제 #20
0
        /// <summary>
        /// Converts the given <paramref name="value"/> to a corresponding CLR type. Expects the 
        /// <paramref name="value"/> to have already been properly unescaped from an actual Uri.
        /// </summary>
        /// <param name="value">Value from a Uri to be converted.</param>
        /// <param name="version">Version to be compliant with.</param>
        /// <param name="model">Optional model to perform verification against.</param>
        /// <param name="typeReference">Optional IEdmTypeReference to perform verification against. 
        ///  Callers must provide a <paramref name="model"/> containing this type if it is specified.</param>
        /// <returns>A CLR object that the <paramref name="value"/> represents.</returns>
        public static object ConvertFromUriLiteral(string value, ODataVersion version, IEdmModel model, IEdmTypeReference typeReference)
        {
            ExceptionUtils.CheckArgumentNotNull(value, "value");
            if (typeReference != null && model == null)
            {
                throw new ODataException(o.Strings.ODataUriUtils_ConvertFromUriLiteralTypeRefWithoutModel);
            }

            if (model == null)
            {
                model = Microsoft.Data.Edm.Library.EdmCoreModel.Instance;
            }

            // Let ExpressionLexer try to get a primitive
            ExpressionLexer lexer = new ExpressionLexer(value, false /*moveToFirstToken*/);
            Exception error;
            ExpressionToken token;

            if (lexer.TryPeekNextToken(out token, out error))
            {
                object result = lexer.ReadLiteralToken();

                // If we have a typeReference then perform verification and convert if necessary
                if (typeReference != null)
                {
                    result = ODataUriConversionUtils.VerifyAndCoerceUriPrimitiveLiteral(result, model, typeReference, version);
                }

                if (result is ISpatial)
                {
                    ODataVersionChecker.CheckSpatialValue(version);
                }

                return result;
            }

            // Should be a complex or collection value
            return ODataUriConversionUtils.ConvertFromComplexOrCollectionValue(value, version, model, typeReference);
        }
예제 #21
0
        /// <summary>
        /// Parses the $expand expression.
        /// </summary>
        /// <param name="expand">The $expand expression string to parse.</param>
        /// <returns>The lexical token representing the expand.</returns>
        internal ExpandQueryToken ParseExpand(string expand)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(expand != null, "expand != null");

            this.lexer = new ExpressionLexer(expand, true /*moveToFirstToken*/);

            List <QueryToken> properties = new List <QueryToken>();

            while (true)
            {
                properties.Add(this.ParseExpression());
                if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.Comma)
                {
                    break;
                }

                this.lexer.NextToken();
            }

            return(new ExpandQueryToken(properties));
        }
예제 #22
0
        /// <summary>
        /// Parses the $orderby expression.
        /// </summary>
        /// <param name="orderBy">The $orderby expression string to parse.</param>
        /// <returns>The enumeraion of lexical tokens representing order by tokens.</returns>
        internal IEnumerable <OrderByToken> ParseOrderBy(string orderBy)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(orderBy != null, "orderBy != null");

            this.recursionDepth = 0;
            this.lexer          = CreateLexerForFilterOrOrderByExpression(orderBy);

            List <OrderByToken> orderByTokens = new List <OrderByToken>();

            while (true)
            {
                QueryToken expression = this.ParseExpression();
                bool       ascending  = true;
                if (this.TokenIdentifierIs(ExpressionConstants.KeywordAscending))
                {
                    this.lexer.NextToken();
                }
                else if (this.TokenIdentifierIs(ExpressionConstants.KeywordDescending))
                {
                    this.lexer.NextToken();
                    ascending = false;
                }

                OrderByToken orderByToken = new OrderByToken(expression, ascending ? OrderByDirection.Ascending : OrderByDirection.Descending);
                orderByTokens.Add(orderByToken);
                if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.Comma)
                {
                    break;
                }

                this.lexer.NextToken();
            }

            this.lexer.ValidateToken(ExpressionTokenKind.End);

            return(new ReadOnlyCollection <OrderByToken>(orderByTokens));
        }
예제 #23
0
        /// <summary>
        /// Parses the -, not unary operators.
        /// </summary>
        /// <returns>The lexical token representing the expression.</returns>
        private QueryToken ParseUnary()
        {
            this.RecurseEnter();
            if (this.lexer.CurrentToken.Kind == ExpressionTokenKind.Minus || this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordNot))
            {
                ExpressionToken operatorToken = this.lexer.CurrentToken;
                this.lexer.NextToken();
                if (operatorToken.Kind == ExpressionTokenKind.Minus && (ExpressionLexer.IsNumeric(this.lexer.CurrentToken.Kind)))
                {
                    ExpressionToken numberLiteral = this.lexer.CurrentToken;
                    numberLiteral.Text      = "-" + numberLiteral.Text;
                    numberLiteral.Position  = operatorToken.Position;
                    this.lexer.CurrentToken = numberLiteral;
                    this.RecurseLeave();
                    return(this.ParsePrimary());
                }

                QueryToken        operand = this.ParseUnary();
                UnaryOperatorKind unaryOperatorKind;
                if (operatorToken.Kind == ExpressionTokenKind.Minus)
                {
                    unaryOperatorKind = UnaryOperatorKind.Negate;
                }
                else
                {
                    Debug.Assert(operatorToken.IdentifierIs(ExpressionConstants.KeywordNot), "Was a new unary operator added?");
                    unaryOperatorKind = UnaryOperatorKind.Not;
                }

                this.RecurseLeave();
                return(new UnaryOperatorQueryToken(unaryOperatorKind, operand));
            }

            this.RecurseLeave();
            return(this.ParsePrimary());
        }
예제 #24
0
        /// <summary>Attempts to parse key values from the specified text.</summary>
        /// <param name='text'>Text to parse (not null).</param>
        /// <returns>
        /// Enumeration of key values or null if there was a syntax error.
        /// </returns>
        /// <remarks>
        /// The returned instance contains only string values.
        /// </remarks>
        private static IEnumerable <NamedValue> ParseKeyValuesFromUri(string text)
        {
            Debug.Assert(text != null, "text != null");

            //// This is a modified copy of KeyInstance.TryParseFromUri

            ExpressionLexer lexer        = new ExpressionLexer(text, true /*moveToFirstToken*/);
            ExpressionToken currentToken = lexer.CurrentToken;

            if (currentToken.Kind == ExpressionTokenKind.End)
            {
                return(EmptyKeyValues);
            }

            List <NamedValue> keyValuesList = new List <NamedValue>();

            do
            {
                if (currentToken.Kind == ExpressionTokenKind.Identifier)
                {
                    // Name-value pair.
                    string identifier = lexer.CurrentToken.GetIdentifier();
                    lexer.NextToken();
                    if (lexer.CurrentToken.Kind != ExpressionTokenKind.Equal)
                    {
                        return(null);
                    }

                    lexer.NextToken();
                    if (!lexer.CurrentToken.IsKeyValueToken)
                    {
                        return(null);
                    }

                    keyValuesList.Add(new NamedValue(identifier, ParseKeyValueLiteral(lexer)));
                }
                else if (currentToken.IsKeyValueToken)
                {
                    // Unnamed value.
                    keyValuesList.Add(new NamedValue(null, ParseKeyValueLiteral(lexer)));
                }
                else
                {
                    return(null);
                }

                // Read the next token. We should be at the end, or find
                // we have a comma followed by something.
                currentToken = lexer.NextToken();
                if (currentToken.Kind == ExpressionTokenKind.Comma)
                {
                    currentToken = lexer.NextToken();
                    if (currentToken.Kind == ExpressionTokenKind.End)
                    {
                        // Trailing comma.
                        return(null);
                    }
                }
            }while (currentToken.Kind != ExpressionTokenKind.End);

            return(keyValuesList);
        }
예제 #25
0
 /// <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="splitParameters">The parameters if they were successfully split.</param>
 /// <returns>Whether the parameters could be split.</returns>
 internal static bool TrySplitFunctionParameters(this ExpressionLexer lexer, out ICollection <FunctionParameterToken> splitParameters)
 {
     DebugUtils.CheckNoExternalCallers();
     return(lexer.TrySplitFunctionParameters(ExpressionTokenKind.CloseParen, out splitParameters));
 }
        /// <summary>
        /// Parses the $filter expression.
        /// </summary>
        /// <param name="filter">The $filter expression string to parse.</param>
        /// <returns>The lexical token representing the filter.</returns>
        internal QueryToken ParseFilter(string filter)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(filter != null, "filter != null");

            this.recursionDepth = 0;
            this.lexer = new ExpressionLexer(filter, true /*moveToFirstToken*/);
            QueryToken result = this.ParseExpression();
            this.lexer.ValidateToken(ExpressionTokenKind.End);

            return result;
        }
        /// <summary>
        /// Parses the $orderby expression.
        /// </summary>
        /// <param name="orderBy">The $orderby expression string to parse.</param>
        /// <returns>The enumeraion of lexical tokens representing order by tokens.</returns>
        internal IEnumerable<OrderByQueryToken> ParseOrderBy(string orderBy)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(orderBy != null, "orderBy != null");

            this.recursionDepth = 0;
            this.lexer = new ExpressionLexer(orderBy, true /*moveToFirstToken*/);

            List<OrderByQueryToken> orderByTokens = new List<OrderByQueryToken>();
            while (true)
            {
                QueryToken expression = this.ParseExpression();
                bool ascending = true;
                if (this.TokenIdentifierIs(ExpressionConstants.KeywordAscending))
                {
                    this.lexer.NextToken();
                }
                else if (this.TokenIdentifierIs(ExpressionConstants.KeywordDescending))
                {
                    this.lexer.NextToken();
                    ascending = false;
                }

                OrderByQueryToken orderByToken = new OrderByQueryToken(expression, ascending ? OrderByDirection.Ascending : OrderByDirection.Descending);
                orderByTokens.Add(orderByToken);
                if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.Comma)
                {
                    break;
                }

                this.lexer.NextToken();
            }

            this.lexer.ValidateToken(ExpressionTokenKind.End);

            return new ReadOnlyCollection<OrderByQueryToken>(orderByTokens);
        }
예제 #28
0
        /// <summary>
        /// Parses the key value literal.
        /// </summary>
        /// <param name="lexer">The lexer positioned on the key value.</param>
        /// <returns>The literal query token.</returns>
        private static LiteralQueryToken ParseKeyValueLiteral(ExpressionLexer lexer)
        {
            Debug.Assert(lexer != null, "lexer != null");

            LiteralQueryToken result = UriQueryExpressionParser.TryParseLiteral(lexer);
            if (result == null)
            {
                throw new ODataException(Strings.UriQueryPathParser_InvalidKeyValueLiteral(lexer.CurrentToken.Text));
            }

            return result;
        }
예제 #29
0
        /// <summary>Attempts to parse key values from the specified text.</summary>
        /// <param name='text'>Text to parse (not null).</param>
        /// <returns>
        /// Enumeration of key values or null if there was a syntax error.
        /// </returns>
        /// <remarks>
        /// The returned instance contains only string values.
        /// </remarks>
        private static IEnumerable<NamedValue> ParseKeyValuesFromUri(string text)
        {
            Debug.Assert(text != null, "text != null");

            //// This is a modified copy of KeyInstance.TryParseFromUri

            ExpressionLexer lexer = new ExpressionLexer(text, true /*moveToFirstToken*/);
            ExpressionToken currentToken = lexer.CurrentToken;
            if (currentToken.Kind == ExpressionTokenKind.End)
            {
                return EmptyKeyValues;
            }

            List<NamedValue> keyValuesList = new List<NamedValue>();
            do
            {
                if (currentToken.Kind == ExpressionTokenKind.Identifier)
                {
                    // Name-value pair.
                    string identifier = lexer.CurrentToken.GetIdentifier();
                    lexer.NextToken();
                    if (lexer.CurrentToken.Kind != ExpressionTokenKind.Equal)
                    {
                        return null;
                    }

                    lexer.NextToken();
                    if (!lexer.CurrentToken.IsKeyValueToken)
                    {
                        return null;
                    }

                    keyValuesList.Add(new NamedValue(identifier, ParseKeyValueLiteral(lexer)));
                }
                else if (currentToken.IsKeyValueToken)
                {
                    // Unnamed value.
                    keyValuesList.Add(new NamedValue(null, ParseKeyValueLiteral(lexer)));
                }
                else
                {
                    return null;
                }

                // Read the next token. We should be at the end, or find
                // we have a comma followed by something.
                currentToken = lexer.NextToken();
                if (currentToken.Kind == ExpressionTokenKind.Comma)
                {
                    currentToken = lexer.NextToken();
                    if (currentToken.Kind == ExpressionTokenKind.End)
                    {
                        // Trailing comma.
                        return null;
                    }
                }
            }
            while (currentToken.Kind != ExpressionTokenKind.End);

            return keyValuesList;
        }
        /// <summary>
        /// Parses the $expand expression.
        /// </summary>
        /// <param name="expand">The $expand expression string to parse.</param>
        /// <returns>The lexical token representing the expand.</returns>
        internal ExpandQueryToken ParseExpand(string expand)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(expand != null, "expand != null");

            this.lexer = new ExpressionLexer(expand, true /*moveToFirstToken*/);

            List<QueryToken> properties = new List<QueryToken>();
            while (true)
            {
                properties.Add(this.ParseExpression());
                if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.Comma)
                {
                    break;
                }

                this.lexer.NextToken();
            }

            return new ExpandQueryToken(properties);
        }
        /// <summary>
        /// Parses typed literals.
        /// </summary>
        /// <param name="lexer">The lexer to use.</param>
        /// <param name="targetTypeReference">Expected type to be parsed.</param>
        /// <param name="targetTypeName">The EDM type name of the expected type to be parsed.</param>
        /// <returns>The literal token produced by building the given literal.</returns>
        private static LiteralQueryToken ParseTypedLiteral(ExpressionLexer lexer, IEdmPrimitiveTypeReference targetTypeReference, string targetTypeName)
        {
            Debug.Assert(lexer != null, "lexer != null");

            object targetValue;
            if (!UriPrimitiveTypeParser.TryUriStringToPrimitive(lexer.CurrentToken.Text, targetTypeReference, out targetValue))
            {
                string message = Strings.UriQueryExpressionParser_UnrecognizedLiteral(
                    targetTypeName,
                    lexer.CurrentToken.Text,
                    lexer.CurrentToken.Position,
                    lexer.ExpressionText);
                throw ParseError(message);
            }

            LiteralQueryToken result = new LiteralQueryToken(targetValue, lexer.CurrentToken.Text);
            lexer.NextToken();
            return result;
        }
        /// <summary>
        /// Parses null literals.
        /// </summary>
        /// <param name="lexer">The lexer to use.</param>
        /// <returns>The literal token produced by building the given literal.</returns>
        private static LiteralQueryToken ParseNullLiteral(ExpressionLexer lexer)
        {
            Debug.Assert(lexer != null, "lexer != null");
            Debug.Assert(lexer.CurrentToken.Kind == ExpressionTokenKind.NullLiteral, "this.lexer.CurrentToken.Kind == ExpressionTokenKind.NullLiteral");

            LiteralQueryToken result = new LiteralQueryToken(null, lexer.CurrentToken.Text);

            lexer.NextToken();
            return result;
        }
예제 #33
0
        /// <summary>Attempts to parse key values from the specified text.</summary>
        /// <param name='text'>Text to parse (not null).</param>
        /// <param name="allowNamedValues">Set to true if the parser should accept named values
        ///     so syntax like Name='value'. If this is false, the parsing will fail on such constructs.</param>
        /// <param name="allowNull">Set to true if the parser should accept null values.
        ///     If set to false, the parser will fail on null values.</param>
        /// <param name='instance'>After invocation, the parsed key instance.</param>
        /// <returns>
        /// true if the key instance was parsed; false if there was a
        /// syntactic error.
        /// </returns>
        /// <remarks>
        /// The returned instance contains only string values. To get typed values, a call to
        /// TryConvertValues is necessary.
        /// </remarks>
        private static bool TryParseFromUri(string text, bool allowNamedValues, bool allowNull, out SegmentArgumentParser instance)
        {
            Debug.Assert(text != null, "text != null");

            Dictionary <string, string> namedValues = null;
            List <string>   positionalValues        = null;
            ExpressionLexer lexer        = new ExpressionLexer(text, true, false);
            ExpressionToken currentToken = lexer.CurrentToken;

            if (currentToken.Kind == ExpressionTokenKind.End)
            {
                instance = Empty;
                return(true);
            }

            instance = null;
            do
            {
                if (currentToken.Kind == ExpressionTokenKind.Identifier && allowNamedValues)
                {
                    // Name-value pair.
                    if (positionalValues != null)
                    {
                        // We cannot mix named and non-named values.
                        return(false);
                    }

                    string identifier = lexer.CurrentToken.GetIdentifier();
                    lexer.NextToken();
                    if (lexer.CurrentToken.Kind != ExpressionTokenKind.Equal)
                    {
                        return(false);
                    }

                    lexer.NextToken();
                    if (!lexer.CurrentToken.IsKeyValueToken)
                    {
                        return(false);
                    }

                    string namedValue = lexer.CurrentToken.Text;
                    CreateIfNull(ref namedValues);
                    if (namedValues.ContainsKey(identifier))
                    {
                        // Duplicate name.
                        return(false);
                    }

                    namedValues.Add(identifier, namedValue);
                }
                else if (currentToken.IsKeyValueToken || (allowNull && currentToken.Kind == ExpressionTokenKind.NullLiteral))
                {
                    // Positional value.
                    if (namedValues != null)
                    {
                        // We cannot mix named and non-named values.
                        return(false);
                    }

                    CreateIfNull(ref positionalValues);
                    positionalValues.Add(lexer.CurrentToken.Text);
                }
                else
                {
                    return(false);
                }

                // Read the next token. 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 == ExpressionTokenKind.End)
                    {
                        // Trailing comma.
                        return(false);
                    }
                }
            }while (currentToken.Kind != ExpressionTokenKind.End);

            instance = new SegmentArgumentParser(namedValues, positionalValues, false);
            return(true);
        }
예제 #34
0
 /// <summary>
 /// Create a SelectExpandTermParser
 /// </summary>
 /// <param name="clauseToParse">the clause to parse</param>
 /// <param name="maxDepth">the maximum recursive depth</param>
 protected SelectExpandTermParser(string clauseToParse, int maxDepth)
 {
     this.maxDepth       = maxDepth;
     this.recursionDepth = 0;
     this.Lexer          = clauseToParse != null ? new ExpressionLexer(clauseToParse, false, true) : null;
 }