protected BinaryOperatorExpression(IExpression leftOprand, IExpression rightOprand,
                                    ExpressionPrecedence precedence, bool leftCombine)
 {
     this.LeftOprand  = leftOprand;
     this.RightOprand = rightOprand;
     this.Precedence  = precedence;
     this.LeftCombine = leftCombine;
 }
Пример #2
0
 public UnaryOperatorExpression(IExpression operand, ExpressionPrecedence precedence)
 {
     if (operand == null)
     {
         throw new ArgumentNullException("operand");
     }
     this.Operand    = operand;
     this.Precedence = precedence;
 }
Пример #3
0
        /// <summary>
        /// Reads a conditional logical expression.
        /// </summary>
        /// <param name="parentProxy">Represents the parent item.</param>
        /// <param name="leftHandSide">The expression on the left hand side of the operator.</param>
        /// <param name="previousPrecedence">The precedence of the expression just before this one.</param>
        /// <returns>Returns the expression.</returns>
        private ConditionalLogicalExpression GetConditionalPreprocessorAndOrExpression(
            CodeUnitProxy parentProxy, Expression leftHandSide, ExpressionPrecedence previousPrecedence)
        {
            Param.AssertNotNull(parentProxy, "parentProxy");
            Param.AssertNotNull(leftHandSide, "leftHandSide");
            Param.Ignore(previousPrecedence);

            ConditionalLogicalExpression expression = null;

            this.AdvanceToNextConditionalDirectiveCodeSymbol(parentProxy);
            var expressionProxy = new CodeUnitProxy(this.document);

            // Create the operator symbol.
            OperatorSymbolToken operatorToken = this.PeekOperatorSymbolToken();

            // Check the precedence of the operators to make sure we can gather this statement now.
            ExpressionPrecedence precedence = GetOperatorPrecedence(operatorToken.SymbolType);

            if (CheckPrecedence(previousPrecedence, precedence))
            {
                // Add the operator token to the document and advance the symbol manager up to it.
                this.symbols.Advance();
                expressionProxy.Children.Add(operatorToken);

                // Get the expression on the right-hand side of the operator.
                Expression rightHandSide = this.GetNextConditionalPreprocessorExpression(this.document, expressionProxy, precedence);
                if (rightHandSide == null)
                {
                    throw new SyntaxException(this.document, operatorToken.LineNumber);
                }

                // Get the expression operator type.
                switch (operatorToken.SymbolType)
                {
                case OperatorType.ConditionalAnd:
                    expression = new ConditionalAndExpression(expressionProxy, leftHandSide, rightHandSide);
                    break;

                case OperatorType.ConditionalOr:
                    expression = new ConditionalOrExpression(expressionProxy, leftHandSide, rightHandSide);
                    break;

                default:
                    throw new SyntaxException(this.document, operatorToken.LineNumber);
                }

                parentProxy.Children.Add(expression);
            }

            return(expression);
        }
 /// <summary>
 /// Determines the operator precedence of the token.
 /// </summary>
 /// <param name="value"></param>
 private void DeterminePrecedence(string value)
 {
     if (value.Equals("+", StringComparison.InvariantCultureIgnoreCase))
     {
         _precedence = ExpressionPrecedence.Add;
     }
     else if (value.Equals("-", StringComparison.InvariantCultureIgnoreCase))
     {
         _precedence = ExpressionPrecedence.Subtract;
     }
     else if (value.Equals("*", StringComparison.InvariantCultureIgnoreCase))
     {
         _precedence = ExpressionPrecedence.MultiplyOrDivide;
     }
     else if (value.Equals("/", StringComparison.InvariantCultureIgnoreCase))
     {
         _precedence = ExpressionPrecedence.MultiplyOrDivide;
     }
 }
