Example #1
0
        /* Function: GetColumn
         * Returns the bounds of a parameter's column and what type it is, which depends on <ColumnOrder>.  You *must* call
         * <CalculateColumns()> beforehand.  Returns false if the column index is out of bounds or the contents are empty for
         * that particular slot.
         */
        public bool GetColumn(int columnIndex, out TokenIterator start, out TokenIterator end, out ColumnType type)
        {
            if (columnIndex >= columnIndexes.Length)
            {
                start = parsedPrototype.Tokenizer.LastToken;
                end   = parsedPrototype.Tokenizer.LastToken;
                type  = ColumnType.Name;
                return(false);
            }

            int startIndex = columnIndexes[columnIndex];
            int endIndex   = (columnIndex + 1 >= columnIndexes.Length ? endOfColumnsIndex : columnIndexes[columnIndex + 1]);

            start = parsedPrototype.Tokenizer.FirstToken;

            if (startIndex > 0)
            {
                start.Next(startIndex);
            }

            end = start;

            if (endIndex > startIndex)
            {
                end.Next(endIndex - startIndex);
            }

            type = ColumnOrder[columnIndex];

            end.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, start);
            start.NextPastWhitespace(end);

            return(end > start);
        }
Example #2
0
        /* Function: MarkAnnotationParameter
         *
         * Applies types to an annotation parameter, such as ""String"" in "@Copynight("String")" or "id = 12" in
         * "@RequestForEnhancement(id = 12, engineer = "String")".
         *
         * Supported Modes:
         *
         *		- <ParseMode.ParsePrototype>
         *			- The contents will be marked with parameter tokens.
         *		- Everything else has no effect.
         */
        protected void MarkAnnotationParameter(TokenIterator start, TokenIterator end, ParseMode mode = ParseMode.IterateOnly)
        {
            if (mode != ParseMode.ParsePrototype)
            {
                return;
            }

            start.NextPastWhitespace(end);
            end.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, start);

            if (start >= end)
            {
                return;
            }


            // Find and mark the equals sign, if there is one

            TokenIterator equals = start;

            while (equals < end)
            {
                if (equals.Character == '=')
                {
                    equals.PrototypeParsingType = PrototypeParsingType.PropertyValueSeparator;
                    break;
                }
                else if (TryToSkipComment(ref equals) ||
                         TryToSkipString(ref equals) ||
                         TryToSkipBlock(ref equals, true))
                {
                }
                else
                {
                    equals.Next();
                }
            }


            // The equals sign will be at or past the end if it doesn't exist.

            if (equals >= end)
            {
                start.SetPrototypeParsingTypeBetween(end, PrototypeParsingType.PropertyValue);
            }
            else
            {
                TokenIterator iterator = equals;
                iterator.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, start);

                if (start < iterator)
                {
                    start.SetPrototypeParsingTypeBetween(iterator, PrototypeParsingType.Name);
                }

                iterator = equals;
                iterator.Next();
                iterator.NextPastWhitespace(end);

                if (iterator < end)
                {
                    iterator.SetPrototypeParsingTypeBetween(end, PrototypeParsingType.PropertyValue);
                }
            }
        }
Example #3
0
        /* Function: ParsePrototype
         * Converts a raw text prototype into a <ParsedPrototype>.
         */
        override public ParsedPrototype ParsePrototype(string stringPrototype, int commentTypeID)
        {
            Tokenizer       tokenizedPrototype = new Tokenizer(stringPrototype, tabWidth: EngineInstance.Config.TabWidth);
            ParsedPrototype parsedPrototype;


            // Mark any leading annotations.

            TokenIterator iterator = tokenizedPrototype.FirstToken;

            TryToSkipWhitespace(ref iterator, true, ParseMode.ParsePrototype);

            if (TryToSkipAnnotations(ref iterator, ParseMode.ParsePrototype))
            {
                TryToSkipWhitespace(ref iterator, true, ParseMode.ParsePrototype);
            }


            // Search for the first opening bracket or brace.

            char closingBracket = '\0';

            while (iterator.IsInBounds)
            {
                if (iterator.Character == '(')
                {
                    closingBracket = ')';
                    break;
                }
                else if (iterator.Character == '[')
                {
                    // Only treat brackets as parameters if it's following "this", meaning it's an iterator.  Ignore all others so we
                    // don't get tripped up on metadata or array brackets on return values.

                    TokenIterator lookbehind = iterator;
                    lookbehind.Previous();
                    lookbehind.PreviousPastWhitespace(PreviousPastWhitespaceMode.Iterator);

                    if (lookbehind.MatchesToken("this"))
                    {
                        closingBracket = ']';
                        break;
                    }
                    else
                    {
                        iterator.Next();
                    }
                }
                else if (iterator.Character == '{')
                {
                    closingBracket = '}';
                    break;
                }
                else if (TryToSkipComment(ref iterator) ||
                         TryToSkipString(ref iterator))
                {
                }
                else
                {
                    iterator.Next();
                }
            }


            // If we found brackets, it's either a function prototype or a class prototype that includes members.
            // Mark the delimiters.

            if (closingBracket != '\0')
            {
                iterator.PrototypeParsingType = PrototypeParsingType.StartOfParams;
                iterator.Next();

                while (iterator.IsInBounds)
                {
                    if (iterator.Character == ',')
                    {
                        iterator.PrototypeParsingType = PrototypeParsingType.ParamSeparator;
                        iterator.Next();
                    }

                    else if (iterator.Character == closingBracket)
                    {
                        iterator.PrototypeParsingType = PrototypeParsingType.EndOfParams;
                        break;
                    }

                    // Unlike prototype detection, here we treat < as an opening bracket.  Since we're already in the parameter list
                    // we shouldn't run into it as part of an operator overload, and we need it to not treat the comma in "template<a,b>"
                    // as a parameter divider.
                    else if (TryToSkipComment(ref iterator) ||
                             TryToSkipString(ref iterator) ||
                             TryToSkipBlock(ref iterator, true))
                    {
                    }

                    else
                    {
                        iterator.Next();
                    }
                }


                // We have enough tokens marked to create the parsed prototype.  This will also let us iterate through the parameters
                // easily.

                parsedPrototype = new ParsedPrototype(tokenizedPrototype);


                // Set the main section to the last one, since any annotations present will each be in their own section.  Some can have
                // parameter lists and we don't want those confused for the actual parameter list.

                parsedPrototype.MainSectionIndex = parsedPrototype.Sections.Count - 1;


                // Mark the part before the parameters, which includes the name and return value.

                TokenIterator start, end;
                parsedPrototype.GetBeforeParameters(out start, out end);

                // Exclude the opening bracket
                end.Previous();
                end.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, start);

                if (start < end)
                {
                    MarkCParameter(start, end);
                }


                // If there are any parameters, mark the tokens in them.

                if (parsedPrototype.NumberOfParameters > 0)
                {
                    for (int i = 0; i < parsedPrototype.NumberOfParameters; i++)
                    {
                        parsedPrototype.GetParameter(i, out start, out end);
                        MarkCParameter(start, end);
                    }
                }
            }


            // If there's no brackets, it's a variable, property, or class.

            else
            {
                parsedPrototype = new ParsedPrototype(tokenizedPrototype);
                TokenIterator start = tokenizedPrototype.FirstToken;
                TokenIterator end   = tokenizedPrototype.LastToken;

                MarkCParameter(start, end);
            }

            return(parsedPrototype);
        }
