示例#1
0
        public void Visit(ParsedPrototype pars)
        {
            pars.ReturnType = ConvertStringToParsedPrimitiveType(pars.TempReturnType, false);

            // only visit IN prototypes (not FORWARD)
            if (pars.SimpleForward)
            {
                return;
            }

            // to code explorer
            PushToCodeExplorer(
                GetExplorerListNode("Function prototypes", CodeExplorerIconType.Prototype),
                new PrototypeCodeItem {
                DisplayText   = pars.Name,
                Flags         = pars.Flags,
                SubText       = null,
                DocumentOwner = pars.FilePath,
                GoToLine      = pars.Line,
                GoToColumn    = pars.Column
            });

            // to completion data
            PushToAutoCompletion(new FunctionCompletionItem {
                DisplayText = pars.Name,
                Flags       = pars.Flags,
                SubText     = pars.ReturnType.ToString()
            }, pars);
        }
示例#2
0
        /* Function: BuildPrototype
         *
         * Builds the HTML for the passed prototype.
         *
         * In order to have type links, links must be specified and contain any links that appear in the prototype.
         * linkTargets must also be specified and contain the target topics of all links.  If you do not need type
         * links, set both to null.
         *
         * Requirements:
         *
         *		- The <Context>'s topic must be set.
         *		- If type links are being generated, the <Context>'s page must also be set.
         */
        public string BuildPrototype(ParsedPrototype parsedPrototype, Context context, IList <Link> links = null,
                                     IList <Topics.Topic> linkTargets = null)
        {
            StringBuilder output = new StringBuilder();

            AppendPrototype(parsedPrototype, context, output, links, linkTargets);
            return(output.ToString());
        }
示例#3
0
        private bool DeletePrototypes(ref StringBuilder outputMessage, ParsedPrototype function)
        {
            DeleteCode(function);

            outputMessage.Append("<br> - " + function.Name);

            return(true);
        }
示例#4
0
        void AppendPostPrototypeLines(ParsedPrototype prototype, StringBuilder output)
        {
            int           numberOfLines = prototype.NumberOfPostPrototypeLines;
            TokenIterator start, end;

            for (int i = 0; i < numberOfLines; i++)
            {
                prototype.GetPostPrototypeLine(i, out start, out end);
                output.Append("  - Post-Prototype Line: ");
                prototype.Tokenizer.AppendTextBetweenTo(start, end, output);
                output.AppendLine();
            }
        }
示例#5
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);
        }
示例#6
0
        /* Function: AppendPrototype
         *
         * Builds the HTML for the passed prototype and appends it to the passed StringBuilder.
         *
         * In order to have type links, links must be specified and contain any links that appear in the prototype.
         * linkTargets must also be specified and contain the target topics of all links.  If you do not need type
         * links, set both to null.
         *
         * Requirements:
         *
         *		- The <Context>'s topic must be set.
         *		- If type links are being generated, the <Context>'s page must also be set.
         */
        public void AppendPrototype(ParsedPrototype parsedPrototype, Context context, StringBuilder output,
                                    IList <Link> links = null, IList <Topics.Topic> linkTargets = null)
        {
            this.parsedPrototype = parsedPrototype;
            this.context         = context;

                        #if DEBUG
            if (context.Topic == null)
            {
                throw new Exception("Tried to generate a prototype when the context's topic was not set.");
            }
                        #endif

            this.links       = links;
            this.linkTargets = linkTargets;
            this.addLinks    = (links != null && linkTargets != null);

                        #if DEBUG
            if (this.addLinks && context.Page.IsNull)
            {
                throw new Exception("Tried to generate a prototype with type links when the context's page was not set.");
            }
                        #endif

            if (parsedPrototype.Tokenizer.HasSyntaxHighlighting == false)
            {
                var language = EngineInstance.Languages.FromID(Context.Topic.LanguageID);
                language.SyntaxHighlight(parsedPrototype);
            }

            // Determine if there's parameters anywhere.  It's possible for parsedPrototype.NumberOfParameters to be zero and
            // there still be a parameters section present somewhere such as for SQL's return table definitions.
            bool hasParameters = false;

            foreach (var section in parsedPrototype.Sections)
            {
                if (section is Prototypes.ParameterSection && (section as Prototypes.ParameterSection).NumberOfParameters > 0)
                {
                    hasParameters = true;
                    break;
                }
            }

            // We always build the wide form by default, but only include the attribute if there's parameters.  The JavaScript assumes
            // there will be a parameters section in any prototype that has it.
            output.Append("<div id=\"NDPrototype" + Context.Topic.TopicID + "\" class=\"NDPrototype" +
                          (hasParameters ? " WideForm" : "") + "\">");

            foreach (var section in parsedPrototype.Sections)
            {
                if (section is Prototypes.ParameterSection && (section as Prototypes.ParameterSection).NumberOfParameters > 0)
                {
                    AppendParameterSection((Prototypes.ParameterSection)section, output);
                }
                else
                {
                    AppendPlainSection(section, output);
                }
            }

            output.Append("</div>");
        }