Пример #5
0
        /// <summary>
        /// Determine the actual operation precedence for this operation.
        /// </summary>
        /// <param name="operation"></param>
        /// <returns></returns>
        private static ExpressionPrecedence DeterminePrecedence(Token operation)
        {
            ExpressionPrecedence precedence = ExpressionPrecedence.Null;

            if (operation.ToString().Equals("+", StringComparison.InvariantCultureIgnoreCase))
            {
                precedence = ExpressionPrecedence.Add;
            }
            else if (operation.ToString().Equals("-", StringComparison.InvariantCultureIgnoreCase))
            {
                precedence = ExpressionPrecedence.Subtract;
            }
            else if (operation.ToString().Equals("*", StringComparison.InvariantCultureIgnoreCase))
            {
                precedence = ExpressionPrecedence.MultiplyOrDivide;
            }
            else if (operation.ToString().Equals("/", StringComparison.InvariantCultureIgnoreCase))
            {
                precedence = ExpressionPrecedence.MultiplyOrDivide;
            }

            return(precedence);
        }
 protected ArithmeticBinaryOperatorExpression(IExpression leftOprand, IExpression rightOprand,
                                              ExpressionPrecedence precedence)
     : base(leftOprand, rightOprand, precedence)
 {
 }
        /// <summary>
        /// Given an expression, reads further to see if it is actually a sub-expression within a larger expression.
        /// </summary>
        /// <param name="sourceCode">
        /// The source code.
        /// </param>
        /// <param name="parentReference">
        /// The parent code part.
        /// </param>
        /// <param name="leftSide">
        /// The known expression which might have an extension.
        /// </param>
        /// <param name="previousPrecedence">
        /// The precedence of the expression just before this one.
        /// </param>
        /// <returns>
        /// Returns the expression.
        /// </returns>
        private Expression GetConditionalPreprocessorExpressionExtension(
            SourceCode sourceCode, Reference<ICodePart> parentReference, Expression leftSide, ExpressionPrecedence previousPrecedence)
        {
            Param.AssertNotNull(sourceCode, "sourceCode");
            Param.AssertNotNull(parentReference, "parentReference");
            Param.AssertNotNull(leftSide, "leftSide");
            Param.Ignore(previousPrecedence);

            // The expression to return.
            Expression expression = null;

            // Move past whitespace.
            this.AdvanceToNextConditionalDirectiveCodeSymbol(parentReference);

            Symbol symbol = this.symbols.Peek(1);
            if (symbol != null)
            {
                // Check the type of the next symbol.
                if (symbol.SymbolType != SymbolType.CloseParenthesis)
                {
                    // Check whether this is an operator symbol.
                    OperatorType type;
                    OperatorCategory category;
                    if (GetOperatorType(symbol, out type, out category))
                    {
                        switch (type)
                        {
                            case OperatorType.ConditionalEquals:
                            case OperatorType.NotEquals:
                                expression = this.GetConditionalPreprocessorEqualityExpression(sourceCode, parentReference, leftSide, previousPrecedence);
                                break;

                            case OperatorType.ConditionalAnd:
                            case OperatorType.ConditionalOr:
                                expression = this.GetConditionalPreprocessorAndOrExpression(sourceCode, parentReference, leftSide, previousPrecedence);
                                break;
                        }
                    }
                }
            }

            return expression;
        }
        /// <summary>
        /// Reads a conditional logical expression.
        /// </summary>
        /// <param name="leftHandSide">The expression on the left hand side of the operator.</param>
        /// <param name="previousPrecedence">The precedence of the expression just before this one.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the expression.</returns>
        private ConditionalLogicalExpression GetConditionalLogicalExpression(
            Expression leftHandSide, ExpressionPrecedence previousPrecedence, bool unsafeCode)
        {
            Param.AssertNotNull(leftHandSide, "leftHandSide");
            Param.Ignore(previousPrecedence);
            Param.Ignore(unsafeCode);

            ConditionalLogicalExpression expression = null;

            // Read the details of the expression.
            OperatorSymbol operatorToken = this.PeekOperatorToken();
            Debug.Assert(operatorToken.Category == OperatorCategory.Logical, "Expected a logical operator");

            // Check the precedence of the operators to make sure we can gather this statement now.
            ExpressionPrecedence precedence = this.GetOperatorPrecedence(operatorToken.SymbolType);
            if (this.CheckPrecedence(previousPrecedence, precedence))
            {
                // Add the operator token to the document and advance the symbol manager up to it.
                this.symbols.Advance();
                this.tokens.Add(operatorToken);

                // Get the expression on the right-hand side of the operator.
                Expression rightHandSide = this.GetOperatorRightHandExpression(precedence, unsafeCode);

                // Create the partial token list for the expression.
                CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last);

                // Get the expression operator type.
                ConditionalLogicalExpression.Operator type;
                switch (operatorToken.SymbolType)
                {
                    case OperatorType.ConditionalAnd:
                        type = ConditionalLogicalExpression.Operator.And;
                        break;

                    case OperatorType.ConditionalOr:
                        type = ConditionalLogicalExpression.Operator.Or;
                        break;

                    default:
                        Debug.Fail("Unexpected operator type");
                        throw new InvalidOperationException();
                }

                // Create and return the expression.
                expression = new ConditionalLogicalExpression(partialTokens, type, leftHandSide, rightHandSide);
            }

            return expression;
        }
        private bool IsCastExpression(ExpressionPrecedence previousPrecedence, bool unsafeCode)
        {
            Param.Ignore(previousPrecedence);
            Param.Ignore(unsafeCode);

            bool cast = false;

            // The first symbol must be an opening parenthesis.
            int index = this.GetNextCodeSymbolIndex(1);
            if (index != -1)
            {
                Symbol symbol = this.symbols.Peek(index);
                if (symbol.SymbolType == SymbolType.OpenParenthesis)
                {
                    // The inner expression must have a type signature.
                    if (this.HasTypeSignature(index + 1, unsafeCode, out index))
                    {
                        if (index != -1)
                        {
                            symbol = this.symbols.Peek(index);
                            if (symbol.SymbolType == SymbolType.Other)
                            {
                                index = this.AdvanceToEndOfName(index);
                            }

                            // The next character must be a closing parenthesis or this is not a cast.
                            if (index != -1)
                            {
                                index = this.GetNextCodeSymbolIndex(index + 1);
                                if (index != -1)
                                {
                                    symbol = this.symbols.Peek(index);
                                    if (symbol.SymbolType == SymbolType.CloseParenthesis)
                                    {
                                        // This looks like it might be a cast, but a cast can only appear in front
                                        // of the following types of symbols.
                                        index = this.GetNextCodeSymbolIndex(index + 1);
                                        if (index != -1)
                                        {
                                            Symbol nextSymbol = this.symbols.Peek(index);
                                            SymbolType symbolType = nextSymbol.SymbolType;
                                            if (symbolType == SymbolType.Other)
                                            {
                                                // This could be an expression like:
                                                // from type in x where (type.IsClass) select type;
                                                if (previousPrecedence != ExpressionPrecedence.Query ||
                                                    (nextSymbol.Text != "where" &&
                                                     nextSymbol.Text != "select" &&
                                                     nextSymbol.Text != "group" &&
                                                     nextSymbol.Text != "into" &&
                                                     nextSymbol.Text != "orderby" &&
                                                     nextSymbol.Text != "join" &&
                                                     nextSymbol.Text != "let" &&
                                                     nextSymbol.Text != "equals" &&
                                                     nextSymbol.Text != "by" &&
                                                     nextSymbol.Text != "on"))
                                                {
                                                    cast = true;
                                                }
                                            }
                                            else if (symbolType == SymbolType.OpenParenthesis ||
                                                symbolType == SymbolType.Number ||
                                                symbolType == SymbolType.Tilde ||
                                                symbolType == SymbolType.Not ||
                                                symbolType == SymbolType.New ||
                                                symbolType == SymbolType.Sizeof ||
                                                symbolType == SymbolType.Typeof ||
                                                symbolType == SymbolType.Default ||
                                                symbolType == SymbolType.Checked ||
                                                symbolType == SymbolType.Unchecked ||
                                                symbolType == SymbolType.This ||
                                                symbolType == SymbolType.Base ||
                                                symbolType == SymbolType.Null ||
                                                symbolType == SymbolType.True ||
                                                symbolType == SymbolType.False ||
                                                symbolType == SymbolType.Plus ||
                                                symbolType == SymbolType.Minus ||
                                                symbolType == SymbolType.String ||
                                                symbolType == SymbolType.Delegate)
                                            {
                                                cast = true;
                                            }
                                            else if (symbolType == SymbolType.Increment ||
                                                symbolType == SymbolType.Decrement)
                                            {
                                                // This could be a cast if the symbol following the cast is an "other" or an opening parenthesis. For instance:
                                                // object x = (object)++y;
                                                // object x = (object)++(y);
                                                // object x = (object)++this.y;
                                                // However this is not a cast when:
                                                // object x = (x)++;
                                                int next = this.GetNextCodeSymbolIndex(index + 1);
                                                if (next != -1)
                                                {
                                                    SymbolType nextSymbolType = this.symbols.Peek(next).SymbolType;
                                                    if (nextSymbolType == SymbolType.Other ||
                                                        nextSymbolType == SymbolType.This ||
                                                        nextSymbolType == SymbolType.Base ||
                                                        nextSymbolType == SymbolType.OpenParenthesis)
                                                    {
                                                        cast = true;
                                                    }
                                                }
                                            }
                                            else if (symbolType == SymbolType.LogicalAnd && unsafeCode)
                                            {
                                                // For example: (IntPtr*)&rc.left
                                                cast = true;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return cast;
        }
        /// <summary>
        /// Reads and returns the right-hand expression of an operator expression.
        /// </summary>
        /// <param name="precedence">The precendence of this operator expression.</param>
        /// <param name="parentReference">The parent code unit.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the expression.</returns>
        private Expression GetOperatorRightHandExpression(ExpressionPrecedence precedence, Reference<ICodePart> parentReference, bool unsafeCode)
        {
            Param.AssertNotNull(precedence, "precedence");
            Param.AssertNotNull(parentReference, "parentReference");
            Param.Ignore(unsafeCode);

            // Get the right hand expression.
            Expression rightHandSide = this.GetNextExpression(precedence, parentReference, unsafeCode);
            if (rightHandSide == null)
            {
                throw this.CreateSyntaxException();
            }

            // Make sure the right hand side has at least one token.
            Debug.Assert(rightHandSide.Tokens.First != null, "The right-hand side should not be empty.");

            return rightHandSide;
        }
        /// <summary>
        /// Reads the next expression from the file and returns it.
        /// </summary>
        /// <param name="previousPrecedence">The precedence of the expression just before this one.</param>
        /// <param name="parentReference">Reference to the parent code part.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the expression.</returns>
        private Expression GetNextExpression(ExpressionPrecedence previousPrecedence, Reference<ICodePart> parentReference, bool unsafeCode)
        {
            Param.Ignore(previousPrecedence);
            Param.AssertNotNull(parentReference, "parentReference");
            Param.Ignore(unsafeCode);

            return this.GetNextExpression(previousPrecedence, parentReference, unsafeCode, false, false);
        }
 protected BinaryOperatorExpression(IExpression leftOprand, IExpression rightOprand,
                                    ExpressionPrecedence precedence)
     : this(leftOprand, rightOprand, precedence, true)
 {
 }
Пример #13
0
 /// <summary>
 /// Creates an instance of FunctionToken.
 /// </summary>
 /// <param name="other"></param>
 protected FunctionToken(Token other)
     : base(other)
 {
     _precedence = ExpressionPrecedence.Function;
 }
Пример #14
0
 /// <summary>
 /// Creates an instance of FunctionToken.
 /// </summary>
 /// <param name="value"></param>
 protected FunctionToken(string value)
     : base(value)
 {
     _precedence = ExpressionPrecedence.Function;
 }
        private Expression GetExpressionExtension(
            Expression leftSide, 
            ExpressionPrecedence previousPrecedence, 
            Reference<ICodePart> parentReference,
            bool unsafeCode, 
            bool typeExpression, 
            bool allowVariableDeclaration)
        {
            Param.AssertNotNull(leftSide, "leftSide");
            Param.Ignore(previousPrecedence);
            Param.AssertNotNull(parentReference, "parentReference");
            Param.Ignore(unsafeCode);
            Param.Ignore(typeExpression);
            Param.Ignore(allowVariableDeclaration);

            // The expression to return.
            Expression expression = null;

            Symbol symbol = this.GetNextSymbol(parentReference);

            if (typeExpression)
            {
                // A type expression can only be extended by a member access expression.
                if (symbol.SymbolType == SymbolType.Dot || symbol.SymbolType == SymbolType.QualifiedAlias)
                {
                    expression = this.GetMemberAccessExpression(leftSide, previousPrecedence, unsafeCode);
                }
            }
            else
            {
                // Check the type of the next symbol.
                switch (symbol.SymbolType)
                {
                    case SymbolType.CloseParenthesis:
                    case SymbolType.CloseSquareBracket:
                    case SymbolType.Semicolon:
                    case SymbolType.Comma:
                        break;

                    case SymbolType.Dot:
                    case SymbolType.QualifiedAlias:
                    case SymbolType.Pointer:
                        expression = this.GetMemberAccessExpression(leftSide, previousPrecedence, unsafeCode);
                        break;

                    case SymbolType.Other:
                        // This can only be a variable declaration expression if the left
                        // side expression is a simple Literal or a MemberAccess which represents the type.
                        if (allowVariableDeclaration &&
                            (leftSide.ExpressionType == ExpressionType.Literal || leftSide.ExpressionType == ExpressionType.MemberAccess))
                        {
                            expression = this.GetVariableDeclarationExpression(leftSide, previousPrecedence, unsafeCode);
                        }

                        break;

                    case SymbolType.OpenParenthesis:
                        expression = this.GetMethodInvocationExpression(leftSide, previousPrecedence, unsafeCode);
                        break;

                    case SymbolType.OpenSquareBracket:
                        expression = this.GetArrayAccessExpression(leftSide, previousPrecedence, unsafeCode);
                        break;

                    case SymbolType.As:
                        expression = this.GetAsExpression(leftSide, previousPrecedence, parentReference, unsafeCode);
                        break;

                    case SymbolType.Is:
                        expression = this.GetIsExpression(leftSide, previousPrecedence, parentReference, unsafeCode);
                        break;

                    case SymbolType.Increment:
                        expression = this.GetPrimaryIncrementExpression(leftSide, previousPrecedence);
                        break;

                    case SymbolType.Decrement:
                        expression = this.GetPrimaryDecrementExpression(leftSide, previousPrecedence);
                        break;

                    default:
                        // Check whether this is an operator symbol.
                        OperatorType type;
                        OperatorCategory category;
                        if (GetOperatorType(symbol, out type, out category))
                        {
                            switch (category)
                            {
                                case OperatorCategory.Conditional:
                                    // The question mark must come before the colon.
                                    if (type == OperatorType.ConditionalQuestionMark)
                                    {
                                        expression = this.GetConditionalExpression(leftSide, previousPrecedence, unsafeCode);
                                    }

                                    break;

                                case OperatorCategory.Arithmetic:
                                    if (unsafeCode && type == OperatorType.Multiplication)
                                    {
                                        if (this.IsDereferenceExpression(leftSide))
                                        {
                                            expression = this.GetUnsafeTypeExpression(leftSide, previousPrecedence, parentReference);
                                        }
                                        else
                                        {
                                            expression = this.GetArithmeticExpression(leftSide, previousPrecedence, parentReference, unsafeCode);
                                        }
                                    }
                                    else
                                    {
                                        expression = this.GetArithmeticExpression(leftSide, previousPrecedence, parentReference, unsafeCode);
                                    }

                                    break;

                                case OperatorCategory.Shift:
                                    expression = this.GetArithmeticExpression(leftSide, previousPrecedence, parentReference, unsafeCode);
                                    break;

                                case OperatorCategory.Assignment:
                                    expression = this.GetAssignmentExpression(leftSide, previousPrecedence, parentReference, unsafeCode);
                                    break;

                                case OperatorCategory.Relational:
                                    // If this is a greater-than symbol, make sure it is not really a right-shift.
                                    if (type == OperatorType.GreaterThan)
                                    {
                                        // If the very next symbol is a greater-than or equals, then this is really a right-shift.
                                        Symbol next = this.symbols.Peek(2);
                                        if (next != null)
                                        {
                                            if (next.SymbolType == SymbolType.GreaterThanOrEquals)
                                            {
                                                // This is a right-shift-equals.
                                                this.symbols.Combine(1, 2, ">>=", SymbolType.RightShiftEquals);
                                                goto case OperatorCategory.Assignment;
                                            }
                                            else if (next.SymbolType == SymbolType.GreaterThan)
                                            {
                                                // This is a right-shift.
                                                this.symbols.Combine(1, 2, ">>", SymbolType.RightShift);
                                                goto case OperatorCategory.Shift;
                                            }
                                        }
                                    }

                                    expression = this.GetRelationalExpression(leftSide, previousPrecedence, parentReference, unsafeCode);
                                    break;

                                case OperatorCategory.Logical:
                                    switch (type)
                                    {
                                        case OperatorType.LogicalAnd:
                                        case OperatorType.LogicalOr:
                                        case OperatorType.LogicalXor:
                                            expression = this.GetLogicalExpression(leftSide, previousPrecedence, parentReference, unsafeCode);
                                            break;

                                        case OperatorType.ConditionalAnd:
                                        case OperatorType.ConditionalOr:
                                            expression = this.GetConditionalLogicalExpression(leftSide, previousPrecedence, parentReference, unsafeCode);
                                            break;

                                        case OperatorType.NullCoalescingSymbol:
                                            expression = this.GetNullCoalescingExpression(leftSide, previousPrecedence, parentReference, unsafeCode);
                                            break;

                                        default:
                                            break;
                                    }

                                    break;
                            }
                        }

                        break;
                }
            }

            return expression;
        }
        /// <summary>
        /// Reads a member access expression.
        /// </summary>
        /// <param name="leftSide">The left side of the expression.</param>
        /// <param name="previousPrecedence">The precedence of the previous expression.</param>
        /// <param name="unsafeCode">Indicates whether the code is marked as unsafe.</param>
        /// <returns>Returns the expression.</returns>
        private MemberAccessExpression GetMemberAccessExpression(
            Expression leftSide, ExpressionPrecedence previousPrecedence, bool unsafeCode)
        {
            Param.AssertNotNull(leftSide, "leftSide");
            Param.Ignore(previousPrecedence);
            Param.Ignore(unsafeCode);

            MemberAccessExpression expression = null;

            OperatorType operatorType;
            MemberAccessExpression.Operator expressionOperatorType;
            ExpressionPrecedence precedence;

            var expressionReference = new Reference<ICodePart>();

            // The next symbol must one of the member access types.
            Symbol symbol = this.GetNextSymbol(expressionReference);

            if (symbol.SymbolType == SymbolType.Dot)
            {
                operatorType = OperatorType.MemberAccess;
                expressionOperatorType = MemberAccessExpression.Operator.Dot;
                precedence = ExpressionPrecedence.Primary;
            }
            else if (symbol.SymbolType == SymbolType.Pointer)
            {
                operatorType = OperatorType.Pointer;
                expressionOperatorType = MemberAccessExpression.Operator.Pointer;
                precedence = ExpressionPrecedence.Primary;
            }
            else if (symbol.SymbolType == SymbolType.QualifiedAlias)
            {
                operatorType = OperatorType.QualifiedAlias;
                expressionOperatorType = MemberAccessExpression.Operator.QualifiedAlias;
                precedence = ExpressionPrecedence.Global;
            }
            else
            {
                Debug.Fail("Unexpected operator type");
                throw new InvalidOperationException();
            }

            // Check the precedence. A member access has primary precedence.
            if (CheckPrecedence(previousPrecedence, precedence))
            {
                // Add this to the document.
                this.tokens.Add(this.GetOperatorToken(operatorType, expressionReference));

                // Get the member being accessed. This must be a literal.
                LiteralExpression member = this.GetLiteralExpression(expressionReference, unsafeCode);
                if (member == null)
                {
                    throw this.CreateSyntaxException();
                }

                // Create the token list.
                CsTokenList partialTokens = new CsTokenList(this.tokens, leftSide.Tokens.First, this.tokens.Last);

                // Create the expression.
                expression = new MemberAccessExpression(partialTokens, expressionOperatorType, leftSide, member);
                expressionReference.Target = expression;
            }

            return expression;
        }
Пример #17
0
 /// <summary>
 /// Creates an instance of Expression.
 /// </summary>
 /// <param name="precedence"></param>
 /// <param name="operation"></param>
 /// <param name="operands"></param>
 protected Expression(ExpressionPrecedence precedence, Token operation, IList <Expression> operands)
 {
     _precedence = precedence;
     _operation  = operation;
     _operands   = operands;
 }
        /// <summary>
        /// Reads a null coalescing expression.
        /// </summary>
        /// <param name="leftHandSide">The expression on the left hand side of the operator.</param>
        /// <param name="previousPrecedence">The precedence of the expression just before this one.</param>
        /// <param name="parentReference">The parent code unit.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the expression.</returns>
        private NullCoalescingExpression GetNullCoalescingExpression(
            Expression leftHandSide, ExpressionPrecedence previousPrecedence, Reference<ICodePart> parentReference, bool unsafeCode)
        {
            Param.AssertNotNull(leftHandSide, "leftHandSide");
            Param.Ignore(previousPrecedence);
            Param.AssertNotNull(parentReference, "parentReference");
            Param.Ignore(unsafeCode);

            NullCoalescingExpression expression = null;
            var expressionReference = new Reference<ICodePart>();

            // Read the details of the expression.
            OperatorSymbol operatorToken = this.PeekOperatorToken(parentReference, expressionReference);
            Debug.Assert(operatorToken.SymbolType == OperatorType.NullCoalescingSymbol, "Expected a null-coalescing symbol");

            // Check the precedence of the operators to make sure we can gather this statement now.
            ExpressionPrecedence precedence = GetOperatorPrecedence(operatorToken.SymbolType);
            if (CheckPrecedence(previousPrecedence, precedence))
            {
                // Add the operator token to the document and advance the symbol manager up to it.
                this.symbols.Advance();
                this.tokens.Add(operatorToken);

                // Get the expression on the right-hand side of the operator.
                Expression rightHandSide = this.GetOperatorRightHandExpression(precedence, expressionReference, unsafeCode);

                // Create the partial token list for the expression.
                CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last);

                // Create and return the expression.
                expression = new NullCoalescingExpression(partialTokens, leftHandSide, rightHandSide);
                expressionReference.Target = expression;
            }

            return expression;
        }
Пример #19
0
        /// <summary>
        /// Reads a relational expression.
        /// </summary>
        /// <param name="sourceCode">
        /// The file containing the expression.
        /// </param>
        /// <param name="parentReference">
        /// The parent code unit.
        /// </param>
        /// <param name="leftHandSide">
        /// The expression on the left hand side of the operator.
        /// </param>
        /// <param name="previousPrecedence">
        /// The precedence of the expression just before this one.
        /// </param>
        /// <returns>
        /// Returns the expression.
        /// </returns>
        private RelationalExpression GetConditionalPreprocessorEqualityExpression(
            SourceCode sourceCode, Reference <ICodePart> parentReference, Expression leftHandSide, ExpressionPrecedence previousPrecedence)
        {
            Param.AssertNotNull(sourceCode, "sourceCode");
            Param.AssertNotNull(parentReference, "parentReference");
            Param.AssertNotNull(leftHandSide, "leftHandSide");
            Param.Ignore(previousPrecedence);

            RelationalExpression expression = null;

            this.AdvanceToNextConditionalDirectiveCodeSymbol(parentReference);
            Symbol firstSymbol = this.symbols.Peek(1);

            if (firstSymbol == null)
            {
                throw new SyntaxException(sourceCode, firstSymbol.LineNumber);
            }

            Reference <ICodePart> expressionReference = new Reference <ICodePart>();

            // Create the operator symbol.
            OperatorType     type;
            OperatorCategory category;

            GetOperatorType(firstSymbol, out type, out category);
            OperatorSymbol operatorToken = new OperatorSymbol(firstSymbol.Text, category, type, firstSymbol.Location, expressionReference, this.symbols.Generated);

            // Check the precedence of the operators to make sure we can gather this statement now.
            ExpressionPrecedence precedence = GetOperatorPrecedence(operatorToken.SymbolType);

            if (CheckPrecedence(previousPrecedence, precedence))
            {
                // Add the operator token to the document and advance the symbol manager up to it.
                this.symbols.Advance();
                this.tokens.Add(operatorToken);

                // Get the expression on the right-hand side of the operator.
                Expression rightHandSide = this.GetNextConditionalPreprocessorExpression(sourceCode, precedence);
                if (rightHandSide == null)
                {
                    throw new SyntaxException(sourceCode, operatorToken.LineNumber);
                }

                // Create the partial token list for the expression.
                CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last);

                // Get the expression operator type.
                RelationalExpression.Operator relationalType;
                switch (operatorToken.SymbolType)
                {
                case OperatorType.ConditionalEquals:
                    relationalType = RelationalExpression.Operator.EqualTo;
                    break;

                case OperatorType.NotEquals:
                    relationalType = RelationalExpression.Operator.NotEqualTo;
                    break;

                default:
                    throw new SyntaxException(sourceCode, operatorToken.LineNumber);
                }

                // Create and return the expression.
                expression = new RelationalExpression(partialTokens, relationalType, leftHandSide, rightHandSide);
                expressionReference.Target = expression;
            }

            return(expression);
        }
        /// <summary>
        /// Reads an unsafe type expression.
        /// </summary>
        /// <param name="type">The type expression.</param>
        /// <param name="previousPrecedence">The precedence of the previous expression.</param>
        /// <param name="parentReference">The parent code unit.</param>
        /// <returns>Returns the expression.</returns>
        private UnsafeAccessExpression GetUnsafeTypeExpression(Expression type, ExpressionPrecedence previousPrecedence, Reference<ICodePart> parentReference)
        {
            Param.Ignore(type);
            Param.AssertNotNull(previousPrecedence, "previousPrecedence");
            Param.AssertNotNull(parentReference, "parentReference");

            UnsafeAccessExpression expression = null;

            if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.Unary))
            {
                // Get the operator symbol.
                Symbol symbol = this.GetNextSymbol(parentReference);

                var expressionReference = new Reference<ICodePart>();

                OperatorType operatorType;
                UnsafeAccessExpression.Operator unsafeOperatorType;
                if (symbol.SymbolType == SymbolType.LogicalAnd)
                {
                    operatorType = OperatorType.AddressOf;
                    unsafeOperatorType = UnsafeAccessExpression.Operator.AddressOf;
                }
                else if (symbol.SymbolType == SymbolType.Multiplication)
                {
                    operatorType = OperatorType.Dereference;
                    unsafeOperatorType = UnsafeAccessExpression.Operator.Dereference;
                }
                else
                {
                    Debug.Fail("Unexpected operator type.");
                    throw new InvalidOperationException();
                }

                // Create a token for the operator symbol.
                this.symbols.Advance();
                OperatorSymbol token = new OperatorSymbol(
                    symbol.Text,
                    OperatorCategory.Reference,
                    operatorType,
                    symbol.Location,
                    expressionReference,
                    this.symbols.Generated);

                this.tokens.Add(token);

                // Create the partial token list for the expression.
                CsTokenList partialTokens = new CsTokenList(this.tokens, type.Tokens.First, this.tokens.Last);

                // Create and return the expression.
                expression = new UnsafeAccessExpression(partialTokens, unsafeOperatorType, type);
                expressionReference.Target = expression;
            }

            return expression;
        }
Пример #21
0
        /// <summary>
        /// Given an expression, reads further to see if it is actually a sub-expression within a larger expression.
        /// </summary>
        /// <param name="sourceCode">
        /// The source code.
        /// </param>
        /// <param name="parentReference">
        /// The parent code part.
        /// </param>
        /// <param name="leftSide">
        /// The known expression which might have an extension.
        /// </param>
        /// <param name="previousPrecedence">
        /// The precedence of the expression just before this one.
        /// </param>
        /// <returns>
        /// Returns the expression.
        /// </returns>
        private Expression GetConditionalPreprocessorExpressionExtension(
            SourceCode sourceCode, Reference <ICodePart> parentReference, Expression leftSide, ExpressionPrecedence previousPrecedence)
        {
            Param.AssertNotNull(sourceCode, "sourceCode");
            Param.AssertNotNull(parentReference, "parentReference");
            Param.AssertNotNull(leftSide, "leftSide");
            Param.Ignore(previousPrecedence);

            // The expression to return.
            Expression expression = null;

            // Move past whitespace.
            this.AdvanceToNextConditionalDirectiveCodeSymbol(parentReference);

            Symbol symbol = this.symbols.Peek(1);

            if (symbol != null)
            {
                // Check the type of the next symbol.
                if (symbol.SymbolType != SymbolType.CloseParenthesis)
                {
                    // Check whether this is an operator symbol.
                    OperatorType     type;
                    OperatorCategory category;
                    if (GetOperatorType(symbol, out type, out category))
                    {
                        switch (type)
                        {
                        case OperatorType.ConditionalEquals:
                        case OperatorType.NotEquals:
                            expression = this.GetConditionalPreprocessorEqualityExpression(sourceCode, parentReference, leftSide, previousPrecedence);
                            break;

                        case OperatorType.ConditionalAnd:
                        case OperatorType.ConditionalOr:
                            expression = this.GetConditionalPreprocessorAndOrExpression(sourceCode, parentReference, leftSide, previousPrecedence);
                            break;
                        }
                    }
                }
            }

            return(expression);
        }
        /// <summary>
        /// Reads an as expression.
        /// </summary>
        /// <param name="leftHandSide">The expression on the left hand side of the operator.</param>
        /// <param name="previousPrecedence">The precedence of the expression just before this one.</param>
        /// <param name="parentReference">The parent code unit.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the expression.</returns>
        private AsExpression GetAsExpression(
            Expression leftHandSide, ExpressionPrecedence previousPrecedence, Reference<ICodePart> parentReference, bool unsafeCode)
        {
            Param.AssertNotNull(leftHandSide, "leftHandSide");
            Param.Ignore(previousPrecedence);
            Param.AssertNotNull(parentReference, "parentReference");
            Param.Ignore(unsafeCode);

            AsExpression expression = null;

            // Check the previous precedence to see if we are allowed to gather up the as expression.
            if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.Relational))
            {
                var expressionReference = new Reference<ICodePart>();

                // Make sure the left hand side has at least one token.
                Debug.Assert(leftHandSide.Tokens.First != null, "The left hand side should not be empty");

                // Get the as symbol.
                this.tokens.Add(this.GetToken(CsTokenType.As, SymbolType.As, parentReference, expressionReference));

                // The next token must be the type.
                this.GetNextSymbol(SymbolType.Other, expressionReference);

                // Get the expression representing the type.
                LiteralExpression rightHandSide = this.GetTypeTokenExpression(expressionReference, unsafeCode, true);
                if (rightHandSide == null || rightHandSide.Tokens.First == null)
                {
                    throw this.CreateSyntaxException();
                }

                // Create the partial token list for the expression.
                CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last);

                // Create and return the expression.
                expression = new AsExpression(partialTokens, leftHandSide, rightHandSide);
                expressionReference.Target = expression;
            }

            return expression;
        }
Пример #23
0
        /// <summary>
        /// Reads the next expression from a conditional preprocessor directive.
        /// </summary>
        /// <param name="sourceCode">
        /// The source code.
        /// </param>
        /// <param name="previousPrecedence">
        /// The precedence of the expression just before this one.
        /// </param>
        /// <returns>
        /// Returns the expression.
        /// </returns>
        private Expression GetNextConditionalPreprocessorExpression(SourceCode sourceCode, ExpressionPrecedence previousPrecedence)
        {
            Param.AssertNotNull(sourceCode, "sourceCode");
            Param.Ignore(previousPrecedence);

            Reference <ICodePart> parentReference = new Reference <ICodePart>();

            // Move past comments and whitepace.
            this.AdvanceToNextConditionalDirectiveCodeSymbol(parentReference);

            // Saves the next expression.
            Expression expression = null;

            // Get the next symbol.
            Symbol symbol = this.symbols.Peek(1);

            if (symbol != null)
            {
                switch (symbol.SymbolType)
                {
                case SymbolType.Other:
                    expression = this.GetConditionalPreprocessorConstantExpression();
                    break;

                case SymbolType.Not:
                    expression = this.GetConditionalPreprocessorNotExpression(sourceCode, parentReference);
                    break;

                case SymbolType.OpenParenthesis:
                    expression = this.GetConditionalPreprocessorParenthesizedExpression(sourceCode, parentReference);
                    break;

                case SymbolType.False:
                    this.symbols.Advance();

                    Reference <ICodePart> falseExpressionReference = new Reference <ICodePart>();
                    CsToken        token     = new CsToken(symbol.Text, CsTokenType.False, symbol.Location, falseExpressionReference, this.symbols.Generated);
                    Node <CsToken> tokenNode = this.tokens.InsertLast(token);
                    expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode);
                    falseExpressionReference.Target = expression;
                    break;

                case SymbolType.True:
                    this.symbols.Advance();

                    Reference <ICodePart> trueExpressionReference = new Reference <ICodePart>();
                    token      = new CsToken(symbol.Text, CsTokenType.True, symbol.Location, trueExpressionReference, this.symbols.Generated);
                    tokenNode  = this.tokens.InsertLast(token);
                    expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode);
                    trueExpressionReference.Target = expression;
                    break;

                default:
                    throw new SyntaxException(sourceCode, symbol.LineNumber);
                }
            }

            // Gather up all extensions to this expression.
            while (expression != null)
            {
                Reference <ICodePart> expressionReference = new Reference <ICodePart>(expression);

                // Check if there is an extension to this expression.
                Expression extension = this.GetConditionalPreprocessorExpressionExtension(sourceCode, expressionReference, expression, previousPrecedence);
                if (extension != null)
                {
                    // The larger expression is what we want to return here.
                    expression = extension;
                }
                else
                {
                    // There are no more extensions.
                    break;
                }
            }

            // Return the expression.
            return(expression);
        }
        /// <summary>
        /// Reads an arithmetic expression.
        /// </summary>
        /// <param name="leftHandSide">The expression on the left hand side of the operator.</param>
        /// <param name="previousPrecedence">The precedence of the expression just before this one.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the expression.</returns>
        private ArithmeticExpression GetArithmeticExpression(
            Expression leftHandSide, ExpressionPrecedence previousPrecedence, bool unsafeCode)
        {
            Param.AssertNotNull(leftHandSide, "leftHandSide");
            Param.Ignore(previousPrecedence);
            Param.Ignore(unsafeCode);

            ArithmeticExpression expression = null;
            
            // Read the details of the expression.
            OperatorSymbol operatorToken = this.PeekOperatorToken();
            Debug.Assert(
                operatorToken.Category == OperatorCategory.Arithmetic || operatorToken.Category == OperatorCategory.Shift, 
                "Expected an arithmetic or shift operator");

            // Check the precedence of the operators to make sure we can gather this statement now.
            ExpressionPrecedence precedence = this.GetOperatorPrecedence(operatorToken.SymbolType);
            if (this.CheckPrecedence(previousPrecedence, precedence))
            {
                // Add the operator token to the document and advance the symbol manager up to it.
                this.symbols.Advance();
                this.tokens.Add(operatorToken);

                // Get the expression on the right-hand side of the operator.
                Expression rightHandSide = this.GetOperatorRightHandExpression(precedence, unsafeCode);

                // Create the partial token list for the expression.
                CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last);

                // Get the expression operator type.
                ArithmeticExpression.Operator type;
                switch (operatorToken.SymbolType)
                {
                    case OperatorType.Plus:
                        type = ArithmeticExpression.Operator.Addition;
                        break;

                    case OperatorType.Minus:
                        type = ArithmeticExpression.Operator.Subtraction;
                        break;

                    case OperatorType.Multiplication:
                        type = ArithmeticExpression.Operator.Multiplication;
                        break;

                    case OperatorType.Division:
                        type = ArithmeticExpression.Operator.Division;
                        break;

                    case OperatorType.Mod:
                        type = ArithmeticExpression.Operator.Mod;
                        break;

                    case OperatorType.LeftShift:
                        type = ArithmeticExpression.Operator.LeftShift;
                        break;

                    case OperatorType.RightShift:
                        type = ArithmeticExpression.Operator.RightShift;
                        break;

                    default:
                        Debug.Fail("Unexpected operator type");
                        throw new InvalidOperationException();
                }

                // Create and return the expression.
                expression = new ArithmeticExpression(partialTokens, type, leftHandSide, rightHandSide);
            }

            return expression;
        }
