/// <summary>
        /// Extracts the body of the given preprocessor directive symbol, parses it, and returns the parsed expression.
        /// </summary>
        /// <param name="parser">The C# parser.</param>
        /// <param name="sourceCode">The source code containing the preprocessor directive symbol.</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(
             CsParser parser, SourceCode sourceCode, Symbol preprocessorSymbol, int startIndex)
        {
            Param.AssertNotNull(parser, "parser");
            Param.AssertNotNull(sourceCode, "sourceCode");
            Param.AssertNotNull(preprocessorSymbol, "preprocessorSymbol");
            Param.AssertGreaterThanOrEqualToZero(startIndex, "startIndex");
            Debug.Assert(preprocessorSymbol.SymbolType == SymbolType.PreprocessorDirective, "The symbol is not a preprocessor directive.");

            string text = preprocessorSymbol.Text.Substring(startIndex, preprocessorSymbol.Text.Length - startIndex).Trim();
            if (text.Length > 0)
            {
                using (StringReader reader = new StringReader(text))
                {
                    // Extract the symbols within this text.
                    CodeLexer lexer = new CodeLexer(parser, sourceCode, new CodeReader(reader));
                    List<Symbol> symbolList = lexer.GetSymbols(sourceCode, null);
                    SymbolManager directiveSymbols = new SymbolManager(symbolList);

                    CodeParser preprocessorBodyParser = new CodeParser(parser, directiveSymbols);

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

            // The directive has no body.
            return null;
        }
예제 #2
0
        /// <summary>
        /// Creates an operator token from the given symbol.
        /// </summary>
        /// <param name="symbol">The symbol to convert.</param>
        /// <param name="parentReference">The parent code part.</param>
        /// <param name="generated">Indicates whether the symbol lies within a generated code block.</param>
        /// <returns>Returns the operator symbol.</returns>
        private static OperatorSymbol CreateOperatorToken(Symbol symbol, Reference<ICodePart> parentReference, bool generated)
        {
            Param.AssertNotNull(symbol, "symbol");
            Param.AssertNotNull(parentReference, "parentReference");
            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.
                Debug.Fail("Unexpected operator type");
                throw new InvalidOperationException();
            }

            // Create and return the operator.
            return new OperatorSymbol(symbol.Text, category, type, symbol.Location, parentReference, generated);
        }
예제 #3
0
 private CsToken ConvertSymbol(Symbol symbol, CsTokenType tokenType)
 {
     if (symbol.SymbolType == SymbolType.WhiteSpace)
     {
         return new Whitespace(symbol.Text, symbol.Location, this.symbols.Generated);
     }
     if (symbol.SymbolType == SymbolType.Number)
     {
         return new Microsoft.StyleCop.CSharp.Number(symbol.Text, symbol.Location, this.symbols.Generated);
     }
     if (symbol.SymbolType == SymbolType.PreprocessorDirective)
     {
         return this.GetPreprocessorDirectiveToken(symbol, this.symbols.Generated);
     }
     return new CsToken(symbol.Text, tokenType, CsTokenClass.Token, symbol.Location, this.symbols.Generated);
 }
예제 #4
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>
        /// <param name="parent">The parent code part.</param>
        /// <param name="generated">Indicates whether the directive lies within a block of generated code.</param>
        /// <returns>Returns the directive.</returns>
        private ConditionalCompilationDirective GetConditionalCompilationDirective(
            Symbol preprocessorSymbol, 
            ConditionalCompilationDirectiveType type,
            int startIndex, 
            Reference<ICodePart> parent,
            bool generated)
        {
            Param.AssertNotNull(preprocessorSymbol, "preprocessorSymbol");
            Param.Ignore(type);
            Param.AssertGreaterThanOrEqualToZero(startIndex, "startIndex");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(generated);

            Expression body = null;

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

            // Create and return the directive.
            return new ConditionalCompilationDirective(
                preprocessorSymbol.Text, type, body, preprocessorSymbol.Location, parent, generated);
        }
예제 #5
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;
        }
예제 #6
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.
            CodeLocation 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.
            Symbol 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;
        }