示例#7
0
 public void Visit(ParsedPrototype pars)
 {
     AppendEverything(pars);
 }
示例#8
0
        /// <summary>
        /// Matches a function definition (not the FORWARD prototype)
        /// </summary>
        private ParsedFunction CreateParsedFunction(Token functionToken)
        {
            // info we will extract from the current statement :
            string               name             = null;
            string               parsedReturnType = null;
            int                  extent           = 0;
            ParseFlag            flags            = 0;
            StringBuilder        parameters       = new StringBuilder();
            List <ParsedDefine>  parametersList   = null;
            ParsedImplementation createdImp       = null;

            _lastTokenWasSpace = true;

            Token token;
            int   state = 0;

            do
            {
                token = PeekAt(1); // next token
                if (token is TokenEos)
                {
                    break;
                }
                if (token is TokenComment)
                {
                    continue;
                }
                switch (state)
                {
                case 0:
                    // matching name
                    if (!(token is TokenWord))
                    {
                        break;
                    }
                    name = token.Value;
                    state++;
                    break;

                case 1:
                    // matching return type
                    if (!(token is TokenWord))
                    {
                        break;
                    }
                    if (token.Value.EqualsCi("returns") || token.Value.EqualsCi("class"))
                    {
                        continue;
                    }

                    parsedReturnType = token.Value;

                    state++;
                    break;

                case 2:
                    // matching parameters (start)
                    if (token is TokenWord)
                    {
                        if (token.Value.EqualsCi("private"))
                        {
                            flags |= ParseFlag.Private;
                        }
                        if (token.Value.EqualsCi("extent"))
                        {
                            extent = GetExtentNumber(2);
                        }

                        // we didn't match any opening (, but we found a forward
                        if (token.Value.EqualsCi("forward"))
                        {
                            state = 99;
                        }
                        else if (token.Value.EqualsCi("in"))
                        {
                            state = 100;
                        }
                    }
                    else if (token is TokenSymbol && token.Value.Equals("("))
                    {
                        state = 3;
                    }
                    break;

                case 3:
                    // read parameters, define a ParsedDefineItem for each
                    parametersList = GetParsedParameters(functionToken, parameters);
                    state          = 10;
                    break;

                case 10:
                    // matching prototype, we dont want to create a ParsedItem for prototype
                    if (token is TokenWord)
                    {
                        if (token.Value.EqualsCi("forward"))
                        {
                            state = 99;
                        }
                        else if (token.Value.EqualsCi("in"))
                        {
                            state = 100;
                        }
                    }
                    break;
                }
            } while (MoveNext());
            if (name == null || parsedReturnType == null)
            {
                return(null);
            }

            // otherwise it needs to ends with : or .
            if (!(token is TokenEos))
            {
                return(null);
            }



            // New prototype, we matched a forward or a IN
            if (state >= 99)
            {
                ParsedPrototype createdProto = new ParsedPrototype(name, functionToken, parsedReturnType)
                {
                    Scope            = GetCurrentBlock <ParsedScopeBlock>(),
                    FilePath         = FilePathBeingParsed,
                    SimpleForward    = state == 99, // allows us to know if we expect an implementation in this .p or not
                    EndPosition      = token.EndPosition,
                    EndBlockLine     = token.Line,
                    EndBlockPosition = token.EndPosition,
                    Flags            = flags,
                    Extent           = extent,
                    ParametersString = parameters.ToString()
                };
                if (!_functionPrototype.ContainsKey(name))
                {
                    _functionPrototype.Add(name, createdProto);
                }

                AddParsedItem(createdProto, functionToken.OwnerNumber);

                // case of a IN
                if (!createdProto.SimpleForward)
                {
                    // add the parameters to the list
                    if (parametersList != null)
                    {
                        createdProto.Parameters = new List <ParsedDefine>();
                        foreach (var parsedItem in parametersList)
                        {
                            createdProto.Parameters.Add(parsedItem);
                        }
                    }
                }
            }
            else
            {
                // New function
                createdImp = new ParsedImplementation(name, functionToken, parsedReturnType)
                {
                    EndPosition      = token.EndPosition,
                    Flags            = flags,
                    Extent           = extent,
                    ParametersString = parameters.ToString()
                };

                // it has a prototype?
                if (_functionPrototype.ContainsKey(name))
                {
                    // make sure it was a prototype!
                    var proto = _functionPrototype[name] as ParsedPrototype;
                    if (proto != null && proto.SimpleForward)
                    {
                        createdImp.HasPrototype         = true;
                        createdImp.PrototypeLine        = proto.Line;
                        createdImp.PrototypeColumn      = proto.Column;
                        createdImp.PrototypePosition    = proto.Position;
                        createdImp.PrototypeEndPosition = proto.EndPosition;

                        // boolean to know if the implementation matches the prototype
                        createdImp.PrototypeUpdated = (
                            createdImp.Flags == proto.Flags &&
                            createdImp.Extent.Equals(proto.Extent) &&
                            createdImp.TempReturnType.EqualsCi(proto.TempReturnType) &&
                            createdImp.ParametersString.EqualsCi(proto.ParametersString));
                    }
                }
                else
                {
                    _functionPrototype.Add(name, createdImp);
                }

                // add the parameters to the list
                if (parametersList != null)
                {
                    createdImp.Parameters = new List <ParsedDefine>();
                    foreach (var parsedItem in parametersList)
                    {
                        createdImp.Parameters.Add(parsedItem);
                    }
                }

                AddParsedItem(createdImp, functionToken.OwnerNumber);
            }

            return(createdImp);
        }