Example #4
0
        /* Function: BuildCurrentClass
         */
        protected void BuildCurrentClass()
        {
            htmlOutput.Append("<div class=\"CPEntry T" + EngineInstance.CommentTypes.FromID(topic.CommentTypeID).SimpleIdentifier + " Current\">");


            // Pre-prototype lines

            int           lineCount = parsedPrototype.NumberOfPrePrototypeLines;
            TokenIterator start, end;

            for (int i = 0; i < lineCount; i++)
            {
                parsedPrototype.GetPrePrototypeLine(i, out start, out end);

                htmlOutput.Append("<div class=\"CPPrePrototypeLine\">");
                BuildSyntaxHighlightedText(start, end);
                htmlOutput.Append("</div>");
            }


            // Keyword and modifiers.  We only show the keyword if it's not "class".

            TokenIterator startKeyword, endKeyword;

            topic.ParsedClassPrototype.GetKeyword(out startKeyword, out endKeyword);
            string keyword = startKeyword.String;

            TokenIterator startModifiers, endModifiers;
            bool          hasModifiers = topic.ParsedClassPrototype.GetModifiers(out startModifiers, out endModifiers);

            if (hasModifiers || keyword != "class")
            {
                StringBuilder modifiersOutput = new StringBuilder();
                TokenIterator partial;

                bool hasPartial = startModifiers.Tokenizer.FindTokenBetween("partial", EngineInstance.Languages.FromID(topic.LanguageID).CaseSensitive,
                                                                            startModifiers, endModifiers, out partial);

                if (hasPartial)
                {
                    TokenIterator lookahead = partial;
                    lookahead.Next();

                    if (lookahead < endModifiers &&
                        (lookahead.FundamentalType == FundamentalType.Text ||
                         lookahead.Character == '_'))
                    {
                        hasPartial = false;
                    }

                    TokenIterator lookbehind = partial;
                    lookbehind.Previous();

                    if (lookbehind >= startModifiers &&
                        (lookbehind.FundamentalType == FundamentalType.Text ||
                         lookbehind.Character == '_'))
                    {
                        hasPartial = false;
                    }
                }

                if (hasModifiers && hasPartial)
                {
                    if (partial > startModifiers)
                    {
                        TokenIterator lookbehind = partial;
                        lookbehind.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds);

                        BuildSyntaxHighlightedText(startModifiers, lookbehind, modifiersOutput);
                    }

                    partial.Next();
                    partial.NextPastWhitespace();

                    if (partial < endModifiers)
                    {
                        if (modifiersOutput.Length > 0)
                        {
                            modifiersOutput.Append(' ');
                        }

                        BuildSyntaxHighlightedText(partial, endModifiers, modifiersOutput);
                    }
                }
                else if (hasModifiers)
                {
                    BuildSyntaxHighlightedText(startModifiers, endModifiers, modifiersOutput);
                }

                if (keyword != "class")
                {
                    if (modifiersOutput.Length > 0)
                    {
                        modifiersOutput.Append(' ');
                    }

                    BuildSyntaxHighlightedText(startKeyword, endKeyword, modifiersOutput);
                }

                if (modifiersOutput.Length > 0)
                {
                    htmlOutput.Append("<div class=\"CPModifiers\">");
                    htmlOutput.Append(modifiersOutput.ToString());
                    htmlOutput.Append("</div>");
                }
            }


            // Name.  We use the fully resolved name in the symbol instead of the prototype name, which may just be the last segment.

            htmlOutput.Append("<div class=\"CPName\">");

            BuildWrappedTitle(topic.Symbol.FormatWithSeparator(this.language.MemberOperator), topic.CommentTypeID, htmlOutput);

            TokenIterator startTemplate, endTemplate;

            if (topic.ParsedClassPrototype.GetTemplateSuffix(out startTemplate, out endTemplate))
            {
                // Include a zero-width space for wrapping
                htmlOutput.Append("&#8203;<span class=\"TemplateSignature\">");
                htmlOutput.EntityEncodeAndAppend(startTemplate.Tokenizer.TextBetween(startTemplate, endTemplate));
                htmlOutput.Append("</span>");
            }

            htmlOutput.Append("</div>");


            // Post-prototype lines

            lineCount = parsedPrototype.NumberOfPostPrototypeLines;

            for (int i = 0; i < lineCount; i++)
            {
                parsedPrototype.GetPostPrototypeLine(i, out start, out end);

                htmlOutput.Append("<div class=\"CPPostPrototypeLine\">");
                BuildSyntaxHighlightedText(start, end);
                htmlOutput.Append("</div>");
            }

            htmlOutput.Append("</div>");
        }