Пример #25
0
 public PolyadicOperatorExpression(ExpressionPrecedence precedence)
     : this(precedence, true)
 {
 }
        /// <summary>
        /// Reads a relational expression.
        /// </summary>
        /// <param name="sourceCode">
        /// The file containing the expression.
        /// </param>
        /// <param name="parentReference">
        /// The parent code unit.
        /// </param>
        /// <param name="leftHandSide">
        /// The expression on the left hand side of the operator.
        /// </param>
        /// <param name="previousPrecedence">
        /// The precedence of the expression just before this one.
        /// </param>
        /// <returns>
        /// Returns the expression.
        /// </returns>
        private RelationalExpression GetConditionalPreprocessorEqualityExpression(
            SourceCode sourceCode, Reference<ICodePart> parentReference, Expression leftHandSide, ExpressionPrecedence previousPrecedence)
        {
            Param.AssertNotNull(sourceCode, "sourceCode");
            Param.AssertNotNull(parentReference, "parentReference");
            Param.AssertNotNull(leftHandSide, "leftHandSide");
            Param.Ignore(previousPrecedence);

            RelationalExpression expression = null;

            this.AdvanceToNextConditionalDirectiveCodeSymbol(parentReference);
            Symbol firstSymbol = this.symbols.Peek(1);
            if (firstSymbol == null)
            {
                throw new SyntaxException(sourceCode, firstSymbol.LineNumber);
            }

            Reference<ICodePart> expressionReference = new Reference<ICodePart>();

            // Create the operator symbol.
            OperatorType type;
            OperatorCategory category;
            GetOperatorType(firstSymbol, out type, out category);
            OperatorSymbol operatorToken = new OperatorSymbol(firstSymbol.Text, category, type, firstSymbol.Location, expressionReference, this.symbols.Generated);

            // Check the precedence of the operators to make sure we can gather this statement now.
            ExpressionPrecedence precedence = GetOperatorPrecedence(operatorToken.SymbolType);
            if (CheckPrecedence(previousPrecedence, precedence))
            {
                // Add the operator token to the document and advance the symbol manager up to it.
                this.symbols.Advance();
                this.tokens.Add(operatorToken);

                // Get the expression on the right-hand side of the operator.
                Expression rightHandSide = this.GetNextConditionalPreprocessorExpression(sourceCode, precedence);
                if (rightHandSide == null)
                {
                    throw new SyntaxException(sourceCode, operatorToken.LineNumber);
                }

                // Create the partial token list for the expression.
                CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last);

                // Get the expression operator type.
                RelationalExpression.Operator relationalType;
                switch (operatorToken.SymbolType)
                {
                    case OperatorType.ConditionalEquals:
                        relationalType = RelationalExpression.Operator.EqualTo;
                        break;

                    case OperatorType.NotEquals:
                        relationalType = RelationalExpression.Operator.NotEqualTo;
                        break;

                    default:
                        throw new SyntaxException(sourceCode, operatorToken.LineNumber);
                }

                // Create and return the expression.
                expression = new RelationalExpression(partialTokens, relationalType, leftHandSide, rightHandSide);
                expressionReference.Target = expression;
            }

            return expression;
        }
Пример #27
0
 public PolyadicOperatorExpression(ExpressionPrecedence precedence, bool leftCombine)
     : this(precedence, 4)
 {
 }
        /// <summary>
        /// Reads the next expression from a conditional preprocessor directive.
        /// </summary>
        /// <param name="sourceCode">
        /// The source code.
        /// </param>
        /// <param name="previousPrecedence">
        /// The precedence of the expression just before this one.
        /// </param>
        /// <returns>
        /// Returns the expression.
        /// </returns>
        private Expression GetNextConditionalPreprocessorExpression(SourceCode sourceCode, ExpressionPrecedence previousPrecedence)
        {
            Param.AssertNotNull(sourceCode, "sourceCode");
            Param.Ignore(previousPrecedence);

            Reference<ICodePart> parentReference = new Reference<ICodePart>();

            // Move past comments and whitepace.
            this.AdvanceToNextConditionalDirectiveCodeSymbol(parentReference);

            // Saves the next expression.
            Expression expression = null;

            // Get the next symbol.
            Symbol symbol = this.symbols.Peek(1);
            if (symbol != null)
            {
                switch (symbol.SymbolType)
                {
                    case SymbolType.Other:
                        expression = this.GetConditionalPreprocessorConstantExpression();
                        break;

                    case SymbolType.Not:
                        expression = this.GetConditionalPreprocessorNotExpression(sourceCode, parentReference);
                        break;

                    case SymbolType.OpenParenthesis:
                        expression = this.GetConditionalPreprocessorParenthesizedExpression(sourceCode, parentReference);
                        break;

                    case SymbolType.False:
                        this.symbols.Advance();

                        Reference<ICodePart> falseExpressionReference = new Reference<ICodePart>();
                        CsToken token = new CsToken(symbol.Text, CsTokenType.False, symbol.Location, falseExpressionReference, this.symbols.Generated);
                        Node<CsToken> tokenNode = this.tokens.InsertLast(token);
                        expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode);
                        falseExpressionReference.Target = expression;
                        break;

                    case SymbolType.True:
                        this.symbols.Advance();

                        Reference<ICodePart> trueExpressionReference = new Reference<ICodePart>();
                        token = new CsToken(symbol.Text, CsTokenType.True, symbol.Location, trueExpressionReference, this.symbols.Generated);
                        tokenNode = this.tokens.InsertLast(token);
                        expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode);
                        trueExpressionReference.Target = expression;
                        break;

                    default:
                        throw new SyntaxException(sourceCode, symbol.LineNumber);
                }
            }

            // Gather up all extensions to this expression.
            while (expression != null)
            {
                Reference<ICodePart> expressionReference = new Reference<ICodePart>(expression);

                // Check if there is an extension to this expression.
                Expression extension = this.GetConditionalPreprocessorExpressionExtension(sourceCode, expressionReference, expression, previousPrecedence);
                if (extension != null)
                {
                    // The larger expression is what we want to return here.
                    expression = extension;
                }
                else
                {
                    // There are no more extensions.
                    break;
                }
            }

            // Return the expression.
            return expression;
        }
Пример #29
0
 public PolyadicOperatorExpression(ExpressionPrecedence precedence, int initArity)
 {
     this.precedence = precedence;
     this.operands   = new List <IExpression>(initArity);
 }
        /// <summary>
        /// Reads a conditional expression.
        /// </summary>
        /// <param name="leftHandSide">The expression on the left hand side of the operator.</param>
        /// <param name="previousPrecedence">The precedence of the expression just before this one.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the expression.</returns>
        private ConditionalExpression GetConditionalExpression(
            Expression leftHandSide, ExpressionPrecedence previousPrecedence, bool unsafeCode)
        {
            Param.AssertNotNull(leftHandSide, "leftHandSide");
            Param.Ignore(unsafeCode);
            Param.Ignore(previousPrecedence);

            ConditionalExpression expression = null;

            if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.Conditional))
            {
                var expressionReference = new Reference<ICodePart>();

                // Get the first operator.
                this.tokens.Add(this.GetOperatorToken(OperatorType.ConditionalQuestionMark, expressionReference));

                // Get the expression on the right-hand side of the operator.
                Expression trueValue = this.GetOperatorRightHandExpression(ExpressionPrecedence.Conditional, expressionReference, unsafeCode);

                // Get the next operator and make sure it is the correct type.
                this.tokens.Add(this.GetOperatorToken(OperatorType.ConditionalColon, expressionReference));

                // Get the expression on the right-hand side of the operator.
                Expression falseValue = this.GetOperatorRightHandExpression(ExpressionPrecedence.None, expressionReference, unsafeCode);

                // Create the partial token list for the expression.
                CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last);

                // Create and return the expression.
                expression = new ConditionalExpression(partialTokens, leftHandSide, trueValue, falseValue);
                expressionReference.Target = expression;
            }

            return expression;
        }
Пример #31
0
 private NullCoalescingExpression GetNullCoalescingExpression(Expression leftHandSide, ExpressionPrecedence previousPrecedence, bool unsafeCode)
 {
     NullCoalescingExpression expression = null;
     OperatorSymbol item = this.PeekOperatorToken();
     ExpressionPrecedence operatorPrecedence = GetOperatorPrecedence(item.SymbolType);
     if (CheckPrecedence(previousPrecedence, operatorPrecedence))
     {
         this.symbols.Advance();
         this.tokens.Add(item);
         Expression operatorRightHandExpression = this.GetOperatorRightHandExpression(operatorPrecedence, unsafeCode);
         CsTokenList tokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last);
         expression = new NullCoalescingExpression(tokens, leftHandSide, operatorRightHandExpression);
     }
     return expression;
 }
        /// <summary>
        /// Compares the precendence of the previous expression with the precedence of the next expression,
        /// to determine which has the higher precedence value.
        /// </summary>
        /// <param name="previousPrecedence">The previous expression's precedence.</param>
        /// <param name="nextPrecedence">The next expression's precendence.</param>
        /// <returns>Returns true if the next expression has greater precedence than the next expression.</returns>
        private static bool CheckPrecedence(ExpressionPrecedence previousPrecedence, ExpressionPrecedence nextPrecedence)
        {
            Param.AssertNotNull(previousPrecedence, "previousPrecedence");
            Param.AssertNotNull(nextPrecedence, "nextPrecedence");

            // Two expressions with no precendence can be chained back to back, and conditional expressions
            // are allowed to be embedded within other conditional expressions.
            if ((previousPrecedence == ExpressionPrecedence.None && nextPrecedence == ExpressionPrecedence.None) ||
                (previousPrecedence == ExpressionPrecedence.Conditional && nextPrecedence == ExpressionPrecedence.Conditional))
            {
                return true;
            }

            return (int)previousPrecedence > (int)nextPrecedence;
        }
Пример #33
0
 private Expression GetOperatorRightHandExpression(ExpressionPrecedence precedence, bool unsafeCode)
 {
     Expression nextExpression = this.GetNextExpression(precedence, unsafeCode);
     if (nextExpression == null)
     {
         throw this.CreateSyntaxException();
     }
     return nextExpression;
 }
        /// <summary>
        /// Reads a method access expression.
        /// </summary>
        /// <param name="methodName">The name of the method being called.</param>
        /// <param name="previousPrecedence">The precedence of the previous expression.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the expression.</returns>
        private MethodInvocationExpression GetMethodInvocationExpression(
            Expression methodName, ExpressionPrecedence previousPrecedence, bool unsafeCode)
        {
            Param.AssertNotNull(methodName, "methodName");
            Param.Ignore(previousPrecedence);
            Param.Ignore(unsafeCode);

            MethodInvocationExpression expression = null;
            if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.Primary))
            {
                var expressionReference = new Reference<ICodePart>();

                // The next symbol will be the opening parenthesis.
                Bracket openParenthesis = this.GetBracketToken(CsTokenType.OpenParenthesis, SymbolType.OpenParenthesis, expressionReference);
                Node<CsToken> openParenthesisNode = this.tokens.InsertLast(openParenthesis);

                // Get the argument list now.
                IList<Argument> argumentList = this.GetArgumentList(SymbolType.CloseParenthesis, expressionReference, unsafeCode);

                // Get the closing parenthesis.
                Bracket closeParenthesis = this.GetBracketToken(CsTokenType.CloseParenthesis, SymbolType.CloseParenthesis, expressionReference);
                Node<CsToken> closeParenthesisNode = this.tokens.InsertLast(closeParenthesis);

                openParenthesis.MatchingBracketNode = closeParenthesisNode;
                closeParenthesis.MatchingBracketNode = openParenthesisNode;

                // Pull out the first token from the method name.
                Debug.Assert(methodName.Tokens.First != null, "The method name should not be empty");
                Node<CsToken> firstTokenNode = methodName.Tokens.First;

                // Create the token list for the method invocation expression.
                CsTokenList partialTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);

                // Create and return the expression.
                expression = new MethodInvocationExpression(partialTokens, methodName, argumentList);
                expressionReference.Target = expression;
            }

            return expression;
        }
Пример #35
0
 private IncrementExpression GetPrimaryIncrementExpression(Expression leftHandSide, ExpressionPrecedence previousPrecedence)
 {
     IncrementExpression expression = null;
     if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.Primary))
     {
         this.tokens.Add(this.GetOperatorToken(OperatorType.Increment));
         CsTokenList tokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last);
         expression = new IncrementExpression(tokens, leftHandSide, IncrementExpression.IncrementType.Postfix);
     }
     return expression;
 }
        private Expression GetNextExpression(
            ExpressionPrecedence previousPrecedence, 
            Reference<ICodePart> parentReference,
            bool unsafeCode, 
            bool allowVariableDeclaration, 
            bool typeExpression)
        {
            Param.Ignore(previousPrecedence);
            Param.AssertNotNull(parentReference, "parentReference");
            Param.Ignore(unsafeCode);
            Param.Ignore(allowVariableDeclaration);
            Param.Ignore(typeExpression);

            // Saves the next expression.
            Expression expression = null;

            // Get the next symbol.
            Symbol symbol = this.GetNextSymbol(parentReference);

            if (symbol != null)
            {
                switch (symbol.SymbolType)
                {
                    case SymbolType.Other:
                        if (this.IsLambdaExpression())
                        {
                            expression = this.GetLambdaExpression(parentReference, unsafeCode);
                        }
                        else if (this.IsQueryExpression(unsafeCode))
                        {
                            expression = this.GetQueryExpression(parentReference, unsafeCode);
                        }

                        // If the expression is still null now, this is just a regular 'other' expression.
                        if (expression == null)
                        {
                            expression = this.GetOtherExpression(parentReference, allowVariableDeclaration, unsafeCode);
                        }

                        break;

                    case SymbolType.Checked:
                        expression = this.GetCheckedExpression(parentReference, unsafeCode);
                        break;

                    case SymbolType.Unchecked:
                        expression = this.GetUncheckedExpression(parentReference, unsafeCode);
                        break;

                    case SymbolType.New:
                        expression = this.GetNewAllocationExpression(parentReference, unsafeCode);
                        break;

                    case SymbolType.Stackalloc:
                        expression = this.GetStackallocExpression(parentReference, unsafeCode);
                        break;

                    case SymbolType.Sizeof:
                        expression = this.GetSizeofExpression(parentReference, unsafeCode);
                        break;

                    case SymbolType.Typeof:
                        expression = this.GetTypeofExpression(parentReference, unsafeCode);
                        break;

                    case SymbolType.Default:
                        expression = this.GetDefaultValueExpression(parentReference, unsafeCode);
                        break;

                    case SymbolType.Delegate:
                        expression = this.GetAnonymousMethodExpression(parentReference, unsafeCode);
                        break;

                    case SymbolType.Increment:
                        if (this.IsUnaryExpression())
                        {
                            expression = this.GetUnaryIncrementExpression(unsafeCode);
                        }

                        break;

                    case SymbolType.Decrement:
                        if (this.IsUnaryExpression())
                        {
                            expression = this.GetUnaryDecrementExpression(unsafeCode);
                        }

                        break;

                    case SymbolType.Plus:
                    case SymbolType.Minus:
                        if (this.IsUnaryExpression())
                        {
                            expression = this.GetUnaryExpression(parentReference, unsafeCode);
                        }

                        break;

                    case SymbolType.Not:
                    case SymbolType.Tilde:
                        expression = this.GetUnaryExpression(parentReference, unsafeCode);
                        break;

                    case SymbolType.OpenParenthesis:
                        if (this.IsLambdaExpression())
                        {
                            expression = this.GetLambdaExpression(parentReference, unsafeCode);
                        }
                        else
                        {
                            expression = this.GetOpenParenthesisExpression(previousPrecedence, unsafeCode);
                        }

                        break;

                    case SymbolType.Number:
                        var numberExpressionReference = new Reference<ICodePart>();
                        Node<CsToken> tokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.Number, SymbolType.Number, numberExpressionReference));
                        expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode);
                        numberExpressionReference.Target = expression;
                        break;

                    case SymbolType.String:
                        var stringExpressionReference = new Reference<ICodePart>();
                        tokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.String, SymbolType.String, stringExpressionReference));
                        expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode);
                        stringExpressionReference.Target = expression;
                        break;

                    case SymbolType.True:
                        var trueExpressionReference = new Reference<ICodePart>();
                        tokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.True, SymbolType.True, trueExpressionReference));
                        expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode);
                        trueExpressionReference.Target = expression;
                        break;

                    case SymbolType.False:
                        var falseExpressionReference = new Reference<ICodePart>();
                        tokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.False, SymbolType.False, falseExpressionReference));
                        expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode);
                        falseExpressionReference.Target = expression;
                        break;

                    case SymbolType.Null:
                        var nullExpressionReference = new Reference<ICodePart>();
                        tokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.Null, SymbolType.Null, nullExpressionReference));
                        expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode);
                        nullExpressionReference.Target = expression;
                        break;

                    case SymbolType.This:
                        var thisExpressionReference = new Reference<ICodePart>();
                        tokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.This, SymbolType.This, thisExpressionReference));
                        expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode);
                        thisExpressionReference.Target = expression;
                        break;

                    case SymbolType.Base:
                        var baseExpressionReference = new Reference<ICodePart>();
                        tokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.Base, SymbolType.Base, baseExpressionReference));
                        expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode);
                        baseExpressionReference.Target = expression;
                        break;

                    case SymbolType.Multiplication:
                        if (!unsafeCode)
                        {
                            goto default;
                        }

                        expression = this.GetUnsafeAccessExpression(parentReference, unsafeCode);
                        break;

                    case SymbolType.LogicalAnd:
                        if (!unsafeCode)
                        {
                            goto default;
                        }

                        expression = this.GetUnsafeAccessExpression(parentReference, unsafeCode);
                        break;

                    default:
                        throw new SyntaxException(this.document.SourceCode, symbol.LineNumber);
                }
            }

            // Gather up all extensions to this expression.
            while (expression != null)
            {
                var expressionReference = new Reference<ICodePart>(expression);

                // Check if there is an extension to this expression.
                Expression extension = this.GetExpressionExtension(expression, previousPrecedence, expressionReference, unsafeCode, typeExpression, allowVariableDeclaration);
                if (extension != null)
                {
                    // The larger expression is what we want to return here.
                    expression = extension;
                }
                else
                {
                    // There are no more extensions.
                    break;
                }
            }

            // Return the expression.
            return expression;
        }
Пример #37
0
 private static bool CheckPrecedence(ExpressionPrecedence previousPrecedence, ExpressionPrecedence nextPrecedence)
 {
     if (((previousPrecedence != ExpressionPrecedence.None) || (nextPrecedence != ExpressionPrecedence.None)) && ((previousPrecedence != ExpressionPrecedence.Conditional) || (nextPrecedence != ExpressionPrecedence.Conditional)))
     {
         return (previousPrecedence > nextPrecedence);
     }
     return true;
 }
        /// <summary>
        /// Reads an expression beginning with an opening parenthesis.
        /// </summary>
        /// <param name="previousPrecedence">The precedence of the previous expression.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the expression.</returns>
        private Expression GetOpenParenthesisExpression(ExpressionPrecedence previousPrecedence, bool unsafeCode)
        {
            Param.Ignore(previousPrecedence, unsafeCode);

            Expression expression = null;

            // Now check whether this is a cast.
            if (this.IsCastExpression(previousPrecedence, unsafeCode))
            {
                expression = this.GetCastExpression(unsafeCode);
            }
            else
            {
                // This is an expression wrapped in parenthesis.
                expression = this.GetParenthesizedExpression(unsafeCode);
            }

            return expression;
        }
Пример #39
0
        private RelationalExpression GetRelationalExpression(Expression leftHandSide, ExpressionPrecedence previousPrecedence, bool unsafeCode)
        {
            RelationalExpression expression = null;
            RelationalExpression.Operator equalTo;
            OperatorSymbol item = this.PeekOperatorToken();
            ExpressionPrecedence operatorPrecedence = GetOperatorPrecedence(item.SymbolType);
            if (!CheckPrecedence(previousPrecedence, operatorPrecedence))
            {
                return expression;
            }
            this.symbols.Advance();
            this.tokens.Add(item);
            Expression operatorRightHandExpression = this.GetOperatorRightHandExpression(operatorPrecedence, unsafeCode);
            CsTokenList tokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last);
            switch (item.SymbolType)
            {
                case OperatorType.ConditionalEquals:
                    equalTo = RelationalExpression.Operator.EqualTo;
                    break;

                case OperatorType.NotEquals:
                    equalTo = RelationalExpression.Operator.NotEqualTo;
                    break;

                case OperatorType.LessThan:
                    equalTo = RelationalExpression.Operator.LessThan;
                    break;

                case OperatorType.GreaterThan:
                    equalTo = RelationalExpression.Operator.GreaterThan;
                    break;

                case OperatorType.LessThanOrEquals:
                    equalTo = RelationalExpression.Operator.LessThanOrEqualTo;
                    break;

                case OperatorType.GreaterThanOrEquals:
                    equalTo = RelationalExpression.Operator.GreaterThanOrEqualTo;
                    break;

                default:
                    throw new InvalidOperationException();
            }
            return new RelationalExpression(tokens, equalTo, leftHandSide, operatorRightHandExpression);
        }
        /// <summary>
        /// Reads a primary increment expression.
        /// </summary>
        /// <param name="leftHandSide">The expression on the left hand side of the operator.</param>
        /// <param name="previousPrecedence">The precedence of the expression just before this one.</param>
        /// <returns>Returns the expression.</returns>
        private IncrementExpression GetPrimaryIncrementExpression(
            Expression leftHandSide, ExpressionPrecedence previousPrecedence)
        {
            Param.AssertNotNull(leftHandSide, "leftHandSide");
            Param.Ignore(previousPrecedence);

            IncrementExpression expression = null;

            // Check the previous precedence to see if we are allowed to gather up the as expression.
            if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.Primary))
            {
                var expressionReference = new Reference<ICodePart>();

                // Make sure the left hand side has at least one token.
                Debug.Assert(leftHandSide.Tokens.First != null, "The left hand side should not be empty.");

                // Get the increment symbol.
                this.tokens.Add(this.GetOperatorToken(OperatorType.Increment, expressionReference));

                // Create the partial token list for the expression.
                CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last);

                // Create and return the expression.
                expression = new IncrementExpression(partialTokens, leftHandSide, IncrementExpression.IncrementType.Postfix);
                expressionReference.Target = expression;
            }

            return expression;
        }
Пример #41
0
 private UnsafeAccessExpression GetUnsafeTypeExpression(Expression type, ExpressionPrecedence previousPrecedence)
 {
     UnsafeAccessExpression expression = null;
     OperatorType addressOf;
     UnsafeAccessExpression.Operator dereference;
     if (!CheckPrecedence(previousPrecedence, ExpressionPrecedence.Unary))
     {
         return expression;
     }
     Symbol nextSymbol = this.GetNextSymbol();
     if (nextSymbol.SymbolType == SymbolType.LogicalAnd)
     {
         addressOf = OperatorType.AddressOf;
         dereference = UnsafeAccessExpression.Operator.AddressOf;
     }
     else
     {
         if (nextSymbol.SymbolType != SymbolType.Multiplication)
         {
             throw new InvalidOperationException();
         }
         addressOf = OperatorType.Dereference;
         dereference = UnsafeAccessExpression.Operator.Dereference;
     }
     this.symbols.Advance();
     OperatorSymbol item = new OperatorSymbol(nextSymbol.Text, OperatorCategory.Reference, addressOf, nextSymbol.Location, this.symbols.Generated);
     this.tokens.Add(item);
     return new UnsafeAccessExpression(new CsTokenList(this.tokens, type.Tokens.First, this.tokens.Last), dereference, type);
 }
        /// <summary>
        /// Reads an expression beginning with two unknown words.
        /// </summary>
        /// <param name="type">The type of the variable.</param>
        /// <param name="previousPrecedence">The precedence of the previous expression.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the expression.</returns>
        private VariableDeclarationExpression GetVariableDeclarationExpression(
            Expression type, ExpressionPrecedence previousPrecedence, bool unsafeCode)
        {
            Param.AssertNotNull(type, "type");
            Param.Ignore(previousPrecedence);
            Param.Ignore(unsafeCode);

            Debug.Assert(
                type.ExpressionType == ExpressionType.Literal ||
                type.ExpressionType == ExpressionType.MemberAccess,
                "The left side of a variable declaration must either be a literal or a member access.");

            VariableDeclarationExpression expression = null;
            if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.None))
            {
                var expressionReference = new Reference<ICodePart>();

                // Convert the type expression to a literal type token expression.
                LiteralExpression literalType = null;
                if (type.ExpressionType == ExpressionType.Literal)
                {
                    literalType = type as LiteralExpression;
                    if (!(literalType.Token is TypeToken))
                    {
                        literalType = null;
                    }
                }

                if (literalType == null)
                {
                    literalType = this.ConvertTypeExpression(type);
                }

                // Get each declarator.
                List<VariableDeclaratorExpression> declarators = new List<VariableDeclaratorExpression>();

                while (true)
                {
                    // Get the next word.
                    Symbol symbol = this.GetNextSymbol(SymbolType.Other, expressionReference);

                    // Get the identifier.
                    LiteralExpression identifier = this.GetLiteralExpression(expressionReference, unsafeCode);
                    if (identifier == null || identifier.Tokens.First == null)
                    {
                        throw new SyntaxException(this.document.SourceCode, symbol.LineNumber);
                    }

                    // Get the initializer if it exists.
                    Expression initializer = null;

                    symbol = this.GetNextSymbol(expressionReference);
                    if (symbol.SymbolType == SymbolType.Equals)
                    {
                        // Add the equals token.
                        this.tokens.Add(this.GetOperatorToken(OperatorType.Equals, expressionReference));

                        // Check whether this is an array initializer.
                        symbol = this.GetNextSymbol(expressionReference);

                        if (symbol.SymbolType == SymbolType.OpenCurlyBracket)
                        {
                            initializer = this.GetArrayInitializerExpression(unsafeCode);
                        }
                        else
                        {
                            initializer = this.GetNextExpression(ExpressionPrecedence.None, expressionReference, unsafeCode);
                        }
                    }

                    // Create the token list for the declarator.
                    CsTokenList partialTokens = new CsTokenList(
                        this.tokens, identifier.Tokens.First, this.tokens.Last);

                    // Create and add the declarator.
                    declarators.Add(new VariableDeclaratorExpression(partialTokens, identifier, initializer));

                    // Now check if the next character is a comma. If so there is another declarator.
                    symbol = this.GetNextSymbol(expressionReference);
                    if (symbol.SymbolType != SymbolType.Comma)
                    {
                        // There are no more declarators.
                        break;
                    }

                    // Add the comma.
                    this.tokens.Add(this.GetToken(CsTokenType.Comma, SymbolType.Comma, expressionReference));
                }

                // Create the token list for the expression.
                CsTokenList tokenList = new CsTokenList(this.tokens, type.Tokens.First, this.tokens.Last);

                // Create the expression.
                expression = new VariableDeclarationExpression(tokenList, literalType, declarators.ToArray());
                expressionReference.Target = expression;
            }

            return expression;
        }
Пример #43
0
 private VariableDeclarationExpression GetVariableDeclarationExpression(Expression type, ExpressionPrecedence previousPrecedence, bool unsafeCode)
 {
     VariableDeclarationExpression expression = null;
     Symbol symbol;
     if (!CheckPrecedence(previousPrecedence, ExpressionPrecedence.None))
     {
         return expression;
     }
     LiteralExpression expression2 = null;
     if (type.ExpressionType == ExpressionType.Literal)
     {
         expression2 = type as LiteralExpression;
         if (!(expression2.Token is TypeToken))
         {
             expression2 = null;
         }
     }
     if (expression2 == null)
     {
         expression2 = this.ConvertTypeExpression(type);
     }
     List<VariableDeclaratorExpression> list = new List<VariableDeclaratorExpression>();
     Label_0042:
     symbol = this.GetNextSymbol(SymbolType.Other);
     LiteralExpression literalExpression = this.GetLiteralExpression(unsafeCode);
     if ((literalExpression == null) || (literalExpression.Tokens.First == null))
     {
         throw new SyntaxException(this.document.SourceCode, symbol.LineNumber);
     }
     Expression initializer = null;
     if (this.GetNextSymbol().SymbolType == SymbolType.Equals)
     {
         this.tokens.Add(this.GetOperatorToken(OperatorType.Equals));
         if (this.GetNextSymbol().SymbolType == SymbolType.OpenCurlyBracket)
         {
             initializer = this.GetArrayInitializerExpression(unsafeCode);
         }
         else
         {
             initializer = this.GetNextExpression(ExpressionPrecedence.None, unsafeCode);
         }
     }
     CsTokenList tokens = new CsTokenList(this.tokens, literalExpression.Tokens.First, this.tokens.Last);
     list.Add(new VariableDeclaratorExpression(tokens, literalExpression, initializer));
     if (this.GetNextSymbol().SymbolType == SymbolType.Comma)
     {
         this.tokens.Add(this.GetToken(CsTokenType.Comma, SymbolType.Comma));
         goto Label_0042;
     }
     return new VariableDeclarationExpression(new CsTokenList(this.tokens, type.Tokens.First, this.tokens.Last), expression2, list.ToArray());
 }
        /// <summary>
        /// Reads an array access expression.
        /// </summary>
        /// <param name="array">The array being accessed.</param>
        /// <param name="previousPrecedence">The precedence of the previous expression.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the expression.</returns>
        private ArrayAccessExpression GetArrayAccessExpression(
            Expression array, ExpressionPrecedence previousPrecedence, bool unsafeCode)
        {
            Param.AssertNotNull(array, "array");
            Param.Ignore(previousPrecedence);
            Param.Ignore(unsafeCode);

            ArrayAccessExpression expression = null;

            if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.Primary))
            {
                var expressionReference = new Reference<ICodePart>();

                // The next symbol will be the opening bracket.
                Bracket openingBracket = this.GetBracketToken(CsTokenType.OpenSquareBracket, SymbolType.OpenSquareBracket, expressionReference);
                Node<CsToken> openingBracketNode = this.tokens.InsertLast(openingBracket);

                // Get the argument list now.
                ICollection<Argument> argumentList = this.GetArgumentList(SymbolType.CloseSquareBracket, expressionReference, unsafeCode);

                // Get the closing bracket.
                Bracket closingBracket = this.GetBracketToken(CsTokenType.CloseSquareBracket, SymbolType.CloseSquareBracket, expressionReference);
                Node<CsToken> closingBracketNode = this.tokens.InsertLast(closingBracket);

                openingBracket.MatchingBracketNode = closingBracketNode;
                closingBracket.MatchingBracketNode = openingBracketNode;

                // Pull out the first token from the array.
                Node<CsToken> firstTokenNode = array.Tokens.First;

                // Create the token list for the method invocation expression.
                CsTokenList partialTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);

                // Create and return the expression.
                expression = new ArrayAccessExpression(partialTokens, array, argumentList);
                expressionReference.Target = expression;
            }

            return expression;
        }
        /// <summary>
        /// Reads the next expression from the file and returns it.
        /// </summary>
        /// <param name="previousPrecedence">The precedence of the expression just before this one.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the expression.</returns>
        private Expression GetNextExpression(ExpressionPrecedence previousPrecedence, bool unsafeCode)
        {
            Param.Ignore(previousPrecedence);
            Param.Ignore(unsafeCode);

            return this.GetNextExpression(previousPrecedence, unsafeCode, false, false);
        }
        /// <summary>
        /// Reads an assignment expression.
        /// </summary>
        /// <param name="leftHandSide">The expression on the left hand side of the operator.</param>
        /// <param name="previousPrecedence">The precedence of the expression just before this one.</param>
        /// <param name="parentReference">The parent code part.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the expression.</returns>
        private AssignmentExpression GetAssignmentExpression(
            Expression leftHandSide, ExpressionPrecedence previousPrecedence, Reference<ICodePart> parentReference, bool unsafeCode)
        {
            Param.AssertNotNull(leftHandSide, "leftHandSide");
            Param.Ignore(previousPrecedence);
            Param.Ignore(parentReference, "parentReference");
            Param.Ignore(unsafeCode);

            AssignmentExpression expression = null;
            var expressionReference = new Reference<ICodePart>();

            // Read the details of the expression.
            OperatorSymbol operatorToken = this.PeekOperatorToken(parentReference, expressionReference);
            Debug.Assert(operatorToken.Category == OperatorCategory.Assignment, "Expected an assignment operator");

            // Check the precedence of the operators to make sure we can gather this statement now.
            ExpressionPrecedence precedence = GetOperatorPrecedence(operatorToken.SymbolType);
            if (CheckPrecedence(previousPrecedence, precedence))
            {
                // Add the operator token to the document and advance the symbol manager up to it.
                this.symbols.Advance();
                this.tokens.Add(operatorToken);

                // Get the expression on the right-hand side of the operator.
                Expression rightHandSide = this.GetOperatorRightHandExpression(ExpressionPrecedence.None, expressionReference, unsafeCode);

                // Create the partial token list for the expression.
                CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last);

                // Get the expression operator type.
                AssignmentExpression.Operator type;
                switch (operatorToken.SymbolType)
                {
                    case OperatorType.Equals:
                        type = AssignmentExpression.Operator.Equals;
                        break;

                    case OperatorType.PlusEquals:
                        type = AssignmentExpression.Operator.PlusEquals;
                        break;

                    case OperatorType.MinusEquals:
                        type = AssignmentExpression.Operator.MinusEquals;
                        break;

                    case OperatorType.MultiplicationEquals:
                        type = AssignmentExpression.Operator.MultiplicationEquals;
                        break;

                    case OperatorType.DivisionEquals:
                        type = AssignmentExpression.Operator.DivisionEquals;
                        break;

                    case OperatorType.AndEquals:
                        type = AssignmentExpression.Operator.AndEquals;
                        break;

                    case OperatorType.OrEquals:
                        type = AssignmentExpression.Operator.OrEquals;
                        break;

                    case OperatorType.XorEquals:
                        type = AssignmentExpression.Operator.XorEquals;
                        break;

                    case OperatorType.ModEquals:
                        type = AssignmentExpression.Operator.ModEquals;
                        break;

                    case OperatorType.LeftShiftEquals:
                        type = AssignmentExpression.Operator.LeftShiftEquals;
                        break;

                    case OperatorType.RightShiftEquals:
                        type = AssignmentExpression.Operator.RightShiftEquals;
                        break;

                    default:
                        Debug.Fail("Unexpected operator type");
                        throw new InvalidOperationException();
                }

                // Create and return the expression.
                expression = new AssignmentExpression(partialTokens, type, leftHandSide, rightHandSide);
                expressionReference.Target = expression;
            }

            return expression;
        }
Пример #47
0
        /// <summary>
        /// Reads the next expression from a conditional preprocessor directive.
        /// </summary>
        /// <param name="document">The parent document.</param>
        /// <param name="parentProxy">Represents the parent item.</param>
        /// <param name="previousPrecedence">The precedence of the expression just before this one.</param>
        /// <returns>Returns the expression.</returns>
        private Expression GetNextConditionalPreprocessorExpression(CsDocument document, CodeUnitProxy parentProxy, ExpressionPrecedence previousPrecedence)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parentProxy, "parentProxy");
            Param.Ignore(previousPrecedence);

            // Move past comments and whitepace.
            this.AdvanceToNextConditionalDirectiveCodeSymbol(parentProxy);

            // Saves the next expression.
            Expression    expression = null;
            CodeUnitProxy expressionExtensionProxy = new CodeUnitProxy(this.document);

            // Get the next symbol.
            Symbol symbol = this.symbols.Peek(1);

            if (symbol != null)
            {
                switch (symbol.SymbolType)
                {
                case SymbolType.Other:
                    expression = this.GetConditionalPreprocessorConstantExpression(expressionExtensionProxy);
                    break;

                case SymbolType.Not:
                    expression = this.GetConditionalPreprocessorNotExpression(expressionExtensionProxy);
                    break;

                case SymbolType.OpenParenthesis:
                    expression = this.GetConditionalPreprocessorParenthesizedExpression(expressionExtensionProxy);
                    break;

                case SymbolType.False:
                    expression = this.CreateLiteralExpression(expressionExtensionProxy, symbol.SymbolType, TokenType.False);
                    break;

                case SymbolType.True:
                    expression = this.CreateLiteralExpression(expressionExtensionProxy, symbol.SymbolType, TokenType.True);
                    break;

                default:
                    throw new SyntaxException(this.document, symbol.LineNumber);
                }
            }

            // Gather up all extensions to this expression.
            Expression topLevelExpression = expression;

            // Gather up all extensions to this expression.
            while (expression != null)
            {
                // Check if there is an extension to this expression.
                Expression extension = this.GetConditionalPreprocessorExpressionExtension(expressionExtensionProxy, expression, previousPrecedence);
                if (extension != null)
                {
                    // Save the expression extension proxy and create a new one for the next expression extension.
                    expressionExtensionProxy = new CodeUnitProxy(this.document);
                    expressionExtensionProxy.Children.Add(expression);

                    topLevelExpression = expression;
                }
                else
                {
                    // There are no more extensions.
                    break;
                }
            }

            // There are no more extensions. The children of the current top-level expression extension proxy
            // should actually be children of the parent proxy, since there are no more extensions.
            CodeUnit unit = expressionExtensionProxy.Children.First;

            while (unit != null)
            {
                CodeUnit next = unit.LinkNode.Next;
                unit.Detach();
                unit.LinkNode.ContainingList = null;
                parentProxy.Children.Add(unit);
                unit = next;
            }

            // Return the expression.
            return(topLevelExpression);
        }