/// <summary>
        /// Initializes a new instance of the NameofExpression class.
        /// </summary>
        /// <param name="tokens">
        /// The list of tokens that form the expression.
        /// </param>
        /// <param name="name">
        /// The type literal to get the name of.
        /// </param>
        internal NameofExpression(CsTokenList tokens, LiteralExpression name)
            : base(ExpressionType.NameOf, tokens)
        {
            Param.AssertNotNull(tokens, "tokens");
            Param.AssertNotNull(name, "name");

            this.type = CodeParser.ExtractTypeTokenFromLiteralExpression(name);
            this.AddExpression(name);
        }
        /// <summary>
        /// Initializes a new instance of the TypeofExpression class.
        /// </summary>
        /// <param name="tokens">
        /// The list of tokens that form the expression.
        /// </param>
        /// <param name="type">
        /// The type literal to get the type of.
        /// </param>
        internal TypeofExpression(CsTokenList tokens, LiteralExpression type)
            : base(ExpressionType.Typeof, tokens)
        {
            Param.AssertNotNull(tokens, "tokens");
            Param.AssertNotNull(type, "type");

            this.type = CodeParser.ExtractTypeTokenFromLiteralExpression(type);
            this.AddExpression(type);
        }
        /// <summary>
        /// Initializes a new instance of the DefaultValueExpression class.
        /// </summary>
        /// <param name="tokens">
        /// The list of tokens that form the expression.
        /// </param>
        /// <param name="type">
        /// The type to obtain the default value of.
        /// </param>
        /// <param name="parent">
        /// The parent reference of this expression.
        /// </param>
        internal DefaultValueExpression(CsTokenList tokens, LiteralExpression type, Reference<ICodePart> parent)
            : base(ExpressionType.DefaultValue, tokens)
        {
            Param.AssertNotNull(tokens, "tokens");
            Param.AssertNotNull(type, "type");

            this.type = CodeParser.ExtractTypeTokenFromLiteralExpression(type);
            this.AddExpression(type);

            this.parent = parent;
        }
        /// <summary>
        /// Initializes a new instance of the CastExpression class.
        /// </summary>
        /// <param name="tokens">
        /// The list of tokens that form the expression.
        /// </param>
        /// <param name="type">
        /// The cast type.
        /// </param>
        /// <param name="castedExpression">
        /// The expression being casted.
        /// </param>
        internal CastExpression(CsTokenList tokens, LiteralExpression type, Expression castedExpression)
            : base(ExpressionType.Cast, tokens)
        {
            Param.AssertNotNull(tokens, "tokens");
            Param.AssertNotNull(type, "type");
            Param.AssertNotNull(castedExpression, "castedExpression");

            this.type = CodeParser.ExtractTypeTokenFromLiteralExpression(type);
            this.castedExpression = castedExpression;

            this.AddExpression(type);
            this.AddExpression(castedExpression);
        }
        /// <summary>
        /// Initializes a new instance of the IsExpression class.
        /// </summary>
        /// <param name="tokens">
        /// The list of tokens that form the expression.
        /// </param>
        /// <param name="value">
        /// The value to check.
        /// </param>
        /// <param name="type">
        /// The type to check.
        /// </param>
        internal IsExpression(CsTokenList tokens, Expression value, LiteralExpression type)
            : base(ExpressionType.Is, tokens)
        {
            Param.AssertNotNull(tokens, "tokens");
            Param.AssertNotNull(value, "value");
            Param.AssertNotNull(type, "type");

            this.value = value;
            this.type = CodeParser.ExtractTypeTokenFromLiteralExpression(type);

            this.AddExpression(value);
            this.AddExpression(type);
        }
        /// <summary>
        /// Initializes a new instance of the MemberAccessExpression class.
        /// </summary>
        /// <param name="tokens">
        /// The list of tokens that form the expression.
        /// </param>
        /// <param name="operatorType">
        /// The type of operation being performed.
        /// </param>
        /// <param name="leftHandSide">
        /// The left side of the operation.
        /// </param>
        /// <param name="rightHandSide">
        /// The member being accessed.
        /// </param>
        internal MemberAccessExpression(CsTokenList tokens, Operator operatorType, Expression leftHandSide, LiteralExpression rightHandSide)
            : base(ExpressionType.MemberAccess, tokens)
        {
            Param.AssertNotNull(tokens, "tokens");
            Param.Ignore(operatorType);
            Param.AssertNotNull(leftHandSide, "leftHandSide");
            Param.AssertNotNull(rightHandSide, "rightHandSide");

            this.operatorType = operatorType;
            this.leftHandSide = leftHandSide;
            this.rightHandSide = rightHandSide;

            this.AddExpression(leftHandSide);
            this.AddExpression(rightHandSide);
        }
        /// <summary>
        /// Initializes a new instance of the VariableDeclarationExpression class.
        /// </summary>
        /// <param name="tokens">
        /// The list of tokens that form the statement.
        /// </param>
        /// <param name="type">
        /// The type of the variable or variables being declared.
        /// </param>
        /// <param name="declarators">
        /// The list of declarators in the expression.
        /// </param>
        internal VariableDeclarationExpression(CsTokenList tokens, LiteralExpression type, ICollection<VariableDeclaratorExpression> declarators)
            : base(ExpressionType.VariableDeclaration, tokens)
        {
            Param.AssertNotNull(tokens, "tokens");
            Param.AssertNotNull(type, "type");
            Param.AssertNotNull(declarators, "declarators");

            this.declarators = declarators;

            Debug.Assert(declarators.IsReadOnly, "The declarators collection should be read-only.");

            this.AddExpression(type);
            this.type = CodeParser.ExtractTypeTokenFromLiteralExpression(type);

            foreach (VariableDeclaratorExpression expression in declarators)
            {
                this.AddExpression(expression);
                expression.ParentVariable = this;
            }
        }
        /// <summary>
        /// Converts the given expression into a literal expression containing a type token.
        /// </summary>
        /// <param name="expression">
        /// The expression to convert.
        /// </param>
        /// <returns>
        /// Returns the converted expression.
        /// </returns>
        private LiteralExpression ConvertTypeExpression(Expression expression)
        {
            Param.AssertNotNull(expression, "expression");

            // Get the first and last token in the expression.
            Node<CsToken> firstTokenNode = expression.Tokens.First;
            Node<CsToken> lastTokenNode = expression.Tokens.Last;

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

            // Create a new token list containing these tokens.
            List<CsToken> tokenList = new List<CsToken>();
            foreach (CsToken token in expression.Tokens)
            {
                tokenList.Add(token);
                token.ParentRef = typeTokenReference;
            }

            // Remove the extra tokens from the master list.
            if (firstTokenNode != null && expression.Tokens.First != null)
            {
                Node<CsToken> temp = firstTokenNode.Next;
                if (!expression.Tokens.OutOfBounds(temp))
                {
                    this.tokens.RemoveRange(temp, expression.Tokens.Last);
                }
            }

            // Add the child tokens to a token list.
            MasterList<CsToken> childTokens = new MasterList<CsToken>(tokenList);

            // Create the new type token.
            TypeToken typeToken = new TypeToken(childTokens, CsToken.JoinLocations(firstTokenNode, lastTokenNode), expressionReference, firstTokenNode.Value.Generated);
            typeTokenReference.Target = typeToken;

            // Insert the new token.
            Node<CsToken> typeTokenNode = this.tokens.Replace(firstTokenNode, typeToken);

            // Create the literal expression.
            LiteralExpression literalExpression = new LiteralExpression(new CsTokenList(this.tokens, firstTokenNode, firstTokenNode), typeTokenNode);

            expressionReference.Target = literalExpression;

            return literalExpression;
        }
        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.IsDelegateExpression())
                        {
                            expression = this.GetAnonymousMethodExpression(parentReference, unsafeCode);
                        }
                        else if (this.IsLambdaExpression())
                        {
                            expression = this.GetLambdaExpression(parentReference, unsafeCode);
                        }
                        else if (this.IsQueryExpression(unsafeCode))
                        {
                            expression = this.GetQueryExpression(parentReference, unsafeCode);
                        }
                        else if (this.IsAwaitExpression())
                        {
                            expression = this.GetAwaitExpression(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:
                        Reference<ICodePart> 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:
                        Reference<ICodePart> 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:
                        Reference<ICodePart> 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:
                        Reference<ICodePart> 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:
                        Reference<ICodePart> 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:
                        Reference<ICodePart> 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:
                        Reference<ICodePart> 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)
            {
                Reference<ICodePart> 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)
                {
                    // There are no more extensions.
                    break;
                }

                // The larger expression is what we want to return here.
                expression = extension;
            }

            // Return the expression.
            return expression;
        }
        /// <summary>
        /// Reads an expression starting with an unknown word.
        /// </summary>
        /// <param name="parentReference">
        /// The parent code part.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <returns>
        /// Returns the expression.
        /// </returns>
        private LiteralExpression GetLiteralExpression(Reference<ICodePart> parentReference, bool unsafeCode)
        {
            Param.Ignore(unsafeCode);
            Param.AssertNotNull(parentReference, "parentReference");

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

            // Create a reference to the literal expression we're creating.
            Reference<ICodePart> expressionReference = new Reference<ICodePart>();

            // First, check if this is a generic.
            CsToken literalToken = null;
            int temp;
            bool generic = false;
            if (symbol.SymbolType == SymbolType.Other && this.HasTypeSignature(1, false, out temp, out generic) && generic)
            {
                literalToken = this.GetGenericToken(expressionReference, unsafeCode);
            }

            if (literalToken == null)
            {
                // This is not a generic. Just convert the symbol to a token.
                literalToken = this.GetToken(CsTokenType.Other, SymbolType.Other, expressionReference);
            }

            // Add the token to the document.
            Node<CsToken> literalTokenNode = this.tokens.InsertLast(literalToken);

            // Create a literal expression from this token.
            LiteralExpression expression = new LiteralExpression(this.tokens, literalTokenNode);
            expressionReference.Target = expression;

            return expression;
        }
        /// <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 expression starting with an unknown word.
        /// </summary>
        /// <returns>Returns the expression.</returns>
        private LiteralExpression GetConditionalPreprocessorConstantExpression()
        {
            // Get the first symbol.
            Symbol symbol = this.symbols.Peek(1);
            Debug.Assert(symbol != null && symbol.SymbolType == SymbolType.Other, "Expected a text symbol");

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

            // Convert the symbol to a token.
            this.symbols.Advance();
            CsToken literalToken = new CsToken(symbol.Text, CsTokenType.Other, symbol.Location, expressionReference, this.symbols.Generated);
            Node<CsToken> literalTokenNode = this.tokens.InsertLast(literalToken);

            // Create a literal expression from this token.
            LiteralExpression expression = new LiteralExpression(this.tokens, literalTokenNode);
            expressionReference.Target = expression;

            return expression;
        }
        /// <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>
        /// Parses and returns a constructor.
        /// </summary>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="elementReference">
        /// A reference to the element being created.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code is marked as generated code.
        /// </param>
        /// <param name="xmlHeader">
        /// The element's documentation header.
        /// </param>
        /// <param name="attributes">
        /// The attributes on the element.
        /// </param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private Constructor ParseConstructor(
            CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);
            Param.Ignore(xmlHeader);
            Param.Ignore(attributes);

            Node<CsToken> previousTokenNode = this.tokens.Last;

            // Get the modifiers and access.
            AccessModifierType accessModifier = AccessModifierType.Private;
            Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, ConstructorModifiers);

            unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe);

            // Get the name of the constructor.
            CsToken name = this.GetElementNameToken(elementReference, unsafeCode);
            this.tokens.Add(name);

            // Get the parameter list.
            IList<Parameter> parameters = this.ParseParameterList(elementReference, unsafeCode, SymbolType.OpenParenthesis);

            // Get the constructor initializer if there is one.
            MethodInvocationExpression constructorInitializer = null;

            Symbol symbol = this.GetNextSymbol(elementReference);
            if (symbol.SymbolType == SymbolType.Colon)
            {
                this.tokens.Add(this.GetToken(CsTokenType.BaseColon, SymbolType.Colon, elementReference));

                // The next symbol must be the keyword base or this.
                symbol = this.GetNextSymbol(elementReference);
                if (symbol.SymbolType != SymbolType.This && symbol.SymbolType != SymbolType.Base)
                {
                    throw this.CreateSyntaxException();
                }

                Reference<ICodePart> initializerNameExpressionReference = new Reference<ICodePart>();
                Node<CsToken> initializerNameTokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.Other, symbol.SymbolType, initializerNameExpressionReference));

                // Get the name expression.
                LiteralExpression initializerNameExpression = new LiteralExpression(this.tokens, initializerNameTokenNode);
                initializerNameExpressionReference.Target = initializerNameExpression;

                // Get the initializer expression.
                constructorInitializer = this.GetMethodInvocationExpression(initializerNameExpression, ExpressionPrecedence.None, unsafeCode);
            }

            // Create the declaration.
            Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next;
            CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);
            Declaration declaration = new Declaration(declarationTokens, name.Text, ElementType.Constructor, accessModifier, modifiers);

            Constructor constructor = new Constructor(
                this.document, parent, xmlHeader, attributes, declaration, parameters, constructorInitializer, unsafeCode, generated);

            elementReference.Target = constructor;

            // If the constructor is extern, it will not have a body.
            if (modifiers.ContainsKey(CsTokenType.Extern))
            {
                // Get the closing semicolon.
                this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference));
            }
            else
            {
                // Get the body.
                this.ParseStatementContainer(constructor, true, unsafeCode);
            }

            return constructor;
        }
        /// <summary>
        /// Reads the next goto statement from the file and returns it.
        /// </summary>
        /// <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 statement.
        /// </returns>
        private GotoStatement ParseGotoStatement(Reference<ICodePart> parentReference, bool unsafeCode)
        {
            Param.AssertNotNull(parentReference, "parentReference");
            Param.Ignore(unsafeCode);

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

            // Move past the goto keyword.
            CsToken firstToken = this.GetToken(CsTokenType.Goto, SymbolType.Goto, parentReference, statementReference);
            Node<CsToken> firstTokenNode = this.tokens.InsertLast(firstToken);

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

            Expression identifier = null;
            if (symbol.SymbolType == SymbolType.Default)
            {
                Node<CsToken> tokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.Other, SymbolType.Default, statementReference));
                identifier = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode);
            }
            else if (symbol.SymbolType == SymbolType.Case)
            {
                this.tokens.Add(this.GetToken(CsTokenType.Other, SymbolType.Case, statementReference));
                identifier = this.GetNextExpression(ExpressionPrecedence.None, statementReference, unsafeCode);
            }
            else
            {
                identifier = this.GetNextExpression(ExpressionPrecedence.None, statementReference, unsafeCode);
            }

            // Get the closing semicolon.
            this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, statementReference));

            // Create the token list for the statement.
            CsTokenList partialTokens = new CsTokenList(this.tokens, firstTokenNode, firstTokenNode);

            // Create and return the goto-statement.
            GotoStatement statement = new GotoStatement(partialTokens, identifier);
            statementReference.Target = statement;

            return statement;
        }
        /// <summary>
        /// The save.
        /// </summary>
        /// <param name="literalExpression">
        /// The literal expression.
        /// </param>
        private void Save(LiteralExpression literalExpression)
        {
            switch (literalExpression.Token.CsTokenType)
            {
                case CsTokenType.Abstract:
                    break;
                case CsTokenType.Add:
                    break;
                case CsTokenType.Alias:
                    break;
                case CsTokenType.As:
                    break;
                case CsTokenType.Ascending:
                    break;
                case CsTokenType.Attribute:
                    break;
                case CsTokenType.AttributeColon:
                    break;
                case CsTokenType.Base:

                    ////if (this.currentBaseClass != null)
                    ////{
                    ////    this.Save(this.currentBaseClass, this.destCPP, true);
                    ////    return;
                    ////}
                    this.cppWriter.Write("__super::");
                    return;
                case CsTokenType.BaseColon:
                    break;
                case CsTokenType.Break:
                    break;
                case CsTokenType.By:
                    break;
                case CsTokenType.Case:
                    break;
                case CsTokenType.Catch:
                    break;
                case CsTokenType.Checked:
                    break;
                case CsTokenType.Class:
                    break;
                case CsTokenType.CloseAttributeBracket:
                    break;
                case CsTokenType.CloseCurlyBracket:
                    break;
                case CsTokenType.CloseGenericBracket:
                    break;
                case CsTokenType.CloseParenthesis:
                    break;
                case CsTokenType.CloseSquareBracket:
                    break;
                case CsTokenType.Comma:
                    break;
                case CsTokenType.Const:
                    break;
                case CsTokenType.Continue:
                    break;
                case CsTokenType.Default:
                    break;
                case CsTokenType.DefaultValue:
                    break;
                case CsTokenType.Delegate:
                    break;
                case CsTokenType.Descending:
                    break;
                case CsTokenType.DestructorTilde:
                    break;
                case CsTokenType.Do:
                    break;
                case CsTokenType.Else:
                    break;
                case CsTokenType.EndOfLine:
                    break;
                case CsTokenType.Enum:
                    break;
                case CsTokenType.Equals:
                    break;
                case CsTokenType.Event:
                    break;
                case CsTokenType.Explicit:
                    break;
                case CsTokenType.Extern:
                    break;
                case CsTokenType.ExternDirective:
                    break;
                case CsTokenType.False:
                    break;
                case CsTokenType.Finally:
                    break;
                case CsTokenType.Fixed:
                    break;
                case CsTokenType.For:
                    break;
                case CsTokenType.Foreach:
                    break;
                case CsTokenType.From:
                    break;
                case CsTokenType.Get:
                    break;
                case CsTokenType.Goto:
                    break;
                case CsTokenType.Group:
                    break;
                case CsTokenType.If:
                    break;
                case CsTokenType.Implicit:
                    break;
                case CsTokenType.In:
                    break;
                case CsTokenType.Interface:
                    break;
                case CsTokenType.Internal:
                    break;
                case CsTokenType.Into:
                    break;
                case CsTokenType.Is:
                    break;
                case CsTokenType.Join:
                    break;
                case CsTokenType.LabelColon:
                    break;
                case CsTokenType.Let:
                    break;
                case CsTokenType.Lock:
                    break;
                case CsTokenType.MultiLineComment:
                    break;
                case CsTokenType.Namespace:
                    break;
                case CsTokenType.New:
                    break;
                case CsTokenType.Null:

                    this.cppWriter.Write("nullptr");
                    return;

                case CsTokenType.NullableTypeSymbol:
                    break;
                case CsTokenType.Number:
                    break;
                case CsTokenType.On:
                    break;
                case CsTokenType.OpenAttributeBracket:
                    break;
                case CsTokenType.OpenCurlyBracket:
                    break;
                case CsTokenType.OpenGenericBracket:
                    break;
                case CsTokenType.OpenParenthesis:
                    break;
                case CsTokenType.OpenSquareBracket:
                    break;
                case CsTokenType.Operator:
                    break;
                case CsTokenType.OperatorSymbol:
                    break;
                case CsTokenType.OrderBy:
                    break;
                case CsTokenType.Other:
                    this.cppWriter.Write(this.letteralOthersPrefix);
                    break;
                case CsTokenType.Out:
                    break;
                case CsTokenType.Override:
                    break;
                case CsTokenType.Params:
                    break;
                case CsTokenType.Partial:
                    break;
                case CsTokenType.PreprocessorDirective:
                    break;
                case CsTokenType.Private:
                    break;
                case CsTokenType.Protected:
                    break;
                case CsTokenType.Public:
                    break;
                case CsTokenType.Readonly:
                    break;
                case CsTokenType.Ref:
                    break;
                case CsTokenType.Remove:
                    break;
                case CsTokenType.Return:
                    break;
                case CsTokenType.Sealed:
                    break;
                case CsTokenType.Select:
                    break;
                case CsTokenType.Semicolon:
                    break;
                case CsTokenType.Set:
                    break;
                case CsTokenType.SingleLineComment:
                    break;
                case CsTokenType.Sizeof:
                    break;
                case CsTokenType.Stackalloc:
                    break;
                case CsTokenType.Static:
                    break;
                case CsTokenType.String:
                    this.cppWriter.Write(literalExpression.ToString());

                    // var typeResolverReference = new ResolvedTypeReference("System.String", this);
                    // this.AddToRequiredTypeRefsForBody(
                    // typeResolverReference.CSType, typeResolverReference.FullyQualifiedName);
                    return;
                case CsTokenType.Struct:
                    break;
                case CsTokenType.Switch:
                    break;
                case CsTokenType.This:
                    break;
                case CsTokenType.Throw:
                    break;
                case CsTokenType.True:
                    break;
                case CsTokenType.Try:
                    break;
                case CsTokenType.Typeof:
                    break;
                case CsTokenType.Unchecked:
                    break;
                case CsTokenType.Unsafe:
                    break;
                case CsTokenType.Using:
                    break;
                case CsTokenType.UsingDirective:
                    break;
                case CsTokenType.Virtual:
                    break;
                case CsTokenType.Volatile:
                    break;
                case CsTokenType.Where:
                    break;
                case CsTokenType.WhereColon:
                    break;
                case CsTokenType.While:
                    break;
                case CsTokenType.WhileDo:
                    break;
                case CsTokenType.WhiteSpace:
                    break;
                case CsTokenType.XmlHeader:
                    break;
                case CsTokenType.XmlHeaderLine:
                    break;
                case CsTokenType.Yield:
                    break;
                default:
                    break;
            }

            this.cppWriter.Write(literalExpression.ToString());
        }
Exemple #17
0
        /// <summary>
        /// Extracts a TypeToken from the literal expression, assuming that one exists.
        /// </summary>
        /// <param name="literal">
        /// The literal expression.
        /// </param>
        /// <returns>
        /// Returns the type token.
        /// </returns>
        internal static TypeToken ExtractTypeTokenFromLiteralExpression(LiteralExpression literal)
        {
            Param.AssertNotNull(literal, "literal");

            Debug.Assert(
                literal.TokenNode != null && literal.TokenNode.Value != null
                && (literal.TokenNode.Value.CsTokenClass == CsTokenClass.Type || literal.TokenNode.Value.CsTokenClass == CsTokenClass.GenericType), 
                "The literal expression does not contain a TypeToken");

            return (TypeToken)literal.TokenNode.Value;
        }
        /// <summary>
        /// Parses the given expression.
        /// </summary>
        /// <param name="expression">
        /// The expression.
        /// </param>
        /// <param name="parentExpression">
        /// The parent expression, if there is one.
        /// </param>
        /// <param name="parentElement">
        /// The element that contains the expressions.
        /// </param>
        /// <param name="parentClass">
        /// The class that the element belongs to.
        /// </param>
        /// <param name="members">
        /// The collection of members of the parent class.
        /// </param>
        private void CheckClassMemberRulesForExpression(
            Expression expression, Expression parentExpression, CsElement parentElement, ClassBase parentClass, Dictionary <string, List <CsElement> > members)
        {
            Param.AssertNotNull(expression, "expression");
            Param.Ignore(parentExpression);
            Param.AssertNotNull(parentElement, "parentElement");
            Param.AssertNotNull(parentClass, "parentClass");
            Param.AssertNotNull(members, "members");

            if (expression.ExpressionType == ExpressionType.Literal)
            {
                LiteralExpression literalExpression = (LiteralExpression)expression;

                // Check to see whether this literal is preceded by a member access symbol. If not
                // then we want to check whether this is a reference to one of our class members.
                if (!IsLiteralTokenPrecededByMemberAccessSymbol(literalExpression.TokenNode, expression.Tokens.MasterList))
                {
                    // Process the literal.
                    this.CheckClassMemberRulesForLiteralToken(literalExpression.TokenNode, expression, parentExpression, parentElement, parentClass, members);
                }
            }
            else
            {
                if (expression.ExpressionType == ExpressionType.Assignment && parentExpression != null &&
                    parentExpression.ExpressionType == ExpressionType.CollectionInitializer)
                {
                    // When we encounter assignment expressions within collection initializer expressions, we ignore the expression
                    // on the left-hand side of the assignment. This is because we know that the left-hand side refers to a property on
                    // the type being initialized, not a property on the local class. Thus, it does not ever need to be prefixed by this.
                    // Without this check we can get name collisions, such as:
                    // public sealed class Person
                    //// {
                    ////     public string FirstName { get; }
                    ////     public void CreateAnonymousType()
                    ////     {
                    ////         var anonymousType = new { FirstName = this.FirstName };
                    ////     }
                    //// }
                    this.CheckClassMemberRulesForExpression(((AssignmentExpression)expression).RightHandSide, expression, parentElement, parentClass, members);
                }
                else if (expression.ChildExpressions.Count > 0)
                {
                    // Check each child expression within this expression.
                    this.CheckClassMemberRulesForExpressions(expression.ChildExpressions, expression, parentElement, parentClass, members);
                }

                // Check if this is an anonymous method expression, which contains a child statement list.
                if (expression.ExpressionType == ExpressionType.AnonymousMethod)
                {
                    // Check the statements under this anonymous method.
                    this.CheckClassMemberRulesForStatements(expression.ChildStatements, parentElement, parentClass, members);
                }
                else if (expression.ExpressionType == ExpressionType.MethodInvocation)
                {
                    // Check each of the arguments passed into the method call.
                    MethodInvocationExpression methodInvocation = (MethodInvocationExpression)expression;
                    foreach (Argument argument in methodInvocation.Arguments)
                    {
                        // Check each expression within this child expression.
                        if (argument.Expression.ExpressionType != ExpressionType.MethodInvocation)
                        {
                            this.CheckClassMemberRulesForExpression(argument.Expression, null, parentElement, parentClass, members);
                        }
                    }
                }
            }
        }