Example #5
0
        /* Function: CalculateSections
         */
        protected void CalculateSections()
        {
            sections = new List <Section>();
            Section section = null;

            TokenIterator iterator = tokenizer.FirstToken;

            iterator.NextPastWhitespace();


            // Pre-Prototype Lines

            while (iterator.IsInBounds &&
                   iterator.ClassPrototypeParsingType == ClassPrototypeParsingType.StartOfPrePrototypeLine)
            {
                section            = new Section();
                section.Type       = SectionType.PrePrototypeLine;
                section.StartIndex = iterator.TokenIndex;

                do
                {
                    iterator.Next();
                }while (iterator.IsInBounds &&
                        iterator.ClassPrototypeParsingType == ClassPrototypeParsingType.PrePrototypeLine);

                section.EndIndex = iterator.TokenIndex;
                sections.Add(section);

                iterator.NextPastWhitespace();
            }


            // Before Parents

            TokenIterator startOfSection = iterator;

            section            = new Section();
            section.Type       = SectionType.BeforeParents;
            section.StartIndex = startOfSection.TokenIndex;

            while (iterator.IsInBounds &&
                   iterator.ClassPrototypeParsingType != ClassPrototypeParsingType.StartOfParents &&
                   iterator.ClassPrototypeParsingType != ClassPrototypeParsingType.StartOfPostPrototypeLine &&
                   iterator.ClassPrototypeParsingType != ClassPrototypeParsingType.StartOfBody)
            {
                iterator.Next();
            }

            TokenIterator lookbehind = iterator;

            lookbehind.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, startOfSection);

            section.EndIndex = lookbehind.TokenIndex;
            sections.Add(section);


            // Parents

            if (iterator.ClassPrototypeParsingType == ClassPrototypeParsingType.StartOfParents)
            {
                do
                {
                    iterator.Next();
                }while (iterator.ClassPrototypeParsingType == ClassPrototypeParsingType.StartOfParents);

                iterator.NextPastWhitespace();

                while (iterator.IsInBounds &&
                       iterator.ClassPrototypeParsingType != ClassPrototypeParsingType.EndOfParents &&
                       iterator.ClassPrototypeParsingType != ClassPrototypeParsingType.StartOfPostPrototypeLine &&
                       iterator.ClassPrototypeParsingType != ClassPrototypeParsingType.StartOfBody)
                {
                    startOfSection = iterator;

                    section            = new Section();
                    section.Type       = SectionType.Parent;
                    section.StartIndex = startOfSection.TokenIndex;

                    while (iterator.IsInBounds &&
                           iterator.ClassPrototypeParsingType != ClassPrototypeParsingType.ParentSeparator &&
                           iterator.ClassPrototypeParsingType != ClassPrototypeParsingType.EndOfParents &&
                           iterator.ClassPrototypeParsingType != ClassPrototypeParsingType.StartOfPostPrototypeLine &&
                           iterator.ClassPrototypeParsingType != ClassPrototypeParsingType.StartOfBody)
                    {
                        iterator.Next();
                    }

                    lookbehind = iterator;
                    lookbehind.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, startOfSection);

                    section.EndIndex = lookbehind.TokenIndex;
                    sections.Add(section);

                    if (iterator.ClassPrototypeParsingType == ClassPrototypeParsingType.ParentSeparator)
                    {
                        do
                        {
                            iterator.Next();
                        }while (iterator.ClassPrototypeParsingType == ClassPrototypeParsingType.ParentSeparator);

                        iterator.NextPastWhitespace();
                    }
                }
            }


            // After Parents

            if (iterator.IsInBounds &&
                iterator.ClassPrototypeParsingType != ClassPrototypeParsingType.StartOfPostPrototypeLine &&
                iterator.ClassPrototypeParsingType != ClassPrototypeParsingType.StartOfBody)
            {
                startOfSection = iterator;

                section            = new Section();
                section.Type       = SectionType.AfterParents;
                section.StartIndex = iterator.TokenIndex;

                do
                {
                    iterator.Next();
                }while (iterator.IsInBounds &&
                        iterator.ClassPrototypeParsingType != ClassPrototypeParsingType.StartOfPostPrototypeLine &&
                        iterator.ClassPrototypeParsingType != ClassPrototypeParsingType.StartOfBody);

                lookbehind = iterator;
                lookbehind.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, startOfSection);

                section.EndIndex = lookbehind.TokenIndex;
                sections.Add(section);
            }


            // Post-Prototype Lines

            while (iterator.IsInBounds &&
                   iterator.ClassPrototypeParsingType == ClassPrototypeParsingType.StartOfPostPrototypeLine)
            {
                section            = new Section();
                section.Type       = SectionType.PostPrototypeLine;
                section.StartIndex = iterator.TokenIndex;

                do
                {
                    iterator.Next();
                }while (iterator.IsInBounds &&
                        iterator.ClassPrototypeParsingType == ClassPrototypeParsingType.PostPrototypeLine);

                section.EndIndex = iterator.TokenIndex;
                sections.Add(section);

                iterator.NextPastWhitespace();
            }
        }
Example #6
0
        /* Function: AppendCellContents
         */
        protected void AppendCellContents(int parameterIndex, int cellIndex, StringBuilder output)
        {
            TokenIterator start = parameterTableSection.Start;

            start.Next(parameterTableTokenIndexes[parameterIndex, cellIndex] - start.TokenIndex);

            TokenIterator end = start;

            end.Next(parameterTableTokenIndexes[parameterIndex, cellIndex + 1] - end.TokenIndex);

            bool hadTrailingWhitespace = end.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, start);

            ColumnType type = ColumnOrder[cellIndex];

            // Find the type of the next used cell
            ColumnType?nextType = null;

            for (int nextCellIndex = cellIndex + 1; nextCellIndex < NumberOfColumns; nextCellIndex++)
            {
                if (parameterTableColumnsUsed[nextCellIndex])
                {
                    nextType = ColumnOrder[nextCellIndex];
                    break;
                }
            }

            // Default value separators always get spaces before.
            // Property value separators get them unless they're ":", but watch out for ":=".
            // Type-name separators get them if they're text (SQL's "AS") instead of symbols (Pascal's ":").
            if (type == ColumnType.DefaultValueSeparator ||
                (type == ColumnType.PropertyValueSeparator && (start.Character != ':' || start.MatchesAcrossTokens(":="))) ||
                (type == ColumnType.TypeNameSeparator && start.FundamentalType == FundamentalType.Text))
            {
                output.Append("&nbsp;");
            }

            // We don't want to highlight keywords on the Name cell because identifiers can accidentally be marked as them with
            // basic language support, such as "event" in "wxPaintEvent &event".
            if (type == ColumnType.Name)
            {
                AppendSyntaxHighlightedText(start, end, output, excludeKeywords: true);
            }
            else if (addLinks)
            {
                AppendSyntaxHighlightedTextWithTypeLinks(start, end, output, links, linkTargets, extendTypeSearch: true);
            }
            else
            {
                AppendSyntaxHighlightedText(start, end, output);
            }

            // Default value separators, property value separators, and type/name separators always get spaces after.  Make sure
            // the spaces aren't duplicated by the preceding cells.
            if (type == ColumnType.DefaultValueSeparator ||
                type == ColumnType.PropertyValueSeparator ||
                type == ColumnType.TypeNameSeparator ||
                (hadTrailingWhitespace &&
                 type != ColumnType.DefaultValue &&
                 nextType != ColumnType.DefaultValueSeparator &&
                 nextType != ColumnType.PropertyValueSeparator &&
                 nextType != ColumnType.TypeNameSeparator))
            {
                output.Append("&nbsp;");
            }
        }
