/// <summary>
        /// Reads the argument list for a method invocation expression.
        /// </summary>
        /// <param name="closingSymbol">
        /// The symbol that closes the argument list.
        /// </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 list of arguments in the method invocation.
        /// </returns>
        private IList<Argument> GetArgumentList(SymbolType closingSymbol, Reference<ICodePart> parentReference, bool unsafeCode)
        {
            Param.AssertNotNull(closingSymbol, "closingSymbol");
            Param.AssertNotNull(parentReference, "parentReference");
            Param.Ignore(unsafeCode);

            List<Argument> arguments = new List<Argument>();

            while (true)
            {
                // Save the current last token.
                Node<CsToken> previousTokenNode = this.tokens.Last;

                // Move to the next code token.
                Symbol firstSymbol = this.GetNextSymbol(parentReference);

                if (firstSymbol.SymbolType == closingSymbol)
                {
                    break;
                }

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

                if (firstSymbol.SymbolType != SymbolType.Comma)
                {
                    // Gather the parameter name label if it exists.
                    CsToken argumentName = null;
                    if (firstSymbol.SymbolType == SymbolType.Other)
                    {
                        // Look at the next symbol after the label.
                        int index = this.GetNextCodeSymbolIndex(2);
                        if (index >= 0)
                        {
                            Symbol colon = this.symbols.Peek(index);
                            if (colon != null && colon.SymbolType == SymbolType.Colon)
                            {
                                // This is an argument name label. Add the name label and the colon.
                                argumentName = this.GetToken(CsTokenType.Other, SymbolType.Other, argumentReference);
                                this.tokens.Add(argumentName);

                                // The next symbol must be the colon.
                                this.tokens.Add(this.GetToken(CsTokenType.LabelColon, SymbolType.Colon, argumentReference));
                            }
                        }
                    }

                    // Gather the argument modifiers.
                    ParameterModifiers modifiers = ParameterModifiers.None;

                    int i = this.GetNextCodeSymbolIndex(1);
                    if (i >= 0)
                    {
                        Symbol symbol = this.symbols.Peek(i);

                        if (symbol.SymbolType == SymbolType.Ref)
                        {
                            this.tokens.Add(this.GetToken(CsTokenType.Ref, SymbolType.Ref, argumentReference));
                            modifiers = ParameterModifiers.Ref;
                        }
                        else if (symbol.SymbolType == SymbolType.Out)
                        {
                            this.tokens.Add(this.GetToken(CsTokenType.Out, SymbolType.Out, argumentReference));
                            modifiers = ParameterModifiers.Out;
                        }
                        else if (symbol.SymbolType == SymbolType.Params)
                        {
                            this.tokens.Add(this.GetToken(CsTokenType.Params, SymbolType.Params, argumentReference));
                            modifiers = ParameterModifiers.Params;
                        }
                    }

                    // The argument body expression must come next.
                    Expression argumentExpression = this.GetNextExpression(ExpressionPrecedence.None, argumentReference, unsafeCode);

                    // Create the collection of tokens that form the argument, and strip off whitesace from the beginning and end.
                    CsTokenList argumentTokenList = new CsTokenList(this.tokens, previousTokenNode.Next, this.tokens.Last);
                    argumentTokenList.Trim(CsTokenType.EndOfLine, CsTokenType.WhiteSpace);

                    // Create and add the argument.
                    Argument argument = new Argument(
                        argumentName, 
                        modifiers, 
                        argumentExpression, 
                        CodeLocation.Join(firstSymbol.Location, argumentExpression.Location), 
                        parentReference, 
                        argumentTokenList, 
                        this.symbols.Generated);

                    argumentReference.Target = argument;
                    arguments.Add(argument);
                }

                // If the next symbol is a comma, add the comma and proceed.
                int x = this.GetNextCodeSymbolIndex(1);
                if (x >= 0)
                {
                    if (this.symbols.Peek(x).SymbolType == SymbolType.Comma)
                    {
                        this.tokens.Add(this.GetToken(CsTokenType.Comma, SymbolType.Comma, parentReference));
                    }
                }
            }

            // Trim the list down to a small array before returning it.
            return arguments.ToArray();
        }
        /// <summary>
        /// Determine whether the argument passed in is equivalent to ""
        /// </summary>
        /// <param name="argument">
        /// The Argument to check.
        /// </param>
        /// <returns>
        /// True if equivalent to string.empty otherwise false.
        /// </returns>
        private static bool ArgumentTokensMatchStringEmpty(Argument argument)
        {
            CsToken firstToken = argument.Tokens.First.Value;

            if (firstToken.CsTokenType == CsTokenType.String && IsEmptyString(firstToken.Text))
            {
                return true;
            }

            if (firstToken.CsTokenType == CsTokenType.Null)
            {
                return true;
            }

            if (argument.Tokens.MatchTokens(StringComparison.OrdinalIgnoreCase, "string", ".", "empty"))
            {
                return true;
            }

            if (argument.Tokens.MatchTokens(StringComparison.OrdinalIgnoreCase, "system", ".", "string", ".", "empty"))
            {
                return true;
            }

            if (argument.Tokens.MatchTokens(StringComparison.OrdinalIgnoreCase, "global", "::", "system", ".", "string", ".", "empty"))
            {
                return true;
            }

            return false;
        }
        /// <summary>
        /// The save.
        /// </summary>
        /// <param name="argument">
        /// The argument.
        /// </param>
        /// <param name="writer">
        /// The writer.
        /// </param>
        private void Save(Argument argument)
        {
            if (argument.Modifiers != ParameterModifiers.None)
            {
                this.Save(argument.Modifiers, this.cppWriter);
                this.SaveModifiersAfter(argument.Modifiers, this.cppWriter);

                this.cppWriter.Write(' ');
            }

            @switch(argument.Expression);
        }