Exemplo n.º 1
0
        private IExpression ParseExpression(PrecedenceLevel precedence)
        {
            _tracer.Trace("ParseExpression");
            PrefixParseFn prefix;
            var           ok = _prefixParseFns.TryGetValue(_curToken.Type, out prefix);

            if (!ok)
            {
                NoPrefixParseFnError(_curToken.Type);
                return(null);
            }
            var leftExpr = prefix();

            // The precedence is what the original Pratt paper refers to as
            // right-binding power and PeekPrecedence() is what it refers to as
            // left-binding power. For as long as left-binding power >
            // right-binding power, we're going to add another level to the
            // Abstract Syntax Three, signifying operations which need to be
            // carried out first when the expression is evaluated.
            while (!PeekTokenIs(TokenType.Semicolon) && precedence < PeekPrecedence())
            {
                InfixParseFn infix;
                ok = _infixParseFns.TryGetValue(_peekToken.Type, out infix);
                if (!ok)
                {
                    return(leftExpr);
                }
                NextToken();
                leftExpr = infix(leftExpr);
            }
            _tracer.Untrace("ParseExpression");

            return(leftExpr);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Parenthesizes the expression if it does not have the minimum required precedence.
 /// </summary>
 static void ParenthesizeIfRequired(Expression expr, PrecedenceLevel minimumPrecedence)
 {
     if (GetPrecedence(expr) < minimumPrecedence)
     {
         Parenthesize(expr);
     }
 }
Exemplo n.º 3
0
        // Binary Operators
        public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)
        {
            PrecedenceLevel precedence = GetPrecedence(binaryOperatorExpression);

            if (binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing)
            {
                if (InsertParenthesesForReadability)
                {
                    ParenthesizeIfRequired(binaryOperatorExpression.Left, PrecedenceLevel.NullableRewrap);
                    if (GetBinaryOperatorType(binaryOperatorExpression.Right) == BinaryOperatorType.NullCoalescing)
                    {
                        ParenthesizeIfRequired(binaryOperatorExpression.Right, precedence);
                    }
                    else
                    {
                        ParenthesizeIfRequired(binaryOperatorExpression.Right, PrecedenceLevel.NullableRewrap);
                    }
                }
                else
                {
                    // ?? is right-associative
                    ParenthesizeIfRequired(binaryOperatorExpression.Left, precedence + 1);
                    ParenthesizeIfRequired(binaryOperatorExpression.Right, precedence);
                }
            }
            else
            {
                if (InsertParenthesesForReadability && precedence < PrecedenceLevel.Equality)
                {
                    // In readable mode, boost the priority of the left-hand side if the operator
                    // there isn't the same as the operator on this expression.
                    PrecedenceLevel boostTo = IsBitwise(binaryOperatorExpression.Operator) ? PrecedenceLevel.Unary : PrecedenceLevel.Equality;
                    if (GetBinaryOperatorType(binaryOperatorExpression.Left) == binaryOperatorExpression.Operator)
                    {
                        ParenthesizeIfRequired(binaryOperatorExpression.Left, precedence);
                    }
                    else
                    {
                        ParenthesizeIfRequired(binaryOperatorExpression.Left, boostTo);
                    }
                    ParenthesizeIfRequired(binaryOperatorExpression.Right, boostTo);
                }
                else
                {
                    // all other binary operators are left-associative
                    ParenthesizeIfRequired(binaryOperatorExpression.Left, precedence);
                    ParenthesizeIfRequired(binaryOperatorExpression.Right, precedence + 1);
                }
            }
            base.VisitBinaryOperatorExpression(binaryOperatorExpression);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Computes whether matching two media types produced a better match than the previously selected one.
        /// </summary>
        /// <param name="selectedTypeIsAcceptable">Whether the currently selected type is acceptable to the client.</param>
        /// <param name="matchingTypeNameParts">The number of matched type name parts during type matching.</param>
        /// <param name="selectedMatchingTypeNameParts">The number of matched type name parts for the currently selected type.</param>
        /// <param name="matchingParameters">The number of matched parameters during type matching.</param>
        /// <param name="selectedMatchingParameters">The number of matched parameters for the currently selected type.</param>
        /// <returns>
        /// The <see cref="PrecedenceLevel"/> indicating whether the most recent match has higher precedence,
        /// the same precedence or lower precedence than the currently selected one.
        /// </returns>
        private static PrecedenceLevel ComputePrecedence(
            bool selectedTypeIsAcceptable,
            int matchingTypeNameParts,
            int selectedMatchingTypeNameParts,
            int matchingParameters,
            int selectedMatchingParameters)
        {
            PrecedenceLevel precedence = PrecedenceLevel.Lower;

            if (!selectedTypeIsAcceptable)
            {
                // the currently selected type is not acceptable to the client; this one matches the type
                // and thus is considered having higher precedence (although we might determine below that this type is
                // also not acceptable to the client due to a 0 quality value).
                precedence = PrecedenceLevel.Higher;
            }
            else if (matchingTypeNameParts > selectedMatchingTypeNameParts)
            {
                // the current type matches more type name parts: choose it.
                precedence = PrecedenceLevel.Higher;
            }
            else if (matchingTypeNameParts == selectedMatchingTypeNameParts)
            {
                // for exact type/subtype matches we check whether both types have no parameters;
                // if that is the case this match is more specific than a previous one (where the
                // supported type might have had parameters).
                // NOTE: only do so for exact type/subtype matches; if the media type specifies a
                //       range ('*') we assume all parameters are supported.
                if (matchingTypeNameParts > 1 && matchingParameters == -1)
                {
                    // the current type perfectly matches the parameters of the
                    // acceptable type (both have no parameters)
                    precedence = PrecedenceLevel.Higher;
                }

                // Now check the parameters and see whether we find a more specific match.
                if (matchingParameters > selectedMatchingParameters)
                {
                    precedence = PrecedenceLevel.Higher;
                }
                else if (matchingParameters == selectedMatchingParameters)
                {
                    precedence = PrecedenceLevel.Same;
                }
            }

            return(precedence);
        }
Exemplo n.º 5
0
        private IValueNode <TwisterPrimitive> Evaluate(PrecedenceLevel precedence = PrecedenceLevel.LogOr)
        {
            var nextPrecedence = (PrecedenceLevel)((int)precedence - 1);
            var left           = EvaluateNext(precedence, nextPrecedence);

            var nextOperator = (_matcher.Peek as IValueToken <Operator>)?.Value;

            while (nextOperator.HasValue && IsOperatorInPrecedence(nextOperator.Value, precedence))
            {
                var op = _matcher.MatchAndGet <IValueToken <Operator> >().Value;

                var right = precedence <= PrecedenceLevel.Multiplicative
                    ? EvaluateUnary()
                    : Evaluate(nextPrecedence);

                left         = new BinaryExpressionNode(left, right, op);
                nextOperator = (_matcher.Peek as IValueToken <Operator>)?.Value;
            }

            return(left);
        }
Exemplo n.º 6
0
        private bool IsOperatorInPrecedence(Operator op, PrecedenceLevel precedence)
        {
            var isPrecedenceOperator = false;

            switch (precedence)
            {
            case PrecedenceLevel.Unary:
                isPrecedenceOperator |= op.IsUnaryArithmeticOperator();
                break;

            case PrecedenceLevel.Multiplicative:
                switch (op)
                {
                case Operator.Multiplication:
                case Operator.ForwardSlash:
                case Operator.Modulo:
                    isPrecedenceOperator = true;
                    break;
                }
                break;

            case PrecedenceLevel.Addition:
                switch (op)
                {
                case Operator.Plus:
                case Operator.Minus:
                    isPrecedenceOperator = true;
                    break;
                }
                break;

            case PrecedenceLevel.Shift:
                switch (op)
                {
                case Operator.LeftShift:
                case Operator.RightShift:
                    isPrecedenceOperator = true;
                    break;
                }
                break;

            case PrecedenceLevel.Relational:
                switch (op)
                {
                case Operator.LogGreater:
                case Operator.LogGreaterEqual:
                case Operator.LogLess:
                case Operator.LogLessEqual:
                    isPrecedenceOperator = true;
                    break;
                }
                break;

            case PrecedenceLevel.Equality:
                switch (op)
                {
                case Operator.LogEqual:
                case Operator.LogNotEqual:
                    isPrecedenceOperator = true;
                    break;
                }
                break;

            case PrecedenceLevel.BitAnd:
                switch (op)
                {
                case Operator.BitAnd:
                    isPrecedenceOperator = true;
                    break;
                }
                break;

            case PrecedenceLevel.BitExor:
                switch (op)
                {
                case Operator.BitExOr:
                    isPrecedenceOperator = true;
                    break;
                }
                break;

            case PrecedenceLevel.BitOr:
                switch (op)
                {
                case Operator.BitOr:
                    isPrecedenceOperator = true;
                    break;
                }
                break;

            case PrecedenceLevel.LogAnd:
                switch (op)
                {
                case Operator.LogAnd:
                    isPrecedenceOperator = true;
                    break;
                }
                break;

            case PrecedenceLevel.LogOr:
                switch (op)
                {
                case Operator.LogOr:
                    isPrecedenceOperator = true;
                    break;
                }
                break;

            default:
                throw new UnexpectedTokenException("Unexpected arithmetic operator")
                      {
                          UnexpectedToken = _matcher.Current
                      };
            }

            return(isPrecedenceOperator);
        }
Exemplo n.º 7
0
 private IValueNode <TwisterPrimitive> EvaluateNext(PrecedenceLevel precedence, PrecedenceLevel nextPrecedence) =>
 precedence <= PrecedenceLevel.Multiplicative
         ? EvaluateUnary()
         : Evaluate(nextPrecedence);
Exemplo n.º 8
0
        /// <summary>
        /// Matches the supported media types against the list of acceptable media types specified in the Accept header of the request. Matching follows the
        /// rules for media type matching as described in RFC 2616.
        /// </summary>
        /// <param name="acceptableTypes">The set of acceptable media types specified in the Accept header of the request.</param>
        /// <param name="supportedMediaTypes">The set of supported media types (sorted in descending precedence order).</param>
        /// <param name="format">The <see cref="ODataFormat"/> for the selected media type.</param>
        /// <returns>The media type that best matches the acceptable media types.</returns>
        private static MediaType MatchMediaTypes(IList <MediaType> acceptableTypes, MediaTypeWithFormat[] supportedMediaTypes, out ODataFormat format)
        {
            Debug.Assert(supportedMediaTypes != null, "supportedMediaTypes != null");

            MediaTypeWithFormat selectedContentType = null;
            int  selectedMatchingTypeNameParts      = -1;
            int  selectedMatchingParameters         = -2;// -2 is an invalid value; GetMatchingParameters returns values >= -1
            int  selectedQualityValue    = 0;
            int  selectedPreferenceIndex = Int32.MaxValue;
            bool selectedAcceptable      = false;

            if (acceptableTypes != null)
            {
                foreach (MediaType acceptableType in acceptableTypes)
                {
                    for (int i = 0; i < supportedMediaTypes.Length; i++)
                    {
                        MediaTypeWithFormat supportedType = supportedMediaTypes[i];

                        // match the type name parts and parameters of the media type
                        int matchingParameters, matchingQualityValue, acceptableTypeParameterCount;
                        int matchingTypeNameParts = acceptableType.GetMatchingParts(supportedType.MediaType, out matchingParameters, out matchingQualityValue, out acceptableTypeParameterCount);

                        if (!IsValidCandidate(matchingTypeNameParts, matchingParameters, acceptableTypeParameterCount))
                        {
                            continue;
                        }

                        // only continue processing the type if it is acceptable or we don't have
                        // an acceptable type yet.
                        bool matchingAcceptable = matchingQualityValue != 0;
                        if (!matchingAcceptable && selectedAcceptable)
                        {
                            continue;
                        }

                        PrecedenceLevel precedence = ComputePrecedence(selectedAcceptable, matchingTypeNameParts, selectedMatchingTypeNameParts, matchingParameters, selectedMatchingParameters);
                        switch (precedence)
                        {
                        case PrecedenceLevel.Higher:
                        {
                            // A more specific type wins.
                            selectedContentType           = supportedType;
                            selectedMatchingTypeNameParts = matchingTypeNameParts;
                            selectedMatchingParameters    = matchingParameters;
                            selectedQualityValue          = matchingQualityValue;
                            selectedPreferenceIndex       = i;
                            selectedAcceptable            = matchingAcceptable;
                        }

                        break;

                        case PrecedenceLevel.Same:
                        {
                            // A type with a higher q-value wins.
                            if (matchingQualityValue > selectedQualityValue)
                            {
                                selectedContentType     = supportedType;
                                selectedQualityValue    = matchingQualityValue;
                                selectedPreferenceIndex = i;
                                selectedAcceptable      = selectedQualityValue != 0;
                            }
                            else if (matchingQualityValue == selectedQualityValue)
                            {
                                // A type that is earlier in the supportedMediaTypes array wins.
                                if (i < selectedPreferenceIndex)
                                {
                                    selectedContentType     = supportedType;
                                    selectedPreferenceIndex = i;
                                }
                            }
                        }

                        break;

                        case PrecedenceLevel.Lower:
                            continue;

                        default:
                            throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataUtils_MatchMediaTypes_UnreachableCodePath));
                        }
                    }
                }
            }

            if (acceptableTypes == null || acceptableTypes.Count == 0)
            {
                // if not acceptable types are specified it means that all types are supported;
                // take the first supported type (as they are oredered by priority/precedence)
                selectedContentType = supportedMediaTypes[0];
            }
            else if (!selectedAcceptable)
            {
                format = ODataFormat.Default;
                return(null);
            }

            format = selectedContentType.Format;
            return(selectedContentType.MediaType);
        }