예제 #7
0
        /// <summary>
        /// Gets an undefine preprocessor directive from the code.
        /// </summary>
        /// <param name="sourceCode">The source code being parsed.</param>
        /// <param name="preprocessorSymbol">The preprocessor symbol being parsed.</param>
        /// <param name="startIndex">The start index within the symbols.</param>
        private void GetUndefinePreprocessorDirective(SourceCode sourceCode, Symbol preprocessorSymbol, int startIndex)
        {
            Param.AssertNotNull(sourceCode, "sourceCode");
            Param.AssertNotNull(preprocessorSymbol, "preprocessorSymbol");
            Param.AssertGreaterThanOrEqualToZero(startIndex, "startIndex");

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

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

            // Add the item to the list.
            if (!this.undefines.ContainsKey(body.Text))
            {
                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);
            }
        }
예제 #8
0
        /// <summary>
        /// Gets the next preprocessor directive keyword.
        /// </summary>
        /// <param name="sourceCode">The source code.</param>
        /// <param name="configuration">The active configuration.</param>
        /// <param name="evaluate">Indicates whether to evaluate the preprocessor symbol if it is a conditional
        /// directive.</param>
        /// <returns>Returns the next preprocessor directive keyword.</returns>
        private Symbol GetPreprocessorDirectiveSymbol(
            SourceCode sourceCode, Configuration configuration, bool evaluate)
        {
            Param.AssertNotNull(sourceCode, "sourceCode");
            Param.Ignore(configuration);
            Param.Ignore(evaluate);

            // Find the end of the current line.
            StringBuilder text = new StringBuilder();
            this.AdvanceToEndOfLine(text);
            if (text.Length == 1)
            {
                throw new SyntaxException(sourceCode, 1, Strings.UnexpectedEndOfFile);
            }

            // Create the code location.
            CodeLocation 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.
            Symbol symbol = new Symbol(text.ToString(), SymbolType.PreprocessorDirective, location);

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

            if (evaluate && configuration != null)
            {
                // Check the type of the symbol. If this is a conditional preprocessor symbol which resolves to false,
                // then we need to advance past all of the code which is not in scope.
                this.CheckForConditionalCompilationDirective(sourceCode, symbol, configuration);
            }

            // Return the symbol.
            return symbol;
        }
예제 #9
0
        private Symbol GetOperatorSymbol(char character)
        {
            Param.Ignore(character);

            SymbolType type = SymbolType.Other;
            StringBuilder 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.
            CodeLocation 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.
            Symbol 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;
        }
예제 #10
0
        private static bool GetOperatorType(Symbol symbol, out OperatorType type, out OperatorCategory category)
        {
            bool flag = true;
            switch (symbol.SymbolType)
            {
                case SymbolType.Equals:
                    type = OperatorType.Equals;
                    category = OperatorCategory.Assignment;
                    return flag;

                case SymbolType.ConditionalEquals:
                    type = OperatorType.ConditionalEquals;
                    category = OperatorCategory.Relational;
                    return flag;

                case SymbolType.Plus:
                    type = OperatorType.Plus;
                    category = OperatorCategory.Arithmetic;
                    return flag;

                case SymbolType.PlusEquals:
                    type = OperatorType.PlusEquals;
                    category = OperatorCategory.Assignment;
                    return flag;

                case SymbolType.Minus:
                    type = OperatorType.Minus;
                    category = OperatorCategory.Arithmetic;
                    return flag;

                case SymbolType.MinusEquals:
                    type = OperatorType.MinusEquals;
                    category = OperatorCategory.Assignment;
                    return flag;

                case SymbolType.Multiplication:
                    type = OperatorType.Multiplication;
                    category = OperatorCategory.Arithmetic;
                    return flag;

                case SymbolType.MultiplicationEquals:
                    type = OperatorType.MultiplicationEquals;
                    category = OperatorCategory.Assignment;
                    return flag;

                case SymbolType.Division:
                    type = OperatorType.Division;
                    category = OperatorCategory.Arithmetic;
                    return flag;

                case SymbolType.DivisionEquals:
                    type = OperatorType.DivisionEquals;
                    category = OperatorCategory.Assignment;
                    return flag;

                case SymbolType.LessThan:
                    type = OperatorType.LessThan;
                    category = OperatorCategory.Relational;
                    return flag;

                case SymbolType.LessThanOrEquals:
                    type = OperatorType.LessThanOrEquals;
                    category = OperatorCategory.Relational;
                    return flag;

                case SymbolType.LeftShift:
                    type = OperatorType.LeftShift;
                    category = OperatorCategory.Shift;
                    return flag;

                case SymbolType.LeftShiftEquals:
                    type = OperatorType.LeftShiftEquals;
                    category = OperatorCategory.Assignment;
                    return flag;

                case SymbolType.GreaterThan:
                    type = OperatorType.GreaterThan;
                    category = OperatorCategory.Relational;
                    return flag;

                case SymbolType.GreaterThanOrEquals:
                    type = OperatorType.GreaterThanOrEquals;
                    category = OperatorCategory.Relational;
                    return flag;

                case SymbolType.RightShift:
                    type = OperatorType.RightShift;
                    category = OperatorCategory.Shift;
                    return flag;

                case SymbolType.RightShiftEquals:
                    type = OperatorType.RightShiftEquals;
                    category = OperatorCategory.Assignment;
                    return flag;

                case SymbolType.Increment:
                    type = OperatorType.Increment;
                    category = OperatorCategory.IncrementDecrement;
                    return flag;

                case SymbolType.Decrement:
                    type = OperatorType.Decrement;
                    category = OperatorCategory.IncrementDecrement;
                    return flag;

                case SymbolType.LogicalAnd:
                    type = OperatorType.LogicalAnd;
                    category = OperatorCategory.Logical;
                    return flag;

                case SymbolType.AndEquals:
                    type = OperatorType.AndEquals;
                    category = OperatorCategory.Assignment;
                    return flag;

                case SymbolType.ConditionalAnd:
                    type = OperatorType.ConditionalAnd;
                    category = OperatorCategory.Logical;
                    return flag;

                case SymbolType.LogicalOr:
                    type = OperatorType.LogicalOr;
                    category = OperatorCategory.Logical;
                    return flag;

                case SymbolType.OrEquals:
                    type = OperatorType.OrEquals;
                    category = OperatorCategory.Assignment;
                    return flag;

                case SymbolType.ConditionalOr:
                    type = OperatorType.ConditionalOr;
                    category = OperatorCategory.Logical;
                    return flag;

                case SymbolType.LogicalXor:
                    type = OperatorType.LogicalXor;
                    category = OperatorCategory.Logical;
                    return flag;

                case SymbolType.XorEquals:
                    type = OperatorType.XorEquals;
                    category = OperatorCategory.Assignment;
                    return flag;

                case SymbolType.Not:
                    type = OperatorType.Not;
                    category = OperatorCategory.Unary;
                    return flag;

                case SymbolType.NotEquals:
                    type = OperatorType.NotEquals;
                    category = OperatorCategory.Relational;
                    return flag;

                case SymbolType.Mod:
                    type = OperatorType.Mod;
                    category = OperatorCategory.Arithmetic;
                    return flag;

                case SymbolType.ModEquals:
                    type = OperatorType.ModEquals;
                    category = OperatorCategory.Assignment;
                    return flag;

                case SymbolType.Dot:
                    type = OperatorType.MemberAccess;
                    category = OperatorCategory.Reference;
                    return flag;

                case SymbolType.Pointer:
                    type = OperatorType.Pointer;
                    category = OperatorCategory.Reference;
                    return flag;

                case SymbolType.Colon:
                    type = OperatorType.ConditionalColon;
                    category = OperatorCategory.Conditional;
                    return flag;

                case SymbolType.QualifiedAlias:
                    type = OperatorType.QualifiedAlias;
                    category = OperatorCategory.Reference;
                    return flag;

                case SymbolType.QuestionMark:
                    type = OperatorType.ConditionalQuestionMark;
                    category = OperatorCategory.Conditional;
                    return flag;

                case SymbolType.NullCoalescingSymbol:
                    type = OperatorType.NullCoalescingSymbol;
                    category = OperatorCategory.Logical;
                    return flag;

                case SymbolType.Tilde:
                    type = OperatorType.BitwiseCompliment;
                    category = OperatorCategory.Unary;
                    return flag;

                case SymbolType.Lambda:
                    type = OperatorType.Lambda;
                    category = OperatorCategory.Lambda;
                    return flag;
            }
            type = OperatorType.AddressOf;
            category = OperatorCategory.Arithmetic;
            return false;
        }
예제 #11
0
 private static OperatorSymbol CreateOperatorToken(Symbol symbol, bool generated)
 {
     OperatorType type;
     OperatorCategory category;
     if (!GetOperatorType(symbol, out type, out category))
     {
         throw new InvalidOperationException();
     }
     return new OperatorSymbol(symbol.Text, category, type, symbol.Location, generated);
 }
예제 #12
0
        private Preprocessor GetPreprocessorDirectiveToken(Symbol preprocessorSymbol, bool generated)
        {
            int num;
            string preprocessorDirectiveType = CsParser.GetPreprocessorDirectiveType(preprocessorSymbol, out num);
            if (preprocessorDirectiveType == null)
            {
                throw new SyntaxException(this.document.SourceCode, preprocessorSymbol.LineNumber);
            }
            switch (preprocessorDirectiveType)
            {
                case "region":
                {
                    Region region = new Region(preprocessorSymbol.Text, preprocessorSymbol.Location, true, generated);
                    this.symbols.PushRegion(region);
                    return region;
                }
                case "endregion":
                {
                    Region region2 = new Region(preprocessorSymbol.Text, preprocessorSymbol.Location, false, generated);
                    Region region3 = this.symbols.PopRegion();
                    if (region3 == null)
                    {
                        throw new SyntaxException(this.document.SourceCode, preprocessorSymbol.LineNumber);
                    }
                    region3.Partner = region2;
                    region2.Partner = region3;
                    return region2;
                }
                case "if":
                    return this.GetConditionalCompilationDirective(preprocessorSymbol, ConditionalCompilationDirectiveType.If, num, generated);

                case "elif":
                    return this.GetConditionalCompilationDirective(preprocessorSymbol, ConditionalCompilationDirectiveType.Elif, num, generated);

                case "else":
                    return this.GetConditionalCompilationDirective(preprocessorSymbol, ConditionalCompilationDirectiveType.Else, num, generated);

                case "endif":
                    return this.GetConditionalCompilationDirective(preprocessorSymbol, ConditionalCompilationDirectiveType.Endif, num, generated);
            }
            return new Preprocessor(preprocessorSymbol.Text, preprocessorSymbol.Location, generated);
        }
예제 #13
0
        private bool GetOtherElementModifier(string[] allowedModifiers, Dictionary<CsTokenType, CsToken> modifiers, Symbol symbol)
        {
            bool flag = true;
            if (allowedModifiers != null)
            {
                for (int i = 0; i < allowedModifiers.Length; i++)
                {
                    CsTokenType @explicit;
                    CsToken token;
                    if (!string.Equals(symbol.Text, allowedModifiers[i], StringComparison.Ordinal))
                    {
                        goto Label_014E;
                    }
                    switch (symbol.SymbolType)
                    {
                        case SymbolType.Explicit:
                            @explicit = CsTokenType.Explicit;
                            goto Label_0128;

                        case SymbolType.Extern:
                            @explicit = CsTokenType.Extern;
                            goto Label_0128;

                        case SymbolType.Fixed:
                            @explicit = CsTokenType.Fixed;
                            goto Label_0128;

                        case SymbolType.Implicit:
                            @explicit = CsTokenType.Implicit;
                            goto Label_0128;

                        case SymbolType.New:
                            @explicit = CsTokenType.New;
                            goto Label_0128;

                        case SymbolType.Abstract:
                            @explicit = CsTokenType.Abstract;
                            goto Label_0128;

                        case SymbolType.Const:
                            @explicit = CsTokenType.Const;
                            goto Label_0128;

                        case SymbolType.Override:
                            @explicit = CsTokenType.Override;
                            goto Label_0128;

                        case SymbolType.Readonly:
                            @explicit = CsTokenType.Readonly;
                            goto Label_0128;

                        case SymbolType.Unsafe:
                            @explicit = CsTokenType.Unsafe;
                            goto Label_0128;

                        case SymbolType.Virtual:
                            @explicit = CsTokenType.Virtual;
                            goto Label_0128;

                        case SymbolType.Volatile:
                            @explicit = CsTokenType.Volatile;
                            goto Label_0128;

                        case SymbolType.Other:
                            if (symbol.Text != "partial")
                            {
                                break;
                            }
                            @explicit = CsTokenType.Partial;
                            goto Label_0128;

                        case SymbolType.Static:
                            @explicit = CsTokenType.Static;
                            goto Label_0128;

                        case SymbolType.Sealed:
                            @explicit = CsTokenType.Sealed;
                            goto Label_0128;
                    }
                    throw this.CreateSyntaxException();
                Label_0128:
                    token = this.GetToken(@explicit, symbol.SymbolType);
                    modifiers.Add(@explicit, token);
                    this.tokens.Add(token);
                    flag = false;
                    break;
                Label_014E:;
                }
            }
            return !flag;
        }
예제 #14
0
 private ConditionalCompilationDirective GetConditionalCompilationDirective(Symbol preprocessorSymbol, ConditionalCompilationDirectiveType type, int startIndex, bool generated)
 {
     Expression body = null;
     if ((type != ConditionalCompilationDirectiveType.Endif) && (startIndex < preprocessorSymbol.Text.Length))
     {
         body = GetConditionalPreprocessorBodyExpression(this.parser, this.document.SourceCode, preprocessorSymbol, startIndex);
     }
     return new ConditionalCompilationDirective(preprocessorSymbol.Text, type, body, preprocessorSymbol.Location, generated);
 }
예제 #15
0
 internal static Expression GetConditionalPreprocessorBodyExpression(CsParser parser, SourceCode sourceCode, Symbol preprocessorSymbol, int startIndex)
 {
     string s = preprocessorSymbol.Text.Substring(startIndex, preprocessorSymbol.Text.Length - startIndex).Trim();
     if (s.Length > 0)
     {
         StringReader code = new StringReader(s);
         CodeLexer lexer = new CodeLexer(parser, sourceCode, new CodeReader(code));
         SymbolManager symbols = new SymbolManager(lexer.GetSymbols(sourceCode, null));
         CodeParser parser2 = new CodeParser(parser, symbols);
         return parser2.GetNextConditionalPreprocessorExpression(sourceCode);
     }
     return null;
 }
예제 #16
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.
                CodeLocation 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;
        }
예제 #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);
                Debug.Assert(!string.IsNullOrEmpty(numberText), "The text should not be empty");

                // Create the location object.
                CodeLocation 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;
        }
예제 #18
0
        /// <summary>
        /// Converts a symbol to the given token type.
        /// </summary>
        /// <param name="symbol">The symbol to convert.</param>
        /// <param name="tokenType">The type of the token to retrieve.</param>
        /// <param name="parentReference">The parent code part.</param>
        /// <returns>Returns the token.</returns>
        private CsToken ConvertSymbol(Symbol symbol, CsTokenType tokenType, Reference<ICodePart> parentReference)
        {
            Param.AssertNotNull(symbol, "symbol");
            Param.Ignore(tokenType);
            Param.AssertNotNull(parentReference, "parentReference");

            // Create the appropriate token based on the type of the symbol.
            if (symbol.SymbolType == SymbolType.WhiteSpace)
            {
                Debug.Assert(tokenType == CsTokenType.WhiteSpace, "The token type is wrong.");
                return new Whitespace(symbol.Text, symbol.Location, parentReference, this.symbols.Generated);
            }
            else if (symbol.SymbolType == SymbolType.Number)
            {
                Debug.Assert(tokenType == CsTokenType.Number, "The token type is wrong.");
                return new Number(symbol.Text, symbol.Location, parentReference, this.symbols.Generated);
            }
            else if (symbol.SymbolType == SymbolType.PreprocessorDirective)
            {
                Debug.Assert(tokenType == CsTokenType.PreprocessorDirective, "The token type is wrong.");
                return this.GetPreprocessorDirectiveToken(symbol, parentReference, this.symbols.Generated);
            }
            else
            {
                // Brackets are created using the GetBracketToken method.
                Debug.Assert(symbol.SymbolType != SymbolType.OpenParenthesis, "Do not use this method for converting brackets.");
                Debug.Assert(symbol.SymbolType != SymbolType.CloseParenthesis, "Do not use this method for converting brackets.");
                Debug.Assert(symbol.SymbolType != SymbolType.OpenSquareBracket, "Do not use this method for converting brackets.");
                Debug.Assert(symbol.SymbolType != SymbolType.CloseSquareBracket, "Do not use this method for converting brackets.");
                Debug.Assert(symbol.SymbolType != SymbolType.OpenCurlyBracket, "Do not use this method for converting brackets.");
                Debug.Assert(symbol.SymbolType != SymbolType.CloseCurlyBracket, "Do not use this method for converting brackets.");
                Debug.Assert(symbol.SymbolType != SymbolType.Attribute, "Do not use this method for converting attributes.");

                return new CsToken(symbol.Text, tokenType, CsTokenClass.Token, symbol.Location, parentReference, this.symbols.Generated);
            }
        }
예제 #19
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(SourceCode sourceCode)
        {
            Param.AssertNotNull(sourceCode, "sourceCode");

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

            string symbolText = text.ToString();

            // Get the token location.
            CodeLocation 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.
            Symbol 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;
        }
예제 #20
0
        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.BitwiseCompliment;
                    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;
        }
예제 #21
0
        /// <summary>
        /// Gets the next string from the code.
        /// </summary>
        /// <returns>Returns the string.</returns>
        private Symbol GetString()
        {
            StringBuilder text = new StringBuilder();

            // Read the opening quote character and add it to the string.
            char quoteType = this.codeReader.ReadNext();
            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.
            CodeLocation 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.
            Symbol 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;
        }
예제 #22
0
        private bool GetOtherElementModifier(
            Reference<ICodePart> elementReference,
            string[] allowedModifiers, 
            Dictionary<CsTokenType, CsToken> modifiers, 
            Symbol symbol)
        {
            Param.AssertNotNull(elementReference, "elementReference");
            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))
                    {
                        CsTokenType modifierType;
                        switch (symbol.SymbolType)
                        {
                            case SymbolType.Abstract:
                                modifierType = CsTokenType.Abstract;
                                break;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                                modifierType = CsTokenType.Partial;
                                break;

                            default:
                                throw this.CreateSyntaxException();
                        }

                        CsToken modifier = this.GetToken(modifierType, symbol.SymbolType, elementReference);
                        modifiers.Add(modifierType, modifier);
                        this.tokens.Add(modifier);
                        stop = false;
                        break;
                    }
                }
            }

            return !stop;
        }
예제 #23
0
        /// <summary>
        /// Gets the next whitespace stream.
        /// </summary>
        /// <returns>Returns the whitespace.</returns>
        private Symbol GetWhitespace()
        {
            StringBuilder 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.
            CodeLocation 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.
            Symbol 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;
        }
예제 #24
0
        /// <summary>
        /// Extracts an if, endif, or else directive.
        /// </summary>
        /// <param name="sourceCode">The source code being parsed.</param>
        /// <param name="preprocessorSymbol">The preprocessor symbol being parsed.</param>
        /// <param name="configuration">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(
            SourceCode sourceCode, 
            Symbol preprocessorSymbol, 
            Configuration configuration, 
            int startIndex, 
            string type, 
            out bool skip)
        {
            Param.AssertNotNull(sourceCode, "sourceCode");
            Param.AssertNotNull(preprocessorSymbol, "preprocessorSymbol");
            Param.AssertNotNull(configuration, "configuration");
            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.
                Expression body = CodeParser.GetConditionalPreprocessorBodyExpression(
                    this.parser, sourceCode, preprocessorSymbol, startIndex);
                if (body == null)
                {
                    throw new SyntaxException(sourceCode, preprocessorSymbol.LineNumber);
                }

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

                bool entered = this.conditionalDirectives.Peek();
                if (entered)
                {
                    skip = true;
                }
                else
                {
                    // Extract the body of the directive.
                    Expression body = CodeParser.GetConditionalPreprocessorBodyExpression(
                        this.parser, sourceCode, 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(sourceCode, body, configuration);
                    }
                }
            }
            else if (type == "else")
            {
                if (this.conditionalDirectives.Count == 0)
                {
                    throw new SyntaxException(sourceCode, preprocessorSymbol.LineNumber);
                }

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

            return ignore;
        }
예제 #25
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="sourceCode">The source code file containing this directive.</param>
        /// <param name="preprocessorSymbol">The symbol to check.</param>
        /// <param name="configuration">The active configuration.</param>
        private void CheckForConditionalCompilationDirective(
            SourceCode sourceCode, Symbol preprocessorSymbol, Configuration configuration)
        {
            Param.AssertNotNull(sourceCode, "sourceCode");
            Param.AssertNotNull(preprocessorSymbol, "preprocessorSymbol");
            Param.Ignore(configuration);

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

                this.conditionalDirectives.Pop();
            }
            else
            {
                // Extract an if, endif, or else directive.
                bool skip;

                if (!this.GetIfElsePreprocessorDirectives(
                    sourceCode, preprocessorSymbol, configuration, 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.
                        int subConditionalPreprocessorCount = 0;
                        while (true)
                        {
                            // Get the next symbol.
                            Symbol symbol = this.GetSymbol(sourceCode, configuration, false);
                            if (symbol == null)
                            {
                                throw new SyntaxException(sourceCode, preprocessorSymbol.LineNumber);
                            }

                            // 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 = CsParser.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.
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        // Indicate that this conditional directive has been entered.
                        if (this.conditionalDirectives.Count == 0)
                        {
                            throw new SyntaxException(sourceCode, preprocessorSymbol.LineNumber);
                        }

                        this.conditionalDirectives.Pop();
                        this.conditionalDirectives.Push(true);
                    }
                }
            }
        }
예제 #26
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");
            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.
            CodeLocation 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.
            Symbol 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;
        }
예제 #27
0
        /// <summary>
        /// Gets and converts preprocessor directive.
        /// </summary>
        /// <param name="preprocessorSymbol">The preprocessor symbol.</param>
        /// <param name="parent">The parent code part.</param>
        /// <param name="generated">Indicates whether the preprocessor directive lies within a block of generated code.</param>
        /// <returns>Returns the preprocessor directive.</returns>
        private Preprocessor GetPreprocessorDirectiveToken(Symbol preprocessorSymbol, Reference<ICodePart> parent, bool generated)
        {
            Param.AssertNotNull(preprocessorSymbol, "preprocessorSymbol");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(generated);

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

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

            // Create the correct preprocessor object type.
            Preprocessor preprocessor = null;
            if (type == "region")
            {
                Region region = new Region(preprocessorSymbol.Text, preprocessorSymbol.Location, parent, true, generated);
                this.symbols.PushRegion(region);
                preprocessor = region;
            }
            else if (type == "endregion")
            {
                Region endregion = new Region(preprocessorSymbol.Text, preprocessorSymbol.Location, parent, false, generated);
                Region startregion = this.symbols.PopRegion();

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

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

                preprocessor = endregion;
            }
            else if (type == "if")
            {
                preprocessor = this.GetConditionalCompilationDirective(
                    preprocessorSymbol, ConditionalCompilationDirectiveType.If, bodyIndex, parent, generated);
            }
            else if (type == "elif")
            {
                preprocessor = this.GetConditionalCompilationDirective(
                    preprocessorSymbol, ConditionalCompilationDirectiveType.Elif, bodyIndex, parent, generated);
            }
            else if (type == "else")
            {
                preprocessor = this.GetConditionalCompilationDirective(
                    preprocessorSymbol, ConditionalCompilationDirectiveType.Else, bodyIndex, parent, generated);
            }
            else if (type == "endif")
            {
                preprocessor = this.GetConditionalCompilationDirective(
                    preprocessorSymbol, ConditionalCompilationDirectiveType.Endif, bodyIndex, parent, generated);
            }
            else
            {
                preprocessor = new Preprocessor(preprocessorSymbol.Text, preprocessorSymbol.Location, parent, generated);
            }

            return preprocessor;
        }
예제 #28
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");
            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();
            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 == char.MinValue)
                {
                    // No more characters in the buffer.
                    break;
                }
                else 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.
            CodeLocation location = new CodeLocation(
                startIndex, endIndex, startIndexOnLine, endIndexOnLine, lineNumber, endLineNumber);

            // Create the symbol.
            Symbol 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;
        }
예제 #29
0
 internal static string GetPreprocessorDirectiveType(Symbol preprocessor, out int bodyIndex)
 {
     bodyIndex = -1;
     int startIndex = -1;
     int num2 = -1;
     for (int i = 1; i < preprocessor.Text.Length; i++)
     {
         if (char.IsLetter(preprocessor.Text[i]))
         {
             startIndex = i;
             break;
         }
     }
     if (startIndex == -1)
     {
         return null;
     }
     num2 = startIndex;
     while (num2 < preprocessor.Text.Length)
     {
         if (!char.IsLetter(preprocessor.Text[num2]))
         {
             break;
         }
         num2++;
     }
     num2--;
     if (num2 < startIndex)
     {
         return null;
     }
     bodyIndex = num2 + 1;
     return preprocessor.Text.Substring(startIndex, (num2 - startIndex) + 1);
 }
예제 #30
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.
            CodeLocation location = new CodeLocation(
                startIndex, endIndex, startIndexOnLine, endIndexOnLine, lineNumber, endLineNumber);

            // Create the symbol object.
            Symbol 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;
        }