Example #1
0
        private Symbol GetOperatorSymbol(char character)
        {
            Param.Ignore(character);

            SymbolType type = SymbolType.Other;
            var text = new StringBuilder();

            if (character == '.')
            {
                text.Append(".");
                type = SymbolType.Dot;
                this.codeReader.ReadNext();
            }
            else if (character == '~')
            {
                text.Append("~");
                type = SymbolType.Tilde;
                this.codeReader.ReadNext();
            }
            else if (character == '+')
            {
                text.Append("+");
                type = SymbolType.Plus;
                this.codeReader.ReadNext();

                character = this.codeReader.Peek();
                if (character == '+')
                {
                    text.Append("+");
                    type = SymbolType.Increment;
                    this.codeReader.ReadNext();
                }
                else if (character == '=')
                {
                    text.Append("=");
                    type = SymbolType.PlusEquals;
                    this.codeReader.ReadNext();
                }
            }
            else if (character == '-')
            {
                text.Append("-");
                type = SymbolType.Minus;
                this.codeReader.ReadNext();

                character = this.codeReader.Peek();
                if (character == '-')
                {
                    text.Append("-");
                    type = SymbolType.Decrement;
                    this.codeReader.ReadNext();
                }
                else if (character == '=')
                {
                    text.Append("=");
                    type = SymbolType.MinusEquals;
                    this.codeReader.ReadNext();
                }
                else if (character == '>')
                {
                    text.Append(">");
                    type = SymbolType.Pointer;
                    this.codeReader.ReadNext();
                }
            }
            else if (character == '*')
            {
                text.Append("*");
                type = SymbolType.Multiplication;
                this.codeReader.ReadNext();

                character = this.codeReader.Peek();
                if (character == '=')
                {
                    text.Append("*");
                    type = SymbolType.MultiplicationEquals;
                    this.codeReader.ReadNext();
                }
            }
            else if (character == '/')
            {
                text.Append("/");
                type = SymbolType.Division;
                this.codeReader.ReadNext();

                character = this.codeReader.Peek();
                if (character == '=')
                {
                    text.Append("=");
                    type = SymbolType.DivisionEquals;
                    this.codeReader.ReadNext();
                }
            }
            else if (character == '|')
            {
                text.Append("|");
                type = SymbolType.LogicalOr;
                this.codeReader.ReadNext();

                character = this.codeReader.Peek();
                if (character == '=')
                {
                    text.Append("=");
                    type = SymbolType.OrEquals;
                    this.codeReader.ReadNext();
                }
                else if (character == '|')
                {
                    text.Append("|");
                    type = SymbolType.ConditionalOr;
                    this.codeReader.ReadNext();
                }
            }
            else if (character == '&')
            {
                text.Append("&");
                type = SymbolType.LogicalAnd;
                this.codeReader.ReadNext();

                character = this.codeReader.Peek();
                if (character == '=')
                {
                    text.Append("=");
                    type = SymbolType.AndEquals;
                    this.codeReader.ReadNext();
                }
                else if (character == '&')
                {
                    text.Append("&");
                    type = SymbolType.ConditionalAnd;
                    this.codeReader.ReadNext();
                }
            }
            else if (character == '^')
            {
                text.Append("^");
                type = SymbolType.LogicalXor;
                this.codeReader.ReadNext();

                character = this.codeReader.Peek();
                if (character == '=')
                {
                    text.Append("=");
                    type = SymbolType.XorEquals;
                    this.codeReader.ReadNext();
                }
            }
            else if (character == '!')
            {
                text.Append("!");
                type = SymbolType.Not;
                this.codeReader.ReadNext();

                character = this.codeReader.Peek();
                if (character == '=')
                {
                    text.Append("=");
                    type = SymbolType.NotEquals;
                    this.codeReader.ReadNext();
                }
            }
            else if (character == '%')
            {
                text.Append("%");
                type = SymbolType.Mod;
                this.codeReader.ReadNext();

                character = this.codeReader.Peek();
                if (character == '=')
                {
                    text.Append("=");
                    type = SymbolType.ModEquals;
                    this.codeReader.ReadNext();
                }
            }
            else if (character == '=')
            {
                text.Append("=");
                type = SymbolType.Equals;
                this.codeReader.ReadNext();

                character = this.codeReader.Peek();
                if (character == '=')
                {
                    text.Append("=");
                    type = SymbolType.ConditionalEquals;
                    this.codeReader.ReadNext();
                }
                else if (character == '>')
                {
                    text.Append(">");
                    type = SymbolType.Lambda;
                    this.codeReader.ReadNext();
                }
            }
            else if (character == '<')
            {
                text.Append("<");
                type = SymbolType.LessThan;
                this.codeReader.ReadNext();

                character = this.codeReader.Peek();
                if (character == '=')
                {
                    text.Append("=");
                    type = SymbolType.LessThanOrEquals;
                    this.codeReader.ReadNext();
                }
                else if (character == '<')
                {
                    text.Append("<");
                    type = SymbolType.LeftShift;
                    this.codeReader.ReadNext();

                    character = this.codeReader.Peek();
                    if (character == '=')
                    {
                        text.Append("=");
                        type = SymbolType.LeftShiftEquals;
                        this.codeReader.ReadNext();
                    }
                }
            }
            else if (character == '>')
            {
                text.Append(">");
                type = SymbolType.GreaterThan;
                this.codeReader.ReadNext();

                character = this.codeReader.Peek();
                if (character == '=')
                {
                    text.Append("=");
                    type = SymbolType.GreaterThanOrEquals;
                    this.codeReader.ReadNext();
                }

                // Note: The right-shift symbol confuses the parsing of generics. 
                // If there are two greater-thans in a row then this may be a right-shift
                // symbol, but we cannot create it as such right now because it may also
                // be a couple of closing generic symbols in a row. This will have to be 
                // parsed out in the code. If this is a right-shift-equals then this will 
                // be created as three separate symbols, two greater-thans and then an 
                // equals. Later on we will recombine these.
            }
            else if (character == '?')
            {
                text.Append("?");
                type = SymbolType.QuestionMark;
                this.codeReader.ReadNext();

                character = this.codeReader.Peek();
                if (character == '?')
                {
                    text.Append("?");
                    type = SymbolType.NullCoalescingSymbol;
                    this.codeReader.ReadNext();
                }
            }
            else if (character == ':')
            {
                text.Append(":");
                type = SymbolType.Colon;
                this.codeReader.ReadNext();

                character = this.codeReader.Peek();
                if (character == ':')
                {
                    text.Append(":");
                    type = SymbolType.QualifiedAlias;
                    this.codeReader.ReadNext();
                }
            }

            // Make sure we have a symbol now.
            if (text == null || text.Length == 0)
            {
                throw new SyntaxException(this.source, this.marker.LineNumber);
            }

            // Create the code location.
            var location = new CodeLocation(
                this.marker.Index,
                this.marker.Index + text.Length - 1,
                this.marker.IndexOnLine,
                this.marker.IndexOnLine + text.Length - 1,
                this.marker.LineNumber,
                this.marker.LineNumber);

            // Create the token.
            var symbol = new Symbol(text.ToString(), type, location);

            // Update the marker.
            this.marker.Index += text.Length;
            this.marker.IndexOnLine += text.Length;

            // Return the symbol.
            return symbol;
        }
        /// <summary>
        /// Extracts the body of the given preprocessor directive symbol, parses it, and returns the parsed expression.
        /// </summary>
        /// <param name="document">The parent document.</param>
        /// <param name="code">The source code.</param>
        /// <param name="parentProxy">Represents the parent item.</param>
        /// <param name="languageService">The C# language service.</param>
        /// <param name="preprocessorDefinitions">Optional preprocessor definitions.</param>
        /// <param name="preprocessorSymbol">The preprocessor directive symbol.</param>
        /// <param name="startIndex">The index of the start of the expression body within the text string.</param>
        /// <returns>Returns the expression.</returns>
        internal static Expression GetConditionalPreprocessorBodyExpression(
            CsDocument document, 
            Code code, 
            CodeUnitProxy parentProxy, 
            CsLanguageService languageService, 
            IDictionary<string, object> preprocessorDefinitions,
            Symbol preprocessorSymbol, 
            int startIndex)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(code, "code");
            Param.AssertNotNull(parentProxy, "parentProxy");
            Param.AssertNotNull(languageService, "languageService");
            Param.Ignore(preprocessorDefinitions);
            Param.AssertNotNull(preprocessorSymbol, "preprocessorSymbol");
            Param.AssertGreaterThanOrEqualToZero(startIndex, "startIndex");
            CsLanguageService.Debug.Assert(preprocessorSymbol.SymbolType == SymbolType.PreprocessorDirective, "The symbol is not a preprocessor directive.");

            string text = preprocessorSymbol.Text.Substring(startIndex, preprocessorSymbol.Text.Length - startIndex).TrimEnd(null);
            if (text.Length > 0)
            {
                // Trim off the whitespace at the beginning and advance the start index.
                int trimIndex = 0;
                for (int i = 0; i < text.Length; ++i)
                {
                    if (char.IsWhiteSpace(text[i]))
                    {
                        ++trimIndex;
                    }
                    else
                    {
                        break;
                    }
                }

                if (trimIndex > 0)
                {
                    text = text.Substring(trimIndex, text.Length - trimIndex);
                    startIndex += trimIndex;
                }

                if (text.Length > 0)
                {
                    // Extract the symbols within this text.
                    Code preprocessorCode = new Code(text, "Preprocessor", "Preprocessor");
                    
                    var lexer = new CodeLexer(
                        languageService,
                        preprocessorCode,
                        new CodeReader(preprocessorCode),
                        preprocessorSymbol.Location.StartPoint.Index + startIndex,
                        preprocessorSymbol.Location.StartPoint.IndexOnLine + startIndex,
                        preprocessorSymbol.Location.StartPoint.LineNumber);

                    List<Symbol> symbolList = lexer.GetSymbols(document, null);
                    var directiveSymbols = new SymbolManager(symbolList);

                    var preprocessorBodyParser = new CodeParser(languageService, document, directiveSymbols, preprocessorDefinitions);

                    // Parse these symbols to create the body expression.
                    return preprocessorBodyParser.GetNextConditionalPreprocessorExpression(document, parentProxy);
                }
            }

            // The directive has no body.
            return null;
        }
Example #3
0
        /// <summary>
        /// Gets an undefine preprocessor directive from the code.
        /// </summary>
        /// <param name="document">The parent document.</param>
        /// <param name="preprocessorSymbol">The preprocessor symbol being parsed.</param>
        /// <param name="startIndex">The start index within the symbols.</param>
        /// <param name="preprocessorDefinitions">Optional preprocessor definitions.</param>
        private void GetUndefinePreprocessorDirective(CsDocument document, Symbol preprocessorSymbol, int startIndex, IDictionary<string, object> preprocessorDefinitions)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(preprocessorSymbol, "preprocessorSymbol");
            Param.AssertGreaterThanOrEqualToZero(startIndex, "startIndex");
            Param.Ignore(preprocessorDefinitions);

            var expressionProxy = new CodeUnitProxy(document);

            // Get the body of the undefine directive.
            LiteralExpression body = CodeParser.GetConditionalPreprocessorBodyExpression(
                document, this.source, expressionProxy, this.languageService, preprocessorDefinitions, preprocessorSymbol, startIndex) as LiteralExpression;
            if (body == null)
            {
                throw new SyntaxException(document, preprocessorSymbol.LineNumber);
            }

            // Create the undefines list if necessary.
            if (this.undefines == null)
            {
                this.undefines = new Dictionary<string, string>();
            }

            // Add the item to the list.
            this.undefines.Add(body.Text, body.Text);

            // Remove the item from the defines list if it exists.
            if (this.defines != null)
            {
                this.defines.Remove(body.Text);
            }
        }
        /// <summary>
        /// Peeks ahead to the next non-Token symbol, without moving the index.
        /// </summary>
        /// <param name="symbol">The current symbol.</param>
        /// <returns>Gets the next non-Token symbol.</returns>
        private LexicalElement PeekNonTokenSymbol(Symbol symbol)
        {
            Param.AssertNotNull(symbol, "symbol");

            if (symbol.SymbolType == SymbolType.WhiteSpace)
            {
                return new Whitespace(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
            }
            else if (symbol.SymbolType == SymbolType.EndOfLine)
            {
                return new EndOfLine(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
            }
            else if (symbol.SymbolType == SymbolType.SingleLineComment)
            {
                return new SingleLineComment(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
            }
            else if (symbol.SymbolType == SymbolType.MultiLineComment)
            {
                return new MultilineComment(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
            }
            else if (symbol.SymbolType == SymbolType.PreprocessorDirective)
            {
                return this.PeekPreprocessorDirective(symbol, this.symbols.Generated);
            }
            else if (symbol.SymbolType == SymbolType.SkippedSection)
            {
                return new SkippedSection(this.document, symbol.Location, this.symbols.Generated, symbol.Text);
            }

            return null;
        }
        private static bool GetOperatorType(Symbol symbol, out OperatorType type, out OperatorCategory category)
        {
            Param.AssertNotNull(symbol, "symbol");

            bool isOperator = true;

            switch (symbol.SymbolType)
            {
                case SymbolType.LogicalAnd:
                    type = OperatorType.LogicalAnd;
                    category = OperatorCategory.Logical;
                    break;
                case SymbolType.LogicalOr:
                    type = OperatorType.LogicalOr;
                    category = OperatorCategory.Logical;
                    break;
                case SymbolType.LogicalXor:
                    type = OperatorType.LogicalXor;
                    category = OperatorCategory.Logical;
                    break;
                case SymbolType.ConditionalAnd:
                    type = OperatorType.ConditionalAnd;
                    category = OperatorCategory.Logical;
                    break;
                case SymbolType.ConditionalOr:
                    type = OperatorType.ConditionalOr;
                    category = OperatorCategory.Logical;
                    break;
                case SymbolType.NullCoalescingSymbol:
                    type = OperatorType.NullCoalescingSymbol;
                    category = OperatorCategory.Logical;
                    break;
                case SymbolType.Equals:
                    type = OperatorType.Equals;
                    category = OperatorCategory.Assignment;
                    break;
                case SymbolType.AndEquals:
                    type = OperatorType.AndEquals;
                    category = OperatorCategory.Assignment;
                    break;
                case SymbolType.OrEquals:
                    type = OperatorType.OrEquals;
                    category = OperatorCategory.Assignment;
                    break;
                case SymbolType.PlusEquals:
                    type = OperatorType.PlusEquals;
                    category = OperatorCategory.Assignment;
                    break;
                case SymbolType.MinusEquals:
                    type = OperatorType.MinusEquals;
                    category = OperatorCategory.Assignment;
                    break;
                case SymbolType.MultiplicationEquals:
                    type = OperatorType.MultiplicationEquals;
                    category = OperatorCategory.Assignment;
                    break;
                case SymbolType.DivisionEquals:
                    type = OperatorType.DivisionEquals;
                    category = OperatorCategory.Assignment;
                    break;
                case SymbolType.ModEquals:
                    type = OperatorType.ModEquals;
                    category = OperatorCategory.Assignment;
                    break;
                case SymbolType.XorEquals:
                    type = OperatorType.XorEquals;
                    category = OperatorCategory.Assignment;
                    break;
                case SymbolType.LeftShiftEquals:
                    type = OperatorType.LeftShiftEquals;
                    category = OperatorCategory.Assignment;
                    break;
                case SymbolType.RightShiftEquals:
                    type = OperatorType.RightShiftEquals;
                    category = OperatorCategory.Assignment;
                    break;
                case SymbolType.ConditionalEquals:
                    type = OperatorType.ConditionalEquals;
                    category = OperatorCategory.Relational;
                    break;
                case SymbolType.NotEquals:
                    type = OperatorType.NotEquals;
                    category = OperatorCategory.Relational;
                    break;
                case SymbolType.LessThan:
                    type = OperatorType.LessThan;
                    category = OperatorCategory.Relational;
                    break;
                case SymbolType.GreaterThan:
                    type = OperatorType.GreaterThan;
                    category = OperatorCategory.Relational;
                    break;
                case SymbolType.LessThanOrEquals:
                    type = OperatorType.LessThanOrEquals;
                    category = OperatorCategory.Relational;
                    break;
                case SymbolType.GreaterThanOrEquals:
                    type = OperatorType.GreaterThanOrEquals;
                    category = OperatorCategory.Relational;
                    break;
                case SymbolType.Plus:
                    type = OperatorType.Plus;
                    category = OperatorCategory.Arithmetic;
                    break;
                case SymbolType.Minus:
                    type = OperatorType.Minus;
                    category = OperatorCategory.Arithmetic;
                    break;
                case SymbolType.Multiplication:
                    type = OperatorType.Multiplication;
                    category = OperatorCategory.Arithmetic;
                    break;
                case SymbolType.Division:
                    type = OperatorType.Division;
                    category = OperatorCategory.Arithmetic;
                    break;
                case SymbolType.Mod:
                    type = OperatorType.Mod;
                    category = OperatorCategory.Arithmetic;
                    break;
                case SymbolType.LeftShift:
                    type = OperatorType.LeftShift;
                    category = OperatorCategory.Shift;
                    break;
                case SymbolType.RightShift:
                    type = OperatorType.RightShift;
                    category = OperatorCategory.Shift;
                    break;
                case SymbolType.Increment:
                    type = OperatorType.Increment;
                    category = OperatorCategory.IncrementDecrement;
                    break;
                case SymbolType.Decrement:
                    type = OperatorType.Decrement;
                    category = OperatorCategory.IncrementDecrement;
                    break;
                case SymbolType.QuestionMark:
                    type = OperatorType.ConditionalQuestionMark;
                    category = OperatorCategory.Conditional;
                    break;
                case SymbolType.Colon:
                    type = OperatorType.ConditionalColon;
                    category = OperatorCategory.Conditional;
                    break;
                case SymbolType.Pointer:
                    type = OperatorType.Pointer;
                    category = OperatorCategory.Reference;
                    break;
                case SymbolType.Dot:
                    type = OperatorType.MemberAccess;
                    category = OperatorCategory.Reference;
                    break;
                case SymbolType.QualifiedAlias:
                    type = OperatorType.QualifiedAlias;
                    category = OperatorCategory.Reference;
                    break;
                case SymbolType.Not:
                    type = OperatorType.Not;
                    category = OperatorCategory.Unary;
                    break;
                case SymbolType.Tilde:
                    type = OperatorType.BitwiseComplement;
                    category = OperatorCategory.Unary;
                    break;
                case SymbolType.Lambda:
                    type = OperatorType.Lambda;
                    category = OperatorCategory.Lambda;
                    break;
                default:
                    // Assign random values.
                    type = OperatorType.AddressOf;
                    category = OperatorCategory.Arithmetic;

                    // Signal that the symbol is not an operator.
                    isOperator = false;
                    break;
            }

            return isOperator;
        }
Example #6
0
        /// <summary>
        /// Gets an unknown symbol type.
        /// </summary>
        /// <param name="sourceCode">The source code containing the symbols.</param>
        /// <returns>Returns the item.</returns>
        private Symbol GetOtherSymbol(Code sourceCode)
        {
            Param.AssertNotNull(sourceCode, "sourceCode");

            var text = new StringBuilder();
            this.ReadToEndOfOtherSymbol(text);
            if (text.Length == 0)
            {
                throw new SyntaxException(sourceCode, 1);
            }

            string symbolText = text.ToString();

            // Get the token location.
            var location = new CodeLocation(
                this.marker.Index,
                this.marker.Index + text.Length - 1,
                this.marker.IndexOnLine,
                this.marker.IndexOnLine + text.Length - 1,
                this.marker.LineNumber,
                this.marker.LineNumber);

            // Create the symbol.
            var symbol = new Symbol(
                symbolText,
                CodeLexer.GetOtherSymbolType(symbolText),
                location);

            // Reset the marker index.
            this.marker.Index += text.Length;
            this.marker.IndexOnLine += text.Length;

            // Return the symbol.
            return symbol;
        }
Example #7
0
        /// <summary>
        /// Combines a range of symbols into a single symbol.
        /// </summary>
        /// <param name="startIndex">The start peek index of the first symbol to combine.</param>
        /// <param name="endIndex">The end peek index of the last symbol to combine.</param>
        /// <param name="text">The text for the new symbol.</param>
        /// <param name="type">The type of the new symbol.</param>
        public void Combine(int startIndex, int endIndex, string text, SymbolType type)
        {
            Param.AssertGreaterThanOrEqualToZero(startIndex, "startIndex");
            Param.AssertGreaterThanOrEqualTo(endIndex, startIndex, "endIndex");
            Param.AssertValidString(text, "text");
            Param.Ignore(type);

            // Adjust the indexes.
            int adjustedStartIndex = startIndex + this.index;
            int adjustedEndIndex = endIndex + this.index;

            CsLanguageService.Debug.Assert(adjustedStartIndex >= 0 && adjustedStartIndex < this.symbols.Count, "The adjusted start index should be within the symbol list");
            CsLanguageService.Debug.Assert(adjustedEndIndex >= 0 && adjustedEndIndex < this.symbols.Count, "The adjusted end index should be within the symbol list");

            // Map the new location of the combined symbol.
            CodeLocation location = CodeLocation.Join(
                this.symbols[adjustedStartIndex].Location, this.symbols[adjustedEndIndex].Location);

            // Create the new symbol.
            var symbol = new Symbol(text, type, location);

            // Replace the first symbol.
            this.symbols[adjustedStartIndex] = symbol;

            // Remove the rest of the symbols.
            ++adjustedStartIndex;
            if (adjustedStartIndex <= adjustedEndIndex)
            {
                this.symbols.RemoveRange(adjustedStartIndex, adjustedEndIndex - adjustedStartIndex + 1);
            }
        }
Example #8
0
        /// <summary>
        /// Gets the next string from the code.
        /// </summary>
        /// <returns>Returns the string.</returns>
        private Symbol GetString()
        {
            var text = new StringBuilder();

            // Read the opening quote character and add it to the string.
            char quoteType = this.codeReader.ReadNext();
            CsLanguageService.Debug.Assert(quoteType == '\'' || quoteType == '\"', "Expected a quote character");
            text.Append(quoteType);
            
            bool slash = false;

            // Read through to the end of the string.
            while (true)
            {
                char character = this.codeReader.Peek();
                if (character == char.MinValue || (character == quoteType && !slash))
                {
                    // This is the end of the string. Add the character and quit.
                    text.Append(character);
                    this.codeReader.ReadNext();
                    break;
                }

                if (character == '\\')
                {
                    slash = !slash;
                }
                else
                {
                    slash = false;

                    if (character == '\r' || character == '\n')
                    {
                        // We've hit the end of the line. Just exit.
                        break;
                    }
                }

                text.Append(character);

                // Advance past this character.
                this.codeReader.ReadNext();
            }

            // Create the code location.
            var location = new CodeLocation(
                this.marker.Index,
                this.marker.Index + text.Length - 1,
                this.marker.IndexOnLine,
                this.marker.IndexOnLine + text.Length - 1,
                this.marker.LineNumber,
                this.marker.LineNumber);

            // Create the symbol.
            var symbol = new Symbol(text.ToString(), SymbolType.String, location);

            // Update the marker.
            this.marker.Index += text.Length;
            this.marker.IndexOnLine += text.Length;

            // Return the symbol.
            return symbol;
        }
Example #9
0
        /// <summary>
        /// Gets the next literal string from the code.
        /// </summary>
        /// <param name="text">The text buffer to add the string text to.</param>
        /// <returns>Returns the literal string.</returns>
        private Symbol GetLiteralString(StringBuilder text)
        {
            Param.AssertNotNull(text, "text");
            CsLanguageService.Debug.Assert(text.Length == 1 && text[0] == '@', "Expected an @ symbol");

            // Initialize the location of the start of the string.
            int startIndex = this.marker.Index;
            int endIndex = this.marker.Index;
            int startIndexOnLine = this.marker.IndexOnLine;
            int endIndexOnLine = this.marker.IndexOnLine;
            int lineNumber = this.marker.LineNumber;
            int endLineNumber = this.marker.LineNumber;

            // Get the opening string character to determine what type of string this is.
            char stringType = this.codeReader.Peek();
            CsLanguageService.Debug.Assert(stringType == '\'' || stringType == '\"', "Expected a quote character");

            // Add the opening quote character and move past it.
            text.Append(stringType);
            this.codeReader.ReadNext();

            // Advance the end indexes past the literal character and the open quote character.
            endIndex += 2;
            endIndexOnLine += 2;

            while (true)
            {
                char character = this.codeReader.Peek();
                if (character == stringType)
                {
                    // Read the character and add it to the text buffer.
                    this.codeReader.ReadNext();
                    text.Append(character);
                    ++endIndex;
                    ++endIndexOnLine;

                    // If the next character is also the same string type, then this is internal to the string.
                    character = this.codeReader.Peek();
                    if (character == stringType)
                    {
                        // Also move past this character and add it.
                        this.codeReader.ReadNext();
                        text.Append(character);

                        ++endIndex;
                        ++endIndexOnLine;
                        continue;
                    }
                    else
                    {
                        // This is the end of the string. We're done now.
                        break;
                    }
                }
                else if (character == '\r' || character == '\n')
                {
                    if (stringType == '\'')
                    {
                        // This is a syntax error in the code as single-quoted literal strings
                        // cannot allowed to span across multiple lines, although double-quoted 
                        // strings can.
                        throw new SyntaxException(this.source, this.marker.LineNumber);
                    }
                    else if (character == '\n')
                    {
                        ++endLineNumber;
                        endIndexOnLine = -1;
                    }
                    else if (character == '\r')
                    {
                        // Just move past this character without adding it.
                        this.codeReader.ReadNext();
                        continue;
                    }
                }

                this.codeReader.ReadNext();
                text.Append(character);
                ++endIndex;
                ++endIndexOnLine;
            }

            // Make sure the end index is correct now.
            if (text.Length <= 2 || text[text.Length - 1] != stringType)
            {
                throw new SyntaxException(this.source, this.marker.LineNumber);
            }

            // Create the location object.
            var location = new CodeLocation(
                startIndex, endIndex, startIndexOnLine, endIndexOnLine, lineNumber, endLineNumber);

            // Create the symbol.
            var token = new Symbol(text.ToString(), SymbolType.String, location);

            // Update the marker.
            this.marker.Index = endIndex + 1;
            this.marker.IndexOnLine = endIndexOnLine + 1;
            this.marker.LineNumber = endLineNumber;

            // Return the token.
            return token;
        }
Example #10
0
        private Symbol GetNewLine()
        {
            Symbol symbol = null;

            char character = this.codeReader.Peek();
            if (character != char.MinValue)
            {
                // Get the character
                this.codeReader.ReadNext();

                // Save the original start and end indexes of the newline character.
                int startIndex = this.marker.Index;
                int endIndex = this.marker.Index;

                // Check if this is an \r\n sequence in which case we need to adjust the end index.
                if (character == '\r')
                {
                    character = this.codeReader.Peek();
                    if (character == '\n')
                    {
                        this.codeReader.ReadNext();
                        ++this.marker.Index;
                        ++endIndex;
                    }
                }

                // Create the code location.
                var location = new CodeLocation(
                    startIndex,
                    endIndex,
                    this.marker.IndexOnLine,
                    this.marker.IndexOnLine + (endIndex - startIndex),
                    this.marker.LineNumber,
                    this.marker.LineNumber);

                // Create the symbol.
                symbol = new Symbol("\n", SymbolType.EndOfLine, location);

                // Update the marker.
                ++this.marker.Index;
                ++this.marker.LineNumber;
                this.marker.IndexOnLine = 0;
            }

            return symbol;
        }
Example #11
0
        /// <summary>
        /// Gets the next whitespace stream.
        /// </summary>
        /// <returns>Returns the whitespace.</returns>
        private Symbol GetWhitespace()
        {
            var text = new StringBuilder();

            // Get all of the characters in the whitespace.
            while (true)
            {
                char character = this.codeReader.Peek();
                if (character == char.MinValue || (character != ' ' && character != '\t'))
                {
                    break;
                }

                text.Append(character);
                
                // Advance past this character.
                this.codeReader.ReadNext();
            }

            // Create the whitespace location object.
            var location = new CodeLocation(
                this.marker.Index,
                this.marker.Index + text.Length - 1,
                this.marker.IndexOnLine,
                this.marker.IndexOnLine + text.Length - 1,
                this.marker.LineNumber,
                this.marker.LineNumber);

            // Create the whitespace object.
            var whitespace = new Symbol(text.ToString(), SymbolType.WhiteSpace, location);

            // Update the marker.
            this.marker.Index += text.Length;
            this.marker.IndexOnLine += text.Length;

            // Return the whitespace object.
            return whitespace;
        }
Example #12
0
        /// <summary>
        /// Gets the next conditional compilation directive from the code.
        /// </summary>
        /// <param name="preprocessorSymbol">The symbol representing the directive.</param>
        /// <param name="type">The type of the conditional compilation directive.</param>
        /// <param name="startIndex">The start index of the body of the directive.</param>
        /// <returns>Returns the directive.</returns>
        private ConditionalCompilationDirective GetConditionalCompilationDirective(Symbol preprocessorSymbol, PreprocessorType type, int startIndex)
        {
            Param.AssertNotNull(preprocessorSymbol, "preprocessorSymbol");
            Param.Ignore(type);
            Param.AssertGreaterThanOrEqualToZero(startIndex, "startIndex");

            Expression body = null;

            var directiveProxy = new CodeUnitProxy(this.document);

            // Extract the body of the directive if necessary.
            if (type != PreprocessorType.Endif && startIndex < preprocessorSymbol.Text.Length)
            {
                body = CodeParser.GetConditionalPreprocessorBodyExpression(
                    this.document, this.lexer.SourceCode, directiveProxy, this.languageService, this.preprocessorDefinitions, preprocessorSymbol, startIndex);
            }

            // Create and return the directive.
            switch (type)
            {
                case PreprocessorType.If:
                    return new IfDirective(preprocessorSymbol.Text, directiveProxy, body);
                case PreprocessorType.Elif:
                    return new ElifDirective(preprocessorSymbol.Text, directiveProxy, body);
                case PreprocessorType.Else:
                    return new ElseDirective(preprocessorSymbol.Text, directiveProxy, body);
                case PreprocessorType.Endif:
                    return new EndifDirective(preprocessorSymbol.Text, directiveProxy, body);
                default:
                    CsLanguageService.Debug.Fail("Not a conditional preprocessor type.");
                    return null;
            }
        }
Example #13
0
        /// <summary>
        /// Gets and converts preprocessor directive.
        /// </summary>
        /// <param name="preprocessorSymbol">The preprocessor symbol.</param>
        /// <param name="generated">Indicates whether the preprocessor directive lies within a block of generated code.</param>
        /// <returns>Returns the preprocessor directive.</returns>
        private PreprocessorDirective PeekPreprocessorDirective(Symbol preprocessorSymbol, bool generated)
        {
            Param.AssertNotNull(preprocessorSymbol, "preprocessorSymbol");
            Param.Ignore(generated);

            CsLanguageService.Debug.Assert(preprocessorSymbol != null && preprocessorSymbol.SymbolType == SymbolType.PreprocessorDirective, "Expected a preprocessor directive");

            // Get the type of the preprocessor directive.
            int bodyIndex;
            string type = CsLanguageService.GetPreprocessorDirectiveType(preprocessorSymbol, out bodyIndex);
            if (type == null)
            {
                throw new SyntaxException(this.document, preprocessorSymbol.LineNumber);
            }

            // Create the correct preprocessor object type.
            PreprocessorDirective preprocessor = null;
            if (type == "region")
            {
                var region = new RegionDirective(this.document, preprocessorSymbol.Text, preprocessorSymbol.Location, generated);
                this.symbols.PushRegion(region);
                preprocessor = region;
            }
            else if (type == "endregion")
            {
                var endregion = new EndRegionDirective(this.document, preprocessorSymbol.Text, preprocessorSymbol.Location, generated);
                RegionDirective startregion = this.symbols.PopRegion();

                if (startregion == null)
                {
                    throw new SyntaxException(this.document, preprocessorSymbol.LineNumber);
                }

                startregion.Partner = endregion;
                endregion.Partner = startregion;

                preprocessor = endregion;
            }
            else if (type == "if")
            {
                preprocessor = this.GetConditionalCompilationDirective(preprocessorSymbol, PreprocessorType.If, bodyIndex);
            }
            else if (type == "elif")
            {
                preprocessor = this.GetConditionalCompilationDirective(preprocessorSymbol, PreprocessorType.Elif, bodyIndex);
            }
            else if (type == "else")
            {
                preprocessor = this.GetConditionalCompilationDirective(preprocessorSymbol, PreprocessorType.Else, bodyIndex);
            }
            else if (type == "endif")
            {
                preprocessor = this.GetConditionalCompilationDirective(preprocessorSymbol, PreprocessorType.Endif, bodyIndex);
            }
            else if (type == "pragma")
            {
                preprocessor = new PragmaDirective(this.document, preprocessorSymbol.Text, preprocessorSymbol.Location, generated);
            }
            else if (type == "define")
            {
                preprocessor = new DefineDirective(this.document, preprocessorSymbol.Text, preprocessorSymbol.Location, generated);
            }
            else if (type == "undef")
            {
                preprocessor = new UndefDirective(this.document, preprocessorSymbol.Text, preprocessorSymbol.Location, generated);
            }
            else if (type == "line")
            {
                preprocessor = new LineDirective(this.document, preprocessorSymbol.Text, preprocessorSymbol.Location, generated);
            }
            else if (type == "error")
            {
                preprocessor = new ErrorDirective(this.document, preprocessorSymbol.Text, preprocessorSymbol.Location, generated);
            }
            else if (type == "warning")
            {
                preprocessor = new WarningDirective(this.document, preprocessorSymbol.Text, preprocessorSymbol.Location, generated);
            }
            else
            {
                throw this.CreateSyntaxException();                
            }

            return preprocessor;
        }
Example #14
0
        /// <summary>
        /// Gets and converts preprocessor directive.
        /// </summary>
        /// <param name="parentProxy">Represents the parent of the token.</param>
        /// <param name="preprocessorSymbol">The preprocessor symbol.</param>
        /// <param name="generated">Indicates whether the preprocessor directive lies within a block of generated code.</param>
        /// <returns>Returns the preprocessor directive.</returns>
        private PreprocessorDirective GetPreprocessorDirective(CodeUnitProxy parentProxy, Symbol preprocessorSymbol, bool generated)
        {
            Param.Ignore(parentProxy);
            Param.AssertNotNull(preprocessorSymbol, "preprocessorSymbol");
            Param.Ignore(generated);

            PreprocessorDirective preprocessor = this.PeekPreprocessorDirective(preprocessorSymbol, generated);

            if (parentProxy != null)
            {
                parentProxy.Children.Add(preprocessor);
            }

            return preprocessor;
        }
Example #15
0
        /// <summary>
        /// Reads, creates, and moves past a symbol.
        /// </summary>
        /// <param name="text">The symbol text.</param>
        /// <param name="type">The type of the symbol.</param>
        /// <returns>Returns the symbol.</returns>
        private Symbol CreateAndMovePastSymbol(string text, SymbolType type)
        {
            Param.AssertValidString(text, "text");
            Param.Ignore(type);

            this.codeReader.ReadNext();
            Symbol symbol = new Symbol(text, type, CodeLocationFromMarker(this.marker));
            ++this.marker.Index;
            ++this.marker.IndexOnLine;

            return symbol;
        }
Example #16
0
        /// <summary>
        /// Gets the next literal keyword token from the code.
        /// </summary>
        /// <param name="text">The text buffer to add the string text to.</param>
        /// <returns>Returns the literal keyword token.</returns>
        private Symbol GetLiteralKeyword(StringBuilder text)
        {
            Param.AssertNotNull(text, "text");
            CsLanguageService.Debug.Assert(text.Length > 0 && text[0] == '@', "Expected an @ character");

            // Advance to the end of the token.
            this.ReadToEndOfOtherSymbol(text);
            if (text.Length == 1)
            {
                // Nothing was read.
                throw new SyntaxException(this.source, this.marker.LineNumber);
            }

            // Get the token location.
            var location = new CodeLocation(
                this.marker.Index,
                this.marker.Index + text.Length - 1,
                this.marker.IndexOnLine,
                this.marker.IndexOnLine + text.Length - 1,
                this.marker.LineNumber,
                this.marker.LineNumber);

            // Create the symbol.
            var symbol = new Symbol(text.ToString(), SymbolType.Other, location);

            // Reset the marker index.
            this.marker.Index += text.Length;
            this.marker.IndexOnLine += text.Length;

            // Return the symbol.
            return symbol;
        }
Example #17
0
        /// <summary>
        /// Gets the next number.
        /// </summary>
        /// <returns>Returns the number.</returns>
        private Symbol GetNumber()
        {
            // The last index of the number.
            int endIndex = -1;

            // The first few characters in the number tell us the type of the number.
            char character = this.codeReader.Peek();
            if (character == '-' || character == '+')
            {
                // This could be a number starting with a negative or positive sign.
                // If that's true, the next character must be a digit between 0 and 9.
                character = this.codeReader.Peek(1);
                if (character >= '0' && character <= '9')
                {
                    endIndex = this.GetPositiveNumber(this.marker.Index + 1);
                }
            }
            else
            {
                // Get the body of the number.
                endIndex = this.GetPositiveNumber(this.marker.Index);
            }

            // Create the NumberSymbol now.
            Symbol number = null;

            // Make sure a number was found.
            if (endIndex >= this.marker.Index)
            {
                // Get the text string for this number.
                int length = endIndex - this.marker.Index + 1;
                string numberText = this.codeReader.ReadString(length);
                CsLanguageService.Debug.Assert(!string.IsNullOrEmpty(numberText), "The text should not be empty");

                // Create the location object.
                var location = new CodeLocation(
                    this.marker.Index,
                    this.marker.Index + length - 1,
                    this.marker.IndexOnLine,
                    this.marker.IndexOnLine + length - 1,
                    this.marker.LineNumber,
                    this.marker.LineNumber);

                number = new Symbol(numberText, SymbolType.Number, location);

                // Update the marker.
                this.marker.Index += length;
                this.marker.IndexOnLine += length;
            }

            return number;
        }
Example #18
0
        /// <summary>
        /// Gets the next multi-line comment.
        /// </summary>
        /// <param name="text">The buffer to add the text to.</param>
        /// <returns>Returns the comment.</returns>
        private Symbol GetMultiLineComment(StringBuilder text)
        {
            Param.AssertNotNull(text, "text");

            // Initialize the location of the start of the comment. Add one to the end indexes since we know the 
            // comment starts with /*, which is two characters long.
            int startIndex = this.marker.Index;
            int endIndex = this.marker.Index + 1;
            int startIndexOnLine = this.marker.IndexOnLine;
            int endIndexOnLine = this.marker.IndexOnLine + 1;
            int lineNumber = this.marker.LineNumber;
            int endLineNumber = this.marker.LineNumber;

            // Initialize loop trackers.
            bool asterisk = false;
            bool first = false;

            // Find the end of the comment.
            while (true)
            {
                char character = this.codeReader.Peek();
                if (character == char.MinValue)
                {
                    break;
                }

                // Add the character and move the index past it.
                text.Append(this.codeReader.ReadNext());

                if (asterisk && character == '/')
                {
                    // This is the end of the comment.
                    break;
                }
                else
                {
                    if (character == '*')
                    {
                        if (first)
                        {
                            // Mark the asterisk.
                            asterisk = true;
                        }
                        else
                        {
                            first = true;
                        }
                    }
                    else
                    {
                        // This is not an asterisk.
                        asterisk = false;

                        // Check for newlines.
                        if (character == '\n')
                        {
                            ++endLineNumber;
                            endIndexOnLine = -1;
                        }
                        else if (character == '\r')
                        {
                            // Peek at the next character and check the type.
                            character = this.codeReader.Peek();
                            if (character != '\n')
                            {
                                ++endLineNumber;
                                endIndexOnLine = -1;
                            }
                        }
                    }
                }

                ++endIndex;
                ++endIndexOnLine;
            }

            // Create the location object.
            var location = new CodeLocation(
                startIndex, endIndex, startIndexOnLine, endIndexOnLine, lineNumber, endLineNumber);

            // Create the symbol object.
            var symbol = new Symbol(text.ToString(), SymbolType.MultiLineComment, location);

            // Update the marker.
            this.marker.Index = endIndex + 1;
            this.marker.IndexOnLine = endIndexOnLine + 1;
            this.marker.LineNumber = endLineNumber;

            // Return the symbol.
            return symbol;
        }
Example #19
0
        /// <summary>
        /// Gets the type of the given preprocessor symbol.
        /// </summary>
        /// <param name="preprocessor">The preprocessor symbol.</param>
        /// <param name="bodyIndex">Returns the start index of the body of the preprocessor.</param>
        /// <returns>Returns the type or null if the type cannot be determined.</returns>
        internal static string GetPreprocessorDirectiveType(Symbol preprocessor, out int bodyIndex)
        {
            Param.AssertNotNull(preprocessor, "preprocessor");
            CsLanguageService.Debug.Assert(preprocessor.SymbolType == SymbolType.PreprocessorDirective, "Expected a preprocessor directive");

            // Get the preprocessor type. This is the second word in the statement.
            bodyIndex = -1;
            int startIndex = -1;
            int endIndex = -1;

            // Move to the start of the second word.
            for (int i = 1; i < preprocessor.Text.Length; ++i)
            {
                if (char.IsLetter(preprocessor.Text[i]))
                {
                    startIndex = i;
                    break;
                }
            }

            if (startIndex == -1)
            {
                return null;
            }

            // Move to the end of the word.
            for (endIndex = startIndex; endIndex < preprocessor.Text.Length; ++endIndex)
            {
                if (!char.IsLetter(preprocessor.Text[endIndex]))
                {
                    break;
                }
            }

            --endIndex;
            if (endIndex < startIndex)
            {
                return null;
            }

            // The body start index is just past the endIndex.
            bodyIndex = endIndex + 1;

            // Get the word.
            return preprocessor.Text.Substring(startIndex, endIndex - startIndex + 1);
        }
Example #20
0
        /// <summary>
        /// Gets the next Xml header line from the code.
        /// </summary>
        /// <param name="text">The buffer in which to store the text.</param>
        /// <returns>Returns the Xml header line.</returns>
        private Symbol GetXmlHeaderLine(StringBuilder text)
        {
            Param.AssertNotNull(text, "text");

            // Find the end of the current line.
            this.AdvanceToEndOfLine(text);

            // Create the code location.
            var location = new CodeLocation(
                this.marker.Index,
                this.marker.Index + text.Length - 1,
                this.marker.IndexOnLine,
                this.marker.IndexOnLine + text.Length - 1,
                this.marker.LineNumber,
                this.marker.LineNumber);

            // Create the symbol.
            var symbol = new Symbol(text.ToString(), SymbolType.XmlHeaderLine, location);

            // Update the marker.
            this.marker.Index += text.Length;
            this.marker.IndexOnLine += text.Length;

            // Return the symbol.
            return symbol;
        }
        /// <summary>
        /// Gets the next non-Token symbol.
        /// </summary>
        /// <param name="typeTokenProxy">Proxy object for the TypeToken being created.</param>
        /// <param name="symbol">The current symbol.</param>
        /// <returns>Returns the non-Token symbol.</returns>
        private bool GatherNonTokenSymbol(CodeUnitProxy typeTokenProxy, Symbol symbol)
        {
            Param.AssertNotNull(typeTokenProxy, "typeTokenProxy");
            Param.AssertNotNull(symbol, "symbol");

            LexicalElement item = this.PeekNonTokenSymbol(symbol);
            if (item != null)
            {
                typeTokenProxy.Children.Add(item);
                return true;
            }

            return false;
        }
Example #22
0
        /// <summary>
        /// Checks the given preprocessor symbol to determine whether it is a conditional preprocessor directive.
        /// If so, determines whether we should skip past code which is out of scope.
        /// </summary>
        /// <param name="document">The parent document.</param>
        /// <param name="preprocessorSymbol">The symbol to check.</param>
        /// <param name="preprocessorDefinitions">The active configuration.</param>
        /// <returns>Returns the collection of symbols found while processing the directive.</returns>
        private ICollection<Symbol> CheckForConditionalCompilationDirective(CsDocument document, Symbol preprocessorSymbol, IDictionary<string, object> preprocessorDefinitions)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(preprocessorSymbol, "preprocessorSymbol");
            Param.Ignore(preprocessorDefinitions);

            List<Symbol> symbols = new List<Symbol>();

            while (true)
            {
                // Get the type of this preprocessor directive.
                int bodyIndex;
                string type = CsLanguageService.GetPreprocessorDirectiveType(preprocessorSymbol, out bodyIndex);
                if (type == "define")
                {
                    this.GetDefinePreprocessorDirective(document, preprocessorSymbol, bodyIndex, preprocessorDefinitions);
                    break;
                }
                else if (type == "undef")
                {
                    this.GetUndefinePreprocessorDirective(document, preprocessorSymbol, bodyIndex, preprocessorDefinitions);
                    break;
                }
                else if (type == "endif")
                {
                    // Pop this conditional directive off of the stack.
                    if (this.conditionalDirectives.Count == 0)
                    {
                        throw new SyntaxException(document, preprocessorSymbol.LineNumber);
                    }

                    this.conditionalDirectives.Pop();
                    break;
                }
                else
                {
                    // Extract an if, endif, or else directive.
                    bool skip;
                    if (!this.GetIfElsePreprocessorDirectives(
                        document, preprocessorSymbol, preprocessorDefinitions, bodyIndex, type, out skip))
                    {
                        // Check whether the code needs to be skipped.
                        if (skip)
                        {
                            // We will skip all code between this conditional preprocessor symbol and the next one.
                            StringBuilder skippedSectionText = new StringBuilder();
                            CodeLocation startLocation = null;
                            CodeLocation endLocation = null;
                            Symbol endSymbol = null;
                            int subConditionalPreprocessorCount = 0;

                            while (true)
                            {
                                // Get the next symbol.
                                IList<Symbol> symbolList = this.GetSymbol(document, preprocessorDefinitions, false);
                                if (symbolList == null || symbolList.Count != 1)
                                {
                                    throw new SyntaxException(document, preprocessorSymbol.LineNumber);
                                }

                                Symbol symbol = symbolList[0];

                                // Check whether this is another preprocessor.
                                if (symbol.SymbolType == SymbolType.PreprocessorDirective)
                                {
                                    // Check to see if this is a conditional preprocessor symbol, which indicates that we have
                                    // reached the end of out-of-scope code.
                                    type = CsLanguageService.GetPreprocessorDirectiveType(symbol, out bodyIndex);
                                    if (type == "if")
                                    {
                                        ++subConditionalPreprocessorCount;
                                    }
                                    else if (subConditionalPreprocessorCount > 0 && type == "endif")
                                    {
                                        --subConditionalPreprocessorCount;
                                    }
                                    else if (subConditionalPreprocessorCount == 0 &&
                                        (type == "elif" || type == "else" || type == "endif"))
                                    {
                                        // Reset the markers to the start of this preprocessor symbol.
                                        this.marker.Index = symbol.Location.StartPoint.Index;
                                        this.marker.IndexOnLine = symbol.Location.StartPoint.IndexOnLine;
                                        this.marker.LineNumber = symbol.Location.StartPoint.LineNumber;

                                        // Break from this loop.
                                        endSymbol = symbol;
                                        break;
                                    }
                                }

                                skippedSectionText.Append(symbol.Text);
                                if (startLocation == null)
                                {
                                    startLocation = symbol.Location;
                                }

                                endLocation = symbol.Location;
                            }

                            if (skippedSectionText.Length > 0)
                            {
                                symbols.Add(new Symbol(skippedSectionText.ToString(), SymbolType.SkippedSection, CodeLocation.Join(startLocation, endLocation)));
                            }

                            if (endSymbol != null)
                            {
                                symbols.Add(endSymbol);
                                preprocessorSymbol = endSymbol;
                            }
                            else
                            {
                                break;
                            }
                        }
                        else
                        {
                            // Indicate that this conditional directive has been entered.
                            if (this.conditionalDirectives.Count == 0)
                            {
                                throw new SyntaxException(document, preprocessorSymbol.LineNumber);
                            }

                            this.conditionalDirectives.Pop();
                            this.conditionalDirectives.Push(true);

                            break;
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }

            return symbols;
        }
        private Token ConvertTokenSymbol(Symbol symbol, TokenType tokenType)
        {
            Param.AssertNotNull(symbol, "symbol");
            Param.Ignore(tokenType);

            switch (symbol.SymbolType)
            {
                case SymbolType.Abstract:
                    return new AbstractToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.As:
                    return new AsToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Base:
                    return new BaseToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Break:
                    return new BreakToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Case:
                    return new CaseToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Catch:
                    return new CatchToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Checked:
                    return new CheckedToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Class:
                    return new ClassToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.CloseCurlyBracket:
                    return new CloseCurlyBracketToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.CloseParenthesis:
                    return new CloseParenthesisToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.CloseSquareBracket:
                    return new CloseSquareBracketToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Colon:
                    switch (tokenType)
                    {
                        case TokenType.BaseColon:
                            return new BaseColonToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.LabelColon:
                            return new LabelColonToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.WhereColon:
                            return new WhereColonToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                    }

                    break;
                case SymbolType.Comma:
                    return new CommaToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Const:
                    return new ConstToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Continue:
                    return new ContinueToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Default:
                    if (tokenType == TokenType.DefaultValue)
                    {
                        return new DefaultValueToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                    }

                    return new DefaultToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Delegate:
                    return new DelegateToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Do:
                    return new DoToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Else:
                    return new ElseToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Enum:
                    return new EnumToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Equals:
                    if (tokenType == TokenType.Equals)
                    {
                        return new EqualsToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                    }

                    break;

                case SymbolType.Event:
                    return new EventToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Explicit:
                    return new ExplicitToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Extern:
                    if (tokenType == TokenType.ExternDirective)
                    {
                        return new ExternDirectiveToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                    }

                    return new ExternToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.False:
                    return new FalseToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Finally:
                    return new FinallyToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Fixed:
                    return new FixedToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.For:
                    return new ForToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Foreach:
                    return new ForeachToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Goto:
                    return new GotoToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.If:
                    return new IfToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Implicit:
                    return new ImplicitToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.In:
                    return new InToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Interface:
                    return new InterfaceToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Internal:
                    return new InternalToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Is:
                    return new IsToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Lock:
                    return new LockToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Namespace:
                    return new NamespaceToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.New:
                    return new NewToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Null:
                    return new NullToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Number:
                    return new NumberToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.OpenCurlyBracket:
                    return new OpenCurlyBracketToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.OpenParenthesis:
                    return new OpenParenthesisToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.OpenSquareBracket:
                    return new OpenSquareBracketToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Operator:
                    return new OperatorToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Other:
                    switch (tokenType)
                    {
                        case TokenType.Add:
                            return new AddToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Alias:
                            return new AliasToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Ascending:
                            return new AscendingToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.By:
                            return new ByToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Descending:
                            return new DescendingToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Equals:
                            return new EqualsToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.From:
                            return new FromToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Get:
                            return new GetToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Group:
                            return new GroupToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Into:
                            return new IntoToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Join:
                            return new JoinToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Let:
                            return new LetToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Literal:
                            return new LiteralToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.On:
                            return new OnToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.OrderBy:
                            return new OrderByToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Partial:
                            return new PartialToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Remove:
                            return new RemoveToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Select:
                            return new SelectToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Set:
                            return new SetToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Where:
                            return new WhereToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                        case TokenType.Yield:
                            return new YieldToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                    }

                    break;
                case SymbolType.Out:
                    return new OutToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Override:
                    return new OverrideToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Params:
                    return new ParamsToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Private:
                    return new PrivateToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Protected:
                    return new ProtectedToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Public:
                    return new PublicToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Readonly:
                    return new ReadonlyToken(this.document,  symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Ref:
                    return new RefToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Return:
                    return new ReturnToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Sealed:
                    return new SealedToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Semicolon:
                    return new SemicolonToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Sizeof:
                    return new SizeofToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Stackalloc:
                    return new StackallocToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Static:
                    return new StaticToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.String:
                    return new StringToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Struct:
                    return new StructToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Switch:
                    return new SwitchToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.This:
                    return new ThisToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Throw:
                    return new ThrowToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Tilde:
                    if (tokenType == TokenType.DestructorTilde)
                    {
                        return new DestructorTildeToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                    }

                    break;

                case SymbolType.True:
                    return new TrueToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Try:
                    return new TryToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Typeof:
                    return new TypeofToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Unchecked:
                    return new UncheckedToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Unsafe:
                    return new UnsafeToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Using:
                    if (tokenType == TokenType.UsingDirective)
                    {
                        return new UsingDirectiveToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                    }

                    return new UsingToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Virtual:
                    return new VirtualToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.Volatile:
                    return new VolatileToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                case SymbolType.While:
                    if (tokenType == TokenType.WhileDo)
                    {
                        return new WhileDoToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
                    }

                    return new WhileToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated);
            }

            CsLanguageService.Debug.Fail("Cannot create a token of the given symbol type using this method.");
            return null;
        }
Example #24
0
        /// <summary>
        /// Extracts an if, endif, or else directive.
        /// </summary>
        /// <param name="document">The parent document.</param>
        /// <param name="preprocessorSymbol">The preprocessor symbol being parsed.</param>
        /// <param name="preprocessorDefinitions">The current code configuration.</param>
        /// <param name="startIndex">The start index of the item within the symbols.</param>
        /// <param name="type">The type of the preprocessor symbol.</param>
        /// <param name="skip">Returns a value indicating whether the item should be skipped.</param>
        /// <returns>Returns a value indicating whether to ignore the item.</returns>
        private bool GetIfElsePreprocessorDirectives(
            CsDocument document, Symbol preprocessorSymbol, IDictionary<string, object> preprocessorDefinitions, int startIndex, string type, out bool skip)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(preprocessorSymbol, "preprocessorSymbol");
            Param.AssertNotNull(preprocessorDefinitions, "preprocessorDefinitions");
            Param.AssertGreaterThanOrEqualToZero(startIndex, "startIndex");
            Param.AssertValidString(type, "type");

            bool ignore = false;

            skip = false;
            if (type == "if")
            {
                // Add this directive to the stack and indicate that it has not been entered.
                this.conditionalDirectives.Push(false);

                // Extract the body of the directive.
                var expressionProxy = new CodeUnitProxy(document);
                Expression body = CodeParser.GetConditionalPreprocessorBodyExpression(
                    document, this.source, expressionProxy, this.languageService, preprocessorDefinitions, preprocessorSymbol, startIndex);
                if (body == null)
                {
                    throw new SyntaxException(document, preprocessorSymbol.LineNumber);
                }

                // Determine whether the code under this directive needs to be skipped because it is out of scope.
                skip = !this.EvaluateConditionalDirectiveExpression(document, body, preprocessorDefinitions);
            }
            else if (type == "elif")
            {
                if (this.conditionalDirectives.Count == 0)
                {
                    throw new SyntaxException(document, preprocessorSymbol.LineNumber);
                }

                bool entered = this.conditionalDirectives.Peek();
                if (entered)
                {
                    skip = true;
                }
                else
                {
                    // Extract the body of the directive.
                    var expressionProxy = new CodeUnitProxy(document);
                    Expression body = CodeParser.GetConditionalPreprocessorBodyExpression(
                        document, this.source, expressionProxy, this.languageService, preprocessorDefinitions, preprocessorSymbol, startIndex);
                    if (body != null)
                    {
                        // Determine whether the code under this directive needs to be skipped because it is out of scope.
                        skip = !this.EvaluateConditionalDirectiveExpression(document, body, preprocessorDefinitions);
                    }
                }
            }
            else if (type == "else")
            {
                if (this.conditionalDirectives.Count == 0)
                {
                    throw new SyntaxException(document, preprocessorSymbol.LineNumber);
                }

                bool entered = this.conditionalDirectives.Peek();
                if (entered)
                {
                    skip = true;
                }
            }
            else
            {
                // This is not a conditional preprocessor directive.
                ignore = true;
            }

            return ignore;
        }
        private OperatorSymbolToken CreateOperatorSymbolToken(Symbol symbol, OperatorType? hint, bool generated)
        {
            Param.AssertNotNull(symbol, "symbol");
            Param.Ignore(hint);
            Param.Ignore(generated);

            // Get the type of the operator.
            OperatorType type;
            OperatorCategory category;
            if (!GetOperatorType(symbol, out type, out category))
            {
                // This should never happen unless there is a bug in the code.
                CsLanguageService.Debug.Fail("Unexpected operator type");
                throw new InvalidOperationException();
            }

            if (hint != null)
            {
                if (hint == OperatorType.Dereference && type == OperatorType.Multiplication)
                {
                    type = OperatorType.Dereference;
                    category = OperatorCategory.Reference;
                }
                else if (hint == OperatorType.AddressOf && type == OperatorType.LogicalAnd)
                {
                    type = OperatorType.AddressOf;
                    category = OperatorCategory.Reference;
                }
            }

            // Create the appropriate operator token based on the type.
            switch (type)
            {
                case OperatorType.AddressOf:
                    return new AddressOfOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.AndEquals:
                    return new AndEqualsOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.BitwiseComplement:
                    return new BitwiseComplementOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.ConditionalAnd:
                    return new ConditionalAndOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.ConditionalColon:
                    return new ConditionalColonOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.ConditionalEquals:
                    return new ConditionalEqualsOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.ConditionalOr:
                    return new ConditionalOrOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.ConditionalQuestionMark:
                    return new ConditionalQuestionMarkOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.Decrement:
                    return new DecrementOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.Dereference:
                    return new DereferenceOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.Division:
                    return new DivisionOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.DivisionEquals:
                    return new DivisionEqualsOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.Equals:
                    return new EqualsOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.GreaterThan:
                    return new GreaterThanOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.GreaterThanOrEquals:
                    return new GreaterThanOrEqualsOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.Increment:
                    return new IncrementOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.Lambda:
                    return new LambdaOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.LeftShift:
                    return new LeftShiftOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.LeftShiftEquals:
                    return new LeftShiftEqualsOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.LessThan:
                    return new LessThanOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.LessThanOrEquals:
                    return new LessThanOrEqualsOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.LogicalAnd:
                    return new LogicalAndOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.LogicalOr:
                    return new LogicalOrOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.LogicalXor:
                    return new LogicalXorOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.MemberAccess:
                    return new MemberAccessOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.Minus:
                    return new MinusOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.MinusEquals:
                    return new MinusEqualsOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.Mod:
                    return new ModOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.ModEquals:
                    return new ModEqualsOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.Multiplication:
                    return new MultiplicationOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.MultiplicationEquals:
                    return new MultiplicationEqualsOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.Negative:
                    return new NegativeOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.Not:
                    return new NotOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.NotEquals:
                    return new NotEqualsOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.NullCoalescingSymbol:
                    return new NullCoalescingSymbolOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.OrEquals:
                    return new OrEqualsOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.Plus:
                    return new PlusOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.PlusEquals:
                    return new PlusEqualsOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.Pointer:
                    return new PointerOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.Positive:
                    return new PositiveOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.QualifiedAlias:
                    return new QualifiedAliasOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.RightShift:
                    return new RightShiftOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.RightShiftEquals:
                    return new RightShiftEqualsOperator(this.document, symbol.Text, symbol.Location, generated);
                case OperatorType.XorEquals:
                    return new XorEqualsOperator(this.document, symbol.Text, symbol.Location, generated);
                default:
                    CsLanguageService.Debug.Fail("Invalid operator type");
                    return null;
            }
        }
        private bool GetOtherElementModifier(CodeUnitProxy elementProxy, string[] allowedModifiers, Dictionary<TokenType, Token> modifiers, Symbol symbol)
        {
            Param.AssertNotNull(elementProxy, "elementProxy");
            Param.Ignore(allowedModifiers);
            Param.AssertNotNull(modifiers, "modifiers");
            Param.AssertNotNull(symbol, "symbol");

            bool stop = true;

            // If the modifier is one of the allowed modifiers, store it. Otherwise, we are done.
            if (allowedModifiers != null)
            {
                for (int i = 0; i < allowedModifiers.Length; ++i)
                {
                    if (string.Equals(symbol.Text, allowedModifiers[i], StringComparison.Ordinal))
                    {
                        TokenType modifierType;
                        switch (symbol.SymbolType)
                        {
                            case SymbolType.Abstract:
                                modifierType = TokenType.Abstract;
                                break;

                            case SymbolType.Const:
                                modifierType = TokenType.Const;
                                break;

                            case SymbolType.Explicit:
                                modifierType = TokenType.Explicit;
                                break;

                            case SymbolType.Extern:
                                modifierType = TokenType.Extern;
                                break;

                            case SymbolType.Implicit:
                                modifierType = TokenType.Implicit;
                                break;

                            case SymbolType.New:
                                modifierType = TokenType.New;
                                break;

                            case SymbolType.Override:
                                modifierType = TokenType.Override;
                                break;

                            case SymbolType.Readonly:
                                modifierType = TokenType.Readonly;
                                break;

                            case SymbolType.Sealed:
                                modifierType = TokenType.Sealed;
                                break;

                            case SymbolType.Static:
                                modifierType = TokenType.Static;
                                break;

                            case SymbolType.Unsafe:
                                modifierType = TokenType.Unsafe;
                                break;

                            case SymbolType.Virtual:
                                modifierType = TokenType.Virtual;
                                break;

                            case SymbolType.Volatile:
                                modifierType = TokenType.Volatile;
                                break;

                            case SymbolType.Fixed:
                                modifierType = TokenType.Fixed;
                                break;

                            case SymbolType.Other:
                                if (symbol.Text != "partial")
                                {
                                    goto default;
                                }

                                modifierType = TokenType.Partial;
                                break;

                            default:
                                throw this.CreateSyntaxException();
                        }

                        Token modifier = this.GetToken(elementProxy, modifierType, symbol.SymbolType);
                        modifiers.Add(modifierType, modifier);
                        stop = false;
                        break;
                    }
                }
            }

            return !stop;
        }