示例#9
0
        /* Function: ScoreParameter
         * Returns a two bit value representing how well the parameters match, or -1 if they match so poorly that the link and
         * the target shouldn't be considered a match at all.
         */
        private long ScoreParameter(ParsedPrototype prototype, ParameterString linkParameters, int index, bool ignoreCase)
        {
            // -1 - The link has a parameter but the prototype does not.
            // 00 - The prototype has a parameter but the link does not.  This allows links on partial parameters.
            // 00 - They both have parameters but do not match at all.
            // 01 - The link doesn't have a parameter but the prototype has one with a default value set.
            // 10 - The parameters match except for qualifiers or modifiers like "unsigned".
            // 11 - The parameters match completely, by type or by name, or both don't exist.

            SimpleTokenIterator linkParamStart, linkParamEnd;
            TokenIterator       prototypeParamStart, prototypeParamEnd;

            bool hasLinkParam = linkParameters.GetParameter(index, out linkParamStart, out linkParamEnd);
            bool hasPrototypeParam;

            if (prototype == null)
            {
                hasPrototypeParam = false;

                // To shut the compiler up.
                prototypeParamStart = new TokenIterator();
                prototypeParamEnd   = new TokenIterator();
            }
            else
            {
                hasPrototypeParam = prototype.GetParameter(index, out prototypeParamStart, out prototypeParamEnd);
            }

            if (!hasLinkParam)
            {
                if (!hasPrototypeParam)
                {
                    return(3);
                }
                else
                {
                    // There is a prototype parameter but not a link parameter.  This will be 0 or 1 depending on whether the
                    // prototype parameter has a default value.

                    while (prototypeParamStart < prototypeParamEnd)
                    {
                        if (prototypeParamStart.PrototypeParsingType == PrototypeParsingType.DefaultValue)
                        {
                            return(1);
                        }

                        prototypeParamStart.Next();
                    }

                    return(0);
                }
            }

            else             // hasLinkParam == true
            {
                if (hasPrototypeParam == false)
                {
                    return(-1);
                }

                // Both the link and the prototype have parameters at index.

                bool typeMatch            = false;
                bool typeMismatch         = false;
                bool typeModifierMismatch = false;
                bool nameMatch            = false;
                bool nameMismatch         = false;

                int modifierBlockLevel = 0;

                while (prototypeParamStart < prototypeParamEnd)
                {
                    var type = prototypeParamStart.PrototypeParsingType;

                    // We want any mismatches that occur nested in type modifier blocks to be scored as a modifier mismatch.
                    if (type == PrototypeParsingType.OpeningTypeModifier ||
                        type == PrototypeParsingType.OpeningParamModifier)
                    {
                        modifierBlockLevel++;
                    }
                    else if (type == PrototypeParsingType.ClosingTypeModifier ||
                             type == PrototypeParsingType.ClosingParamModifier)
                    {
                        modifierBlockLevel--;
                    }
                    else if (modifierBlockLevel > 0)
                    {
                        type = PrototypeParsingType.TypeModifier;
                    }

                    switch (type)
                    {
                    case PrototypeParsingType.TypeModifier:
                    case PrototypeParsingType.TypeQualifier:
                    case PrototypeParsingType.OpeningTypeModifier:
                    case PrototypeParsingType.ClosingTypeModifier:
                    case PrototypeParsingType.ParamModifier:
                    case PrototypeParsingType.OpeningParamModifier:
                    case PrototypeParsingType.ClosingParamModifier:

                        if (linkParamStart < linkParamEnd && linkParamStart.MatchesToken(prototypeParamStart, ignoreCase))
                        {
                            linkParamStart.Next();
                            linkParamStart.NextPastWhitespace();
                        }
                        else
                        {
                            typeModifierMismatch = true;
                        }
                        break;

                    case PrototypeParsingType.Type:

                        if (linkParamStart < linkParamEnd && linkParamStart.MatchesToken(prototypeParamStart, ignoreCase))
                        {
                            typeMatch = true;

                            linkParamStart.Next();
                            linkParamStart.NextPastWhitespace();
                        }
                        else
                        {
                            typeMismatch = true;
                        }
                        break;

                    case PrototypeParsingType.Name:

                        if (linkParamStart < linkParamEnd && linkParamStart.MatchesToken(prototypeParamStart, ignoreCase))
                        {
                            nameMatch = true;

                            linkParamStart.Next();
                            linkParamStart.NextPastWhitespace();
                        }
                        else
                        {
                            nameMismatch = true;
                        }
                        break;
                    }

                    prototypeParamStart.Next();
                    prototypeParamStart.NextPastWhitespace();
                }

                if (linkParamStart < linkParamEnd)
                {
                    return(0);
                }
                if (nameMatch && !nameMismatch)
                {
                    return(3);
                }
                if (typeMatch && !typeMismatch)
                {
                    if (!typeModifierMismatch)
                    {
                        return(3);
                    }
                    else
                    {
                        return(2);
                    }
                }

                return(0);
            }
        }
示例#10
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);
            TokenIterator iterator           = tokenizedPrototype.FirstToken;

            ParsedPrototype parsedPrototype;


            // Search for the first opening parenthesis.

            while (iterator.IsInBounds)
            {
                if (iterator.Character == '(')
                {
                    break;
                }
                else if (TryToSkipComment(ref iterator) ||
                         TryToSkipString(ref iterator))
                {
                }
                else
                {
                    iterator.Next();
                }
            }


            // If we found parentheses, it's a function prototype.  Mark the delimiters.

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

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

                    else if (iterator.Character == ')')
                    {
                        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, supportsImpliedTypes: false);


                // 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)
                {
                    MarkParameter(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);
                        MarkParameter(start, end);
                    }
                }
            }


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

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

                MarkParameter(start, end);
            }

            return(parsedPrototype);
        }