Example #7
0
        // Group: Parsing Functions
        // __________________________________________________________________________


        /* Function: TryToSkipPODLine
         * If the iterator is on a POD line such as "=pod", moves the iterator past it and returns true and the type.  If the iterator
         * isn't on a POD line it will return false and leave the iterator alone.
         */
        protected bool TryToSkipPODLine(ref TokenIterator iterator, out PODLineType type)
        {
            type = 0;

            if (iterator.Character != '=')
            {
                return(false);
            }

            TokenIterator lookbehind = iterator;

            for (;;)
            {
                lookbehind.Previous();

                if (lookbehind.IsInBounds == false ||
                    lookbehind.FundamentalType == FundamentalType.LineBreak)
                {
                    break;
                }
                else if (lookbehind.FundamentalType != FundamentalType.Whitespace)
                {
                    return(false);
                }
            }

            TokenIterator endOfLine = iterator;

            endOfLine.Next();

            if (endOfLine.FundamentalType != FundamentalType.Text)
            {
                return(false);
            }

            do
            {
                endOfLine.Next();
            }while (endOfLine.IsInBounds &&
                    endOfLine.FundamentalType != FundamentalType.LineBreak);

            TokenIterator endOfContent = endOfLine;

            endOfContent.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds);

            // ND and Javadoc lines may also match PODBeginLineRegex so test them first.
            if (iterator.Tokenizer.MatchTextBetween(PODBeginNDLineRegex, iterator, endOfContent).Success)
            {
                type = PODLineType.StartNaturalDocs;
            }
            else if (iterator.Tokenizer.MatchTextBetween(PODBeginJavadocLineRegex, iterator, endOfContent).Success)
            {
                type = PODLineType.StartJavadoc;
            }
            else if (iterator.Tokenizer.MatchTextBetween(PODBeginLineRegex, iterator, endOfContent).Success)
            {
                type = PODLineType.StartPOD;
            }
            else if (iterator.Tokenizer.MatchTextBetween(PODEndLineRegex, iterator, endOfContent).Success)
            {
                type = PODLineType.End;
            }
            else
            {
                return(false);
            }

            iterator = endOfLine;

            if (iterator.FundamentalType == FundamentalType.LineBreak)
            {
                iterator.Next();
            }

            return(true);
        }
Example #8
0
        /* Function: BuildCellContents
         */
        protected void BuildCellContents(int parameterIndex, int cellIndex)
        {
            TokenIterator start = parameterTableSection.Start;

            start.Next(parameterTableTokenIndexes[parameterIndex, cellIndex] - start.TokenIndex);

            TokenIterator end = start;

            end.Next(parameterTableTokenIndexes[parameterIndex, cellIndex + 1] - end.TokenIndex);

            bool hadTrailingWhitespace = end.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, start);

            ColumnType type = ColumnOrder[cellIndex];

            // Find the type of the next used cell
            ColumnType?nextType = null;

            for (int nextCellIndex = cellIndex + 1; nextCellIndex < NumberOfColumns; nextCellIndex++)
            {
                if (parameterTableColumnsUsed[nextCellIndex])
                {
                    nextType = ColumnOrder[nextCellIndex];
                    break;
                }
            }

            // Default value separators always get spaces before.  Type-name separators get them if they're text (SQL's "AS") instead
            // of symbols (Pascal's ":").
            if (type == ColumnType.DefaultValueSeparator ||
                (type == ColumnType.TypeNameSeparator && start.FundamentalType == FundamentalType.Text))
            {
                htmlOutput.Append("&nbsp;");
            }

            // We don't want syntax highlighting on the Name cell because identifiers can accidentally be marked as keywords with
            // simple highlighting and basic language support, such as "event" in "wxPaintEvent &event".
            if (type == ColumnType.Name)
            {
                htmlOutput.EntityEncodeAndAppend(start.TextBetween(end));
            }
            else if (addLinks)
            {
                BuildTypeLinkedAndSyntaxHighlightedText(start, end, true, htmlOutput);
            }
            else
            {
                BuildSyntaxHighlightedText(start, end, htmlOutput);
            }

            // Default value separators and type/name separators always get spaces after.  Make sure the spaces aren't duplicated
            // by the preceding cells.
            if (type == ColumnType.DefaultValueSeparator ||
                type == ColumnType.TypeNameSeparator ||
                (hadTrailingWhitespace &&
                 type != ColumnType.DefaultValue &&
                 nextType != ColumnType.DefaultValueSeparator &&
                 nextType != ColumnType.TypeNameSeparator))
            {
                htmlOutput.Append("&nbsp;");
            }
        }
Example #9
0
        /* Function: AppendCurrentClassPrototype
         */
        protected void AppendCurrentClassPrototype(StringBuilder output)
        {
            // Main tag

            string simpleTypeIdentifier = EngineInstance.CommentTypes.FromID(context.Topic.CommentTypeID).SimpleIdentifier;

            output.Append("<div class=\"CPEntry T" + simpleTypeIdentifier + " Current\">");


            // Pre-prototype lines

            int           lineCount = parsedClassPrototype.NumberOfPrePrototypeLines;
            TokenIterator start, end;

            for (int i = 0; i < lineCount; i++)
            {
                parsedClassPrototype.GetPrePrototypeLine(i, out start, out end);

                output.Append("<div class=\"CPPrePrototypeLine\">");
                AppendSyntaxHighlightedText(start, end, output);
                output.Append("</div>");
            }


            // Keyword and modifiers.  We only show the keyword if it's not "class", and we exclude "partial" from the list of modifiers.

            TokenIterator startKeyword, endKeyword;

            parsedClassPrototype.GetKeyword(out startKeyword, out endKeyword);
            string keyword = startKeyword.String;

            TokenIterator startModifiers, endModifiers;
            bool          hasModifiers = parsedClassPrototype.GetModifiers(out startModifiers, out endModifiers);

            if (hasModifiers || keyword != "class")
            {
                StringBuilder modifiersOutput = new StringBuilder();
                TokenIterator partial;

                bool hasPartial = startModifiers.Tokenizer.FindTokenBetween("partial", language.CaseSensitive, startModifiers, endModifiers,
                                                                            out partial);

                // Make sure "partial" is a keyword and not part of a longer identifier
                if (hasPartial)
                {
                    TokenIterator lookahead = partial;
                    lookahead.Next();

                    if (lookahead < endModifiers &&
                        (lookahead.FundamentalType == FundamentalType.Text ||
                         lookahead.Character == '_'))
                    {
                        hasPartial = false;
                    }

                    TokenIterator lookbehind = partial;
                    lookbehind.Previous();

                    if (lookbehind >= startModifiers &&
                        (lookbehind.FundamentalType == FundamentalType.Text ||
                         lookbehind.Character == '_'))
                    {
                        hasPartial = false;
                    }
                }

                // Add the modifiers sans-"partial"
                if (hasModifiers && hasPartial)
                {
                    if (partial > startModifiers)
                    {
                        TokenIterator lookbehind = partial;
                        lookbehind.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds);

                        AppendSyntaxHighlightedText(startModifiers, lookbehind, modifiersOutput);
                    }

                    partial.Next();
                    partial.NextPastWhitespace();

                    if (partial < endModifiers)
                    {
                        if (modifiersOutput.Length > 0)
                        {
                            modifiersOutput.Append(' ');
                        }

                        AppendSyntaxHighlightedText(partial, endModifiers, modifiersOutput);
                    }
                }
                else if (hasModifiers)
                {
                    AppendSyntaxHighlightedText(startModifiers, endModifiers, modifiersOutput);
                }

                // Add the keyword if it isn't "class"
                if (keyword != "class")
                {
                    if (modifiersOutput.Length > 0)
                    {
                        modifiersOutput.Append(' ');
                    }

                    AppendSyntaxHighlightedText(startKeyword, endKeyword, modifiersOutput);
                }

                if (modifiersOutput.Length > 0)
                {
                    output.Append("<div class=\"CPModifiers\">");
                    output.Append(modifiersOutput.ToString());
                    output.Append("</div>");
                }
            }


            // Name.  We use the fully resolved name in the symbol instead of the prototype name, which may just be the last segment.

            output.Append("<div class=\"CPName\">");

            AppendWrappedTitle(context.Topic.Symbol.FormatWithSeparator(language.MemberOperator), WrappedTitleMode.Code, output);

            TokenIterator startTemplate, endTemplate;

            if (parsedClassPrototype.GetTemplateSuffix(out startTemplate, out endTemplate))
            {
                // Include preceding whitespace if present, or a zero-width space for wrapping if not
                if (!startTemplate.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds))
                {
                    output.Append("&#8203;");
                }

                output.Append("<span class=\"TemplateSignature\">");
                AppendSyntaxHighlightedText(startTemplate, endTemplate, output);
                output.Append("</span>");
            }

            output.Append("</div>");


            // Post-prototype lines

            lineCount = parsedClassPrototype.NumberOfPostPrototypeLines;

            for (int i = 0; i < lineCount; i++)
            {
                parsedClassPrototype.GetPostPrototypeLine(i, out start, out end);

                output.Append("<div class=\"CPPostPrototypeLine\">");
                AppendSyntaxHighlightedText(start, end, output);
                output.Append("</div>");
            }

            output.Append("</div>");
        }
Example #10
0
        /* Function: RecalculateSections
         *
         * Recalculates the <Sections> list.  If you've set <MainSectionIndex> manually, it will have to be set again after calling this
         * function.
         *
         * Sections are delimited with <PrototypeParsingType.StartOfPrototypeSection> and <PrototypeParsingType.EndOfPrototypeSection>.
         * Neither of these token types are required to appear, and if they do not the entire prototype will be in one section.  Also, they are
         * not required to appear together.  Sections can be delimited by only start tokens or only end tokens, whichever is most convenient
         * to the language parser and won't interfere with marking other types.
         *
         * Each section containing <PrototypeParsingType.StartOfParams> will generate a <ParameterSection>.  All others will generate a
         * regular <Section>.
         */
        public void RecalculateSections()
        {
            if (sections == null)
            {
                sections = new List <Section>(1);
            }
            else
            {
                sections.Clear();
            }

            TokenIterator startOfSection = tokenizer.FirstToken;
            TokenIterator endOfSection   = startOfSection;

            int firstSectionWithName   = -1;
            int firstSectionWithParams = -1;

            for (;;)
            {
                // Find the section bounds

                bool sectionIsEmpty   = true;
                bool sectionHasName   = false;
                bool sectionHasParams = false;

                while (endOfSection.IsInBounds)
                {
                    // Break if we hit the beginning of the next section, but not if it's the start of the current section
                    if (endOfSection.PrototypeParsingType == PrototypeParsingType.StartOfPrototypeSection &&
                        endOfSection > startOfSection)
                    {
                        break;
                    }

                    if (endOfSection.FundamentalType != FundamentalType.Whitespace)
                    {
                        sectionIsEmpty = false;
                    }

                    if (endOfSection.PrototypeParsingType == PrototypeParsingType.Name)
                    {
                        sectionHasName = true;
                    }
                    else if (endOfSection.PrototypeParsingType == PrototypeParsingType.StartOfParams)
                    {
                        sectionHasParams = true;
                    }
                    else if (endOfSection.PrototypeParsingType == PrototypeParsingType.EndOfPrototypeSection)
                    {
                        endOfSection.Next();
                        break;
                    }

                    endOfSection.Next();
                }


                // Process the section

                if (!sectionIsEmpty)
                {
                    endOfSection.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, startOfSection);
                    startOfSection.NextPastWhitespace(endOfSection);

                    if (sectionHasParams)
                    {
                        sections.Add(new ParameterSection(startOfSection, endOfSection, supportsImpliedTypes));
                    }
                    else
                    {
                        sections.Add(new Section(startOfSection, endOfSection));
                    }

                    if (sectionHasName && firstSectionWithName == -1)
                    {
                        firstSectionWithName = sections.Count - 1;
                    }
                    if (sectionHasParams && firstSectionWithParams == -1)
                    {
                        firstSectionWithParams = sections.Count - 1;
                    }
                }


                // Continue?

                if (endOfSection.IsInBounds)
                {
                    startOfSection = endOfSection;
                }
                else
                {
                    break;
                }
            }


            // Sanity check.  This should only happen if all the sections were whitespace, which shouldn't normally happen but I
            // suppose could with a manual prototype.

            if (sections.Count < 1)
            {
                sections.Add(new Section(tokenizer.FirstToken, tokenizer.LastToken));
            }


            // Determine main section

            if (sections.Count == 1)
            {
                mainSectionIndex = 0;
            }
            else if (firstSectionWithName != -1)
            {
                mainSectionIndex = firstSectionWithName;
            }
            else if (firstSectionWithParams != -1)
            {
                mainSectionIndex = firstSectionWithParams;
            }
            else
            {
                mainSectionIndex = 0;
            }
        }
Example #11
0
        /* Function: CalculateSections
         */
        protected void CalculateSections()
        {
            sections = new List <Section>();
            Section section = null;

            TokenIterator iterator = tokenizer.FirstToken;

            iterator.NextPastWhitespace();


            // Pre-Prototype Lines

            while (iterator.IsInBounds &&
                   iterator.PrototypeParsingType == PrototypeParsingType.StartOfPrePrototypeLine)
            {
                section            = new Section();
                section.Type       = SectionType.PrePrototypeLine;
                section.StartIndex = iterator.TokenIndex;

                do
                {
                    iterator.Next();
                }while (iterator.IsInBounds &&
                        iterator.PrototypeParsingType == PrototypeParsingType.PrePrototypeLine);

                section.EndIndex = iterator.TokenIndex;
                sections.Add(section);

                iterator.NextPastWhitespace();
            }


            // Before Parameters

            section            = new Section();
            section.Type       = SectionType.BeforeParameters;
            section.StartIndex = iterator.TokenIndex;

            while (iterator.IsInBounds &&
                   iterator.PrototypeParsingType != PrototypeParsingType.StartOfParams &&
                   iterator.PrototypeParsingType != PrototypeParsingType.StartOfPostPrototypeLine)
            {
                iterator.Next();
            }


            if (iterator.PrototypeParsingType == PrototypeParsingType.StartOfParams)
            {
                // Include the StartOfParams symbol in the section
                iterator.Next();

                section.EndIndex = iterator.TokenIndex;
                sections.Add(section);

                iterator.NextPastWhitespace();


                // Parameters

                while (iterator.IsInBounds &&
                       iterator.PrototypeParsingType != PrototypeParsingType.EndOfParams &&
                       iterator.PrototypeParsingType != PrototypeParsingType.StartOfPostPrototypeLine)
                {
                    section            = new Section();
                    section.Type       = SectionType.Parameter;
                    section.StartIndex = iterator.TokenIndex;

                    while (iterator.IsInBounds &&
                           iterator.PrototypeParsingType != PrototypeParsingType.EndOfParams &&
                           iterator.PrototypeParsingType != PrototypeParsingType.ParamSeparator &&
                           iterator.PrototypeParsingType != PrototypeParsingType.StartOfPostPrototypeLine)
                    {
                        iterator.Next();
                    }

                    // Include the separator in the parameter block
                    if (iterator.PrototypeParsingType == PrototypeParsingType.ParamSeparator)
                    {
                        iterator.Next();
                        section.EndIndex = iterator.TokenIndex;
                    }
                    else
                    {
                        TokenIterator lookbehind = iterator;
                        lookbehind.PreviousPastWhitespace(PreviousPastWhitespaceMode.Iterator, iterator);
                        section.EndIndex = lookbehind.TokenIndex;
                    }

                    sections.Add(section);

                    iterator.NextPastWhitespace();
                }


                // After Parameters

                if (iterator.IsInBounds &&
                    iterator.PrototypeParsingType != PrototypeParsingType.StartOfPostPrototypeLine)
                {
                    section            = new Section();
                    section.Type       = SectionType.AfterParameters;
                    section.StartIndex = iterator.TokenIndex;

                    do
                    {
                        iterator.Next();
                    }while (iterator.IsInBounds &&
                            iterator.PrototypeParsingType != PrototypeParsingType.StartOfPostPrototypeLine);

                    TokenIterator lookbehind = iterator;
                    lookbehind.PreviousPastWhitespace(PreviousPastWhitespaceMode.Iterator, iterator);
                    section.EndIndex = lookbehind.TokenIndex;

                    sections.Add(section);
                }
            }

            else             // there was no StartOfParams
            {
                // We still have to finish the BeforeParameters section.
                TokenIterator lookbehind = iterator;
                lookbehind.PreviousPastWhitespace(PreviousPastWhitespaceMode.Iterator, iterator);
                section.EndIndex = lookbehind.TokenIndex;

                sections.Add(section);
            }


            // Post-Prototype Lines

            while (iterator.IsInBounds &&
                   iterator.PrototypeParsingType == PrototypeParsingType.StartOfPostPrototypeLine)
            {
                section            = new Section();
                section.Type       = SectionType.PostPrototypeLine;
                section.StartIndex = iterator.TokenIndex;

                do
                {
                    iterator.Next();
                }while (iterator.IsInBounds &&
                        iterator.PrototypeParsingType == PrototypeParsingType.PostPrototypeLine);

                section.EndIndex = iterator.TokenIndex;
                sections.Add(section);

                iterator.NextPastWhitespace();
            }
        }
Example #12
0
        /* Function: GetFullParameterType
         *
         * Returns the bounds of the type of the passed parameter, or false if it couldn't find it.  This includes modifiers and type
         * suffixes.  Since the type token may not be continuous, it returns separate start and end iterators for extra type modifiers
         * ("const" in "const x: integer") prefixes ("*" in "int *x") and suffixes ("[12]" in "int x[12]").  Regular modifiers attached to
         * the type ("unsigned" in "unsigned int x") will be accounted for by the main iterators.
         *
         * If the implied types flag is set this will return "int" for y in "int x, y".  If it is not then it will return false for y.
         */
        public bool GetFullParameterType(int index, out TokenIterator start, out TokenIterator end,
                                         out TokenIterator extraModifierStart, out TokenIterator extraModifierEnd,
                                         out TokenIterator prefixStart, out TokenIterator prefixEnd,
                                         out TokenIterator suffixStart, out TokenIterator suffixEnd,
                                         bool impliedTypes = true)
        {
            TokenIterator paramStart, paramEnd;

            if (!GetParameter(index, out paramStart, out paramEnd))
            {
                start = paramEnd;
                end   = paramEnd;
                extraModifierStart = paramEnd;
                extraModifierEnd   = paramEnd;
                prefixStart        = paramEnd;
                prefixEnd          = paramEnd;
                suffixStart        = paramEnd;
                suffixEnd          = paramEnd;
                return(false);
            }


            // Find the beginning of the type by finding the first type token

            start = paramStart;
            PrototypeParsingType type = start.PrototypeParsingType;

            while (start < paramEnd &&
                   type != PrototypeParsingType.Type &&
                   type != PrototypeParsingType.TypeModifier &&
                   type != PrototypeParsingType.TypeQualifier &&
                   type != PrototypeParsingType.NameModifier_PartOfType)
            {
                start.Next();
                type = start.PrototypeParsingType;
            }


            // If we're on a name modifier, get it and keep looking for the type

            if (type == PrototypeParsingType.NameModifier_PartOfType)
            {
                extraModifierStart = start;

                do
                {
                    start.Next();
                    type = start.PrototypeParsingType;
                }while (start < paramEnd &&
                        type == PrototypeParsingType.NameModifier_PartOfType);

                extraModifierEnd = start;

                // Search for the start again after the extra modifier

                while (start < paramEnd &&
                       type != PrototypeParsingType.Type &&
                       type != PrototypeParsingType.TypeModifier &&
                       type != PrototypeParsingType.TypeQualifier)
                {
                    start.Next();
                    type = start.PrototypeParsingType;
                }
            }
            else
            {
                extraModifierStart = paramEnd;
                extraModifierEnd   = paramEnd;
            }


            // If we found one, find the end of the type

            bool foundType = (start < paramEnd);

            end = start;

            if (foundType)
            {
                int nestLevel = 0;

                do
                {
                    if (end.PrototypeParsingType == PrototypeParsingType.OpeningTypeSuffix)
                    {
                        nestLevel++;
                    }
                    else if (end.PrototypeParsingType == PrototypeParsingType.ClosingTypeSuffix)
                    {
                        nestLevel--;
                    }

                    end.Next();
                    type = end.PrototypeParsingType;
                }while ((nestLevel > 0 ||
                         type == PrototypeParsingType.Type ||
                         type == PrototypeParsingType.TypeModifier ||
                         type == PrototypeParsingType.TypeQualifier ||
                         type == PrototypeParsingType.OpeningTypeSuffix ||
                         type == PrototypeParsingType.ClosingTypeSuffix ||
                         type == PrototypeParsingType.TypeSuffix ||
                         end.FundamentalType == FundamentalType.Whitespace) &&
                        end < paramEnd);

                end.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, start);
            }


            // See if we can fill it out with implied types

            if (impliedTypes)
            {
                if (Style == ParameterStyle.C)
                {
                    // If there's no type for a C parameter, move backwards for "int x, y"

                    if (!foundType)
                    {
                        TokenIterator ignoredA, ignoredB;

                        for (int i = index - 1; i >= 0; i--)
                        {
                            if (GetFullParameterType(i, out start, out end, out ignoredA, out ignoredB, out prefixStart, out prefixEnd,
                                                     out suffixStart, out suffixEnd, false))
                            {
                                foundType = true;
                                break;
                            }
                        }
                    }
                }

                else                 // Style == ParameterStyle.Pascal
                {
                    // If there's no type for a Pascal parameter, move forwards for "x, y: integer"

                    if (!foundType)
                    {
                        TokenIterator ignoredA, ignoredB;

                        for (int i = index + 1; i <= NumberOfParameters; i++)
                        {
                            if (GetFullParameterType(i, out start, out end, out ignoredA, out ignoredB, out prefixStart, out prefixEnd,
                                                     out suffixStart, out suffixEnd, false))
                            {
                                foundType = true;
                                break;
                            }
                        }
                    }


                    // If there's no extra modifiers for a Pascal parameter, move backwards for "const x, y: integer"

                    if (extraModifierEnd <= extraModifierStart)
                    {
                        TokenIterator prevParamIterator, prevParamEnd, prevExtraModifierStart, prevExtraModifierEnd;

                        for (int i = index - 1; i >= 0; i--)
                        {
                            // We can't use GetFullParameterType() here because it won't return anything if it doesn't find a type with
                            // implied types off, and turning implied types on means we can't detect when another type occurs which
                            // would mean we wouldn't want to inherit its modifiers ("const x: integer; y: integer").  So we do it manually
                            // with GetParameter().
                            GetParameter(i, out prevParamIterator, out prevParamEnd);
                            prevExtraModifierStart = prevParamEnd;
                            prevExtraModifierEnd   = prevParamEnd;
                            bool foundPrevExtraModifier = false;
                            bool foundPrevType          = false;

                            while (prevParamIterator < prevParamEnd)
                            {
                                if (prevParamIterator.PrototypeParsingType == PrototypeParsingType.NameModifier_PartOfType)
                                {
                                    if (!foundPrevExtraModifier)
                                    {
                                        prevExtraModifierStart = prevParamIterator;
                                        foundPrevExtraModifier = true;
                                    }

                                    prevParamIterator.Next();
                                    prevExtraModifierEnd = prevParamIterator;
                                }
                                else if (prevParamIterator.PrototypeParsingType == PrototypeParsingType.Type)
                                {
                                    foundPrevType = true;
                                    break;
                                }
                                else
                                {
                                    prevParamIterator.Next();
                                }
                            }

                            if (foundPrevType)
                            {
                                break;
                            }
                            else if (foundPrevExtraModifier)
                            {
                                extraModifierStart = prevExtraModifierStart;
                                extraModifierEnd   = prevExtraModifierEnd;
                                break;
                            }
                        }
                    }
                }
            }


            // If we found a type, explicit or implied, find the prefix and suffix.  We do this after checking for implied types because we
            // want "int a[12], b" to work.  b should be int, not int[12].  In "int *x, y", y should be int, not int*.

            if (foundType)
            {
                prefixStart = paramStart;

                while (prefixStart < paramEnd &&
                       prefixStart.PrototypeParsingType != PrototypeParsingType.NamePrefix_PartOfType)
                {
                    prefixStart.Next();
                }

                prefixEnd = prefixStart;

                while (prefixEnd < paramEnd &&
                       prefixEnd.PrototypeParsingType == PrototypeParsingType.NamePrefix_PartOfType)
                {
                    prefixEnd.Next();
                }

                suffixStart = paramStart;

                while (suffixStart < paramEnd &&
                       suffixStart.PrototypeParsingType != PrototypeParsingType.NameSuffix_PartOfType)
                {
                    suffixStart.Next();
                }

                suffixEnd = suffixStart;

                while (suffixEnd < paramEnd &&
                       suffixEnd.PrototypeParsingType == PrototypeParsingType.NameSuffix_PartOfType)
                {
                    suffixEnd.Next();
                }

                return(true);
            }

            else             // didn't find a type
            {
                start = paramEnd;
                end   = paramEnd;
                extraModifierStart = paramEnd;
                extraModifierEnd   = paramEnd;
                prefixStart        = paramEnd;
                prefixEnd          = paramEnd;
                suffixStart        = paramEnd;
                suffixEnd          = paramEnd;
                return(false);
            }
        }
Example #13
0
        /* Function: GetFullParameterType
         *
         * Returns the bounds of the type of the passed parameter, or false if it couldn't find it.  This includes modifiers and type
         * suffixes.  Since the type token may not be continuous, it returns separate start and end iterators for type prefixes
         * (* in "int *x") and suffixes ("[12]" in "int x[12]").
         *
         * If the implied types flag is set this will return "int" for y in "int x, y".  If it is not then it will return false for y.
         */
        public bool GetFullParameterType(int index, out TokenIterator start, out TokenIterator end,
                                         out TokenIterator prefixStart, out TokenIterator prefixEnd,
                                         out TokenIterator suffixStart, out TokenIterator suffixEnd,
                                         bool impliedTypes = true)
        {
            TokenIterator paramStart, paramEnd;

            if (!GetParameter(index, out paramStart, out paramEnd))
            {
                start       = paramEnd;
                end         = paramEnd;
                prefixStart = paramEnd;
                prefixEnd   = paramEnd;
                suffixStart = paramEnd;
                suffixEnd   = paramEnd;
                return(false);
            }


            // Find the beginning of the type by finding the first type token

            start = paramStart;
            PrototypeParsingType type = start.PrototypeParsingType;

            while (start < paramEnd &&
                   type != PrototypeParsingType.Type &&
                   type != PrototypeParsingType.TypeModifier &&
                   type != PrototypeParsingType.TypeQualifier)
            {
                start.Next();
                type = start.PrototypeParsingType;
            }


            // If we found one, find the end of the type

            bool foundType = (start < paramEnd);

            end = start;

            if (foundType)
            {
                int nestLevel = 0;

                do
                {
                    if (end.PrototypeParsingType == PrototypeParsingType.OpeningTypeSuffix)
                    {
                        nestLevel++;
                    }
                    else if (end.PrototypeParsingType == PrototypeParsingType.ClosingTypeSuffix)
                    {
                        nestLevel--;
                    }

                    end.Next();
                    type = end.PrototypeParsingType;
                }while ((nestLevel > 0 ||
                         type == PrototypeParsingType.Type ||
                         type == PrototypeParsingType.TypeModifier ||
                         type == PrototypeParsingType.TypeQualifier ||
                         type == PrototypeParsingType.OpeningTypeSuffix ||
                         type == PrototypeParsingType.ClosingTypeSuffix ||
                         type == PrototypeParsingType.TypeSuffix ||
                         end.FundamentalType == FundamentalType.Whitespace) &&
                        end < paramEnd);

                end.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, start);
            }


            // If we didn't find a type, see if it's implied

            else if (impliedTypes)
            {
                if (Style == ParameterStyle.C)
                {
                    // Move backwards for "int x, y"
                    for (int i = index - 1; i >= 0; i--)
                    {
                        if (GetFullParameterType(i, out start, out end, out prefixStart, out prefixEnd, out suffixStart, out suffixEnd, false))
                        {
                            foundType = true;
                            break;
                        }
                    }
                }
                else                 // Style == ParameterStyle.Pascal
                {
                    // Move forwards for "x, y: integer"
                    for (int i = index + 1; i <= NumberOfParameters; i++)
                    {
                        if (GetFullParameterType(i, out start, out end, out prefixStart, out prefixEnd, out suffixStart, out suffixEnd, false))
                        {
                            foundType = true;
                            break;
                        }
                    }
                }
            }


            // If we found a type, explicit or implied, find the prefix and suffix.  We do this after checking for implied types because we
            // want "int a[12], b" to work.  b should be int, not int[12].  In "int *x, y", y should be int, not int*.

            if (foundType)
            {
                prefixStart = paramStart;

                while (prefixStart < paramEnd &&
                       prefixStart.PrototypeParsingType != PrototypeParsingType.NamePrefix_PartOfType)
                {
                    prefixStart.Next();
                }

                prefixEnd = prefixStart;

                while (prefixEnd < paramEnd &&
                       prefixEnd.PrototypeParsingType == PrototypeParsingType.NamePrefix_PartOfType)
                {
                    prefixEnd.Next();
                }

                suffixStart = paramStart;

                while (suffixStart < paramEnd &&
                       suffixStart.PrototypeParsingType != PrototypeParsingType.NameSuffix_PartOfType)
                {
                    suffixStart.Next();
                }

                suffixEnd = suffixStart;

                while (suffixEnd < paramEnd &&
                       suffixEnd.PrototypeParsingType == PrototypeParsingType.NameSuffix_PartOfType)
                {
                    suffixEnd.Next();
                }

                return(true);
            }

            else             // didn't find a type
            {
                start       = paramEnd;
                end         = paramEnd;
                prefixStart = paramEnd;
                prefixEnd   = paramEnd;
                suffixStart = paramEnd;
                suffixEnd   = paramEnd;
                return(false);
            }
        }
Example #14
0
        /* Function: MarkParameter
         * Marks the tokens in the parameter specified by the bounds with <PrototypeParsingTypes>.
         */
        protected void MarkParameter(TokenIterator start, TokenIterator end)
        {
            // Pass 1: Count the number of "words" in the parameter prior to the default value and mark the default value
            // separator.  We'll figure out how to interpret the words in the second pass.

            int           words    = 0;
            TokenIterator iterator = start;

            while (iterator < end)
            {
                // Default values

                if (iterator.Character == '=')
                {
                    iterator.PrototypeParsingType = PrototypeParsingType.DefaultValueSeparator;
                    iterator.Next();

                    iterator.NextPastWhitespace(end);
                    TokenIterator endOfDefaultValue = end;

                    TokenIterator lookbehind = endOfDefaultValue;
                    lookbehind.Previous();

                    while (lookbehind >= iterator && lookbehind.PrototypeParsingType == PrototypeParsingType.ParamSeparator)
                    {
                        endOfDefaultValue = lookbehind;
                        lookbehind.Previous();
                    }

                    endOfDefaultValue.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, iterator);

                    if (iterator < endOfDefaultValue)
                    {
                        iterator.SetPrototypeParsingTypeBetween(endOfDefaultValue, PrototypeParsingType.DefaultValue);
                    }

                    break;
                }


                // Param separator

                else if (iterator.PrototypeParsingType == PrototypeParsingType.ParamSeparator)
                {
                    break;
                }


                // "Words" we're interested in

                else if (TryToSkipTypeOrVarName(ref iterator, end) ||
                         TryToSkipComment(ref iterator) ||
                         TryToSkipString(ref iterator) ||
                         TryToSkipBlock(ref iterator, true))
                {
                    // If there was a comment in the prototype, that means it specifically wasn't filtered out because it was something
                    // significant like a Splint comment or /*out*/.  Treat it like a modifier.

                    // Strings don't really make sense in the prototype until the default value, but we need the parser to handle it anyway
                    // just so it doesn't lose its mind if one occurs.

                    // If we come across a block that doesn't immediately follow an identifier, it may be something like a C# property so
                    // treat it as a modifier.

                    words++;
                }


                // Whitespace and any unexpected random symbols

                else
                {
                    iterator.Next();
                }
            }


            // Pass 2: Mark the "words" we counted from the first pass.  The order of words goes [modifier] [modifier] [type] [name],
            // starting from the right.  Typeless languages that only have one word will have it correctly interpreted as the name.

            iterator = start;
            TokenIterator wordStart, wordEnd;

            while (iterator < end)
            {
                wordStart = iterator;
                bool foundWord  = false;
                bool foundBlock = false;

                if (iterator.PrototypeParsingType == PrototypeParsingType.DefaultValueSeparator ||
                    iterator.PrototypeParsingType == PrototypeParsingType.ParamSeparator)
                {
                    break;
                }
                else if (TryToSkipTypeOrVarName(ref iterator, end))
                {
                    foundWord = true;
                }
                else if (TryToSkipComment(ref iterator) ||
                         TryToSkipString(ref iterator) ||
                         TryToSkipBlock(ref iterator, true))
                {
                    foundWord  = true;
                    foundBlock = true;
                }
                else
                {
                    iterator.Next();
                }

                // Process the word we found
                if (foundWord)
                {
                    wordEnd = iterator;

                    if (words >= 3)
                    {
                        if (foundBlock && wordEnd.TokenIndex - wordStart.TokenIndex >= 2)
                        {
                            wordStart.PrototypeParsingType = PrototypeParsingType.OpeningTypeModifier;

                            TokenIterator lookbehind = wordEnd;
                            lookbehind.Previous();
                            lookbehind.PrototypeParsingType = PrototypeParsingType.ClosingTypeModifier;
                        }
                        else
                        {
                            wordStart.SetPrototypeParsingTypeBetween(wordEnd, PrototypeParsingType.TypeModifier);
                        }
                    }
                    else if (words == 2)
                    {
                        MarkType(wordStart, wordEnd);
                    }
                    else if (words == 1)
                    {
                        MarkName(wordStart, wordEnd);

                        // Change the $ at the beginning of the name from a param modifier to part of the name
                        if (wordStart.Character == '$')
                        {
                            wordStart.PrototypeParsingType = PrototypeParsingType.Name;
                        }
                    }

                    words--;
                }
            }
        }