Example #1
0
        /* Function: Start_CantDefinePropertyError
         * A helper function used only by <Start()> and its other helper functions which adds an error saying the passed
         * property cannot be defined for the current language type.
         */
        private void Start_CantDefinePropertyError(ConfigFileLanguage configFileLanguage, Language.LanguageType type,
                                                   Path sourceFile, string propertyName, Errors.ErrorList errorList)
        {
            string typeString;

            if (type == Language.LanguageType.TextFile)
            {
                typeString = "TextFiles";
            }
            else if (type == Language.LanguageType.Container)
            {
                typeString = "Containers";
            }
            else if (type == Language.LanguageType.FullSupport)
            {
                typeString = "FullLanguageSupport";
            }
            else             // BasicSupport
            {
                typeString = "BasicLanguageSupport";
            }

            errorList.Add(
                Locale.Get("NaturalDocs.Engine", "Languages.txt.CantDefinePropertyFor" + typeString + "(property, language)",
                           propertyName, configFileLanguage.Name),
                sourceFile, configFileLanguage.LineNumber
                );
        }
Example #2
0
        // Group: Loading Functions
        // __________________________________________________________________________


        /* Function: Load
         *
         * Loads the configuration file and parses it.  Redundant information will be simplified out, such as an Alter
         * Language section that applies to a language defined in the same file.
         *
         * Parameters:
         *
         *		filename - The <Path> where the file is located.
         *		fileLanguages - Returns a list of <ConfigFileLanguages> in no particular order.
         *		fileIgnoredExtensions - Returns any ignored extensions as a string array.
         *		errorList - If it couldn't successfully parse the file it will add error messages to this list.
         *
         * Returns:
         *
         *		Whether it was able to successfully load and parse the file without any errors.
         */
        public bool Load(Path filename, out List <ConfigFileLanguage> fileLanguages,
                         out List <string> fileIgnoredExtensions, Errors.ErrorList errorList)
        {
            fileLanguages         = new List <ConfigFileLanguage>();
            fileIgnoredExtensions = new List <string>();
            StringTable <ConfigFileLanguage> fileLanguageNames =
                new StringTable <ConfigFileLanguage>(Engine.Languages.Manager.KeySettingsForLanguageName);

            int previousErrorCount = errorList.Count;

            using (ConfigFile file = new ConfigFile())
            {
                // Can't make identifiers lowercase here or we'd lose the case of the comment type in prototype ender lines.
                bool openResult = file.Open(filename,
                                            ConfigFile.FileFormatFlags.CondenseIdentifierWhitespace |
                                            ConfigFile.FileFormatFlags.CondenseValueWhitespace,
                                            errorList);

                if (openResult == false)
                {
                    return(false);
                }

                string             identifier, lcIdentifier, value;
                ConfigFileLanguage currentLanguage = null;

                // We need this in addition to ConfigFileLanguage.AlterLanguage because an entry altering a type defined in the
                // same file would be combined into the original, yet we still need to know if that entry is Alter to properly
                // detect whether we need to use Add/Replace with certain properties.
                bool alterCurrentLanguage = false;

                char[] space = { ' ' };

                System.Text.RegularExpressions.Match match;


                while (file.Get(out identifier, out value))
                {
                    lcIdentifier = identifier.ToLower();

                    //
                    // Ignore Extensions
                    //

                    if (ignoreExtensionsRegex.IsMatch(lcIdentifier))
                    {
                        currentLanguage = null;

                        string[] ignoredExtensionsArray = value.Split(space);
                        fileIgnoredExtensions.AddRange(ignoredExtensionsArray);
                    }


                    //
                    // Language
                    //

                    else if (lcIdentifier == "language")
                    {
                        if (fileLanguageNames.ContainsKey(value))
                        {
                            file.AddError(
                                Locale.Get("NaturalDocs.Engine", "Languages.txt.LanguageAlreadyExists(name)", value)
                                );

                            // Continue parsing.  We'll throw this into the existing language even though it shouldn't be overwriting
                            // its values because we want to find any other errors there are in the file.
                            currentLanguage      = fileLanguageNames[value];
                            alterCurrentLanguage = false;
                        }

                        else
                        {
                            currentLanguage      = new ConfigFileLanguage(value, false, file.LineNumber);
                            alterCurrentLanguage = false;
                            fileLanguages.Add(currentLanguage);
                            fileLanguageNames.Add(value, currentLanguage);
                        }
                    }



                    //
                    // Alter Language
                    //

                    else if (alterLanguageRegex.IsMatch(lcIdentifier))
                    {
                        // If this language already exists, collapse it into the current definition.
                        if (fileLanguageNames.ContainsKey(value))
                        {
                            currentLanguage      = fileLanguageNames[value];
                            alterCurrentLanguage = true;
                        }

                        // If it doesn't exist, create the new language anyway with the alter flag set because it may exist in another
                        // file.
                        else
                        {
                            currentLanguage      = new ConfigFileLanguage(value, true, file.LineNumber);
                            alterCurrentLanguage = true;
                            fileLanguages.Add(currentLanguage);
                            fileLanguageNames.Add(value, currentLanguage);
                        }
                    }


                    //
                    // Aliases
                    //

                    else if (aliasesRegex.IsMatch(lcIdentifier))
                    {
                        if (currentLanguage == null)
                        {
                            NeedsLanguageError(file, identifier);
                        }
                        else if (alterCurrentLanguage == true)
                        {
                            file.AddError(
                                Locale.Get("NaturalDocs.Engine", "Languages.txt.NeedAddReplaceWhenAlteringLanguage(keyword)", "Aliases")
                                );
                        }
                        else
                        {
                            currentLanguage.Aliases    = value.Split(space);
                            currentLanguage.AddAliases = false;
                        }
                    }


                    //
                    // Add/Replace Aliases
                    //

                    else if ((match = addReplaceAliasesRegex.Match(lcIdentifier)) != null && match.Success)
                    {
                        if (currentLanguage == null)
                        {
                            NeedsLanguageError(file, identifier);
                        }

                        else if (alterCurrentLanguage == true && match.Groups[1].Value == "add" &&
                                 currentLanguage.Aliases != null)
                        {
                            string[] addAliases = value.Split(space);
                            string[] newAliases = new string[addAliases.Length + currentLanguage.Aliases.Length];

                            currentLanguage.Aliases.CopyTo(newAliases, 0);
                            addAliases.CopyTo(newAliases, currentLanguage.Aliases.Length);

                            currentLanguage.Aliases    = newAliases;
                            currentLanguage.AddAliases = true;
                        }

                        // Covers "replace" when altering a language, "add" and "replace" when not altering a language (no point
                        // in adding an error when we can just tolerate it, and "replace" when altering a language that doesn't have
                        // anything defined.
                        else
                        {
                            currentLanguage.Aliases    = value.Split(space);
                            currentLanguage.AddAliases = (match.Groups[1].Value == "add");
                        }
                    }



                    //
                    // Extensions
                    //

                    else if (extensionsRegex.IsMatch(lcIdentifier))
                    {
                        if (currentLanguage == null)
                        {
                            NeedsLanguageError(file, identifier);
                        }
                        else if (alterCurrentLanguage == true)
                        {
                            file.AddError(
                                Locale.Get("NaturalDocs.Engine", "Languages.txt.NeedAddReplaceWhenAlteringLanguage(keyword)", "Extensions")
                                );
                        }
                        else
                        {
                            currentLanguage.Extensions    = value.Split(space);
                            currentLanguage.AddExtensions = false;
                        }
                    }


                    //
                    // Add/Replace Extensions
                    //

                    else if ((match = addReplaceExtensionsRegex.Match(lcIdentifier)) != null && match.Success)
                    {
                        if (currentLanguage == null)
                        {
                            NeedsLanguageError(file, identifier);
                        }

                        else if (alterCurrentLanguage == true && match.Groups[1].Value == "add" &&
                                 currentLanguage.Extensions != null)
                        {
                            string[] addExtensions = value.Split(space);
                            string[] newExtensions = new string[addExtensions.Length + currentLanguage.Extensions.Length];

                            currentLanguage.Extensions.CopyTo(newExtensions, 0);
                            addExtensions.CopyTo(newExtensions, currentLanguage.Extensions.Length);

                            currentLanguage.Extensions    = newExtensions;
                            currentLanguage.AddExtensions = true;
                        }

                        // Covers "replace" when altering a language, "add" and "replace" when not altering a language (no point
                        // in adding an error when we can just tolerate it, and "replace" when altering a language that doesn't have
                        // anything defined.
                        else
                        {
                            currentLanguage.Extensions    = value.Split(space);
                            currentLanguage.AddExtensions = (match.Groups[1].Value == "add");
                        }
                    }



                    //
                    // Shebang Strings
                    //

                    else if (shebangStringsRegex.IsMatch(lcIdentifier))
                    {
                        if (currentLanguage == null)
                        {
                            NeedsLanguageError(file, identifier);
                        }
                        else if (alterCurrentLanguage == true)
                        {
                            file.AddError(
                                Locale.Get("NaturalDocs.Engine", "Languages.txt.NeedAddReplaceWhenAlteringLanguage(keyword)", "Shebang Strings")
                                );
                        }
                        else
                        {
                            currentLanguage.ShebangStrings    = value.Split(space);
                            currentLanguage.AddShebangStrings = false;
                        }
                    }


                    //
                    // Add/Replace Shebang Strings
                    //

                    else if ((match = addReplaceShebangStringsRegex.Match(lcIdentifier)) != null && match.Success)
                    {
                        if (currentLanguage == null)
                        {
                            NeedsLanguageError(file, identifier);
                        }

                        else if (alterCurrentLanguage == true && match.Groups[1].Value == "add" &&
                                 currentLanguage.ShebangStrings != null)
                        {
                            string[] addShebangStrings = value.Split(space);
                            string[] newShebangStrings = new string[addShebangStrings.Length +
                                                                    currentLanguage.ShebangStrings.Length];

                            currentLanguage.ShebangStrings.CopyTo(newShebangStrings, 0);
                            addShebangStrings.CopyTo(newShebangStrings, currentLanguage.ShebangStrings.Length);

                            currentLanguage.ShebangStrings    = newShebangStrings;
                            currentLanguage.AddShebangStrings = true;
                        }

                        // Covers "replace" when altering a language, "add" and "replace" when not altering a language (no point
                        // in adding an error when we can just tolerate it, and "replace" when altering a language that doesn't have
                        // anything defined.
                        else
                        {
                            currentLanguage.ShebangStrings    = value.Split(space);
                            currentLanguage.AddShebangStrings = (match.Groups[1].Value == "add");
                        }
                    }



                    //
                    // Simple Identifier
                    //

                    else if (lcIdentifier == "simple identifier")
                    {
                        if (currentLanguage == null)
                        {
                            NeedsLanguageError(file, identifier);
                        }
                        else if (nonASCIILettersRegex.IsMatch(value))
                        {
                            file.AddError(
                                Locale.Get("NaturalDocs.Engine", "Languages.txt.SimpleIdentifierMustOnlyBeASCIILetters(name)", value)
                                );
                        }
                        else
                        {
                            currentLanguage.SimpleIdentifier = value;
                        }
                    }



                    //
                    // Line Comments
                    //

                    else if (lineCommentsRegex.IsMatch(lcIdentifier))
                    {
                        if (currentLanguage == null)
                        {
                            NeedsLanguageError(file, identifier);
                        }
                        else
                        {
                            currentLanguage.LineCommentStrings = value.Split(space);
                        }
                    }



                    //
                    // Block Comments
                    //

                    else if (blockCommentsRegex.IsMatch(lcIdentifier))
                    {
                        if (currentLanguage == null)
                        {
                            NeedsLanguageError(file, identifier);
                        }
                        else
                        {
                            string[] newBlockCommentStrings = value.Split(space);

                            if (newBlockCommentStrings.Length % 2 != 0)
                            {
                                file.AddError(
                                    Locale.Get("NaturalDocs.Engine", "Languages.txt.BlockCommentsMustHaveAnEvenNumberOfSymbols")
                                    );
                            }
                            else
                            {
                                currentLanguage.BlockCommentStringPairs = newBlockCommentStrings;
                            }
                        }
                    }



                    //
                    // Member Operator
                    //

                    else if (memberOperatorRegex.IsMatch(lcIdentifier))
                    {
                        if (currentLanguage == null)
                        {
                            NeedsLanguageError(file, identifier);
                        }
                        else
                        {
                            currentLanguage.MemberOperator = value;
                        }
                    }



                    //
                    // Line Extender
                    //

                    else if (lcIdentifier == "line extender")
                    {
                        if (currentLanguage == null)
                        {
                            NeedsLanguageError(file, identifier);
                        }
                        else
                        {
                            currentLanguage.LineExtender = value;
                        }
                    }



                    //
                    // Enum Values
                    //

                    else if (enumValuesRegex.IsMatch(lcIdentifier))
                    {
                        string lcValue = value.ToLower();

                        if (currentLanguage == null)
                        {
                            NeedsLanguageError(file, identifier);
                        }
                        else if (lcValue == "global")
                        {
                            currentLanguage.EnumValue = Language.EnumValues.Global;
                        }
                        else if (lcValue == "under type")
                        {
                            currentLanguage.EnumValue = Language.EnumValues.UnderType;
                        }
                        else if (lcValue == "under parent")
                        {
                            currentLanguage.EnumValue = Language.EnumValues.UnderParent;
                        }
                        else
                        {
                            file.AddError(
                                Locale.Get("NaturalDocs.Engine", "Languages.txt.InvalidEnumValue(value)", value)
                                );
                        }
                    }


                    //
                    // Case Sensitive
                    //

                    else if (caseSensitiveRegex.IsMatch(lcIdentifier))
                    {
                        string lcValue = value.ToLower();

                        if (currentLanguage == null)
                        {
                            NeedsLanguageError(file, identifier);
                        }
                        else if (yesRegex.IsMatch(lcValue))
                        {
                            currentLanguage.CaseSensitive = true;
                        }
                        else if (noRegex.IsMatch(lcValue))
                        {
                            currentLanguage.CaseSensitive = false;
                        }
                        else
                        {
                            file.AddError(
                                Locale.Get("NaturalDocs.Engine", "Languages.txt.UnrecognizedValue(keyword, value)", "Case Sensitive", value)
                                );
                        }
                    }


                    //
                    // Prototype Enders
                    //

                    // Use identifier and not lcIdentifier to keep the case of the comment type.  The regex will compensate.
                    else if ((match = prototypeEndersRegex.Match(identifier)) != null && match.Success)
                    {
                        if (currentLanguage == null)
                        {
                            NeedsLanguageError(file, identifier);
                        }
                        else
                        {
                            string   commentType  = match.Groups[1].Value;
                            string[] enderStrings = value.Split(space);

                            currentLanguage.SetPrototypeEnderStrings(commentType, enderStrings);
                        }
                    }


                    //
                    // Deprecated keywords
                    //

                    else if (ignorePrefixesRegex.IsMatch(lcIdentifier) ||
                             lcIdentifier == "perl package" || lcIdentifier == "full language support")
                    {
                        // Ignore
                    }


                    //
                    // Unrecognized keywords
                    //

                    else
                    {
                        file.AddError(
                            Locale.Get("NaturalDocs.Engine", "Languages.txt.UnrecognizedKeyword(keyword)", identifier)
                            );
                    }
                }                          // while (file.Get)

                file.Close();
            }


            if (errorList.Count == previousErrorCount)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #3
0
        /* Function: Start_AddLanguage
         * A helper function that is used only by <Start()> to add a <ConfigFileLanguage> into <languages>.
         * Returns whether it was able to do so without any errors.
         */
        private bool Start_AddLanguage(ConfigFileLanguage configFileLanguage, Path sourceFile, bool isSystemFile,
                                       StringSet ignoredExtensions, Errors.ErrorList errorList)
        {
            bool success = true;


            // Validate or create the language.

            if (configFileLanguage.AlterLanguage == true)
            {
                // If altering a language that doesn't exist at all, at least not in the config files...
                if (languages.Contains(configFileLanguage.Name) == false ||
                    languages[configFileLanguage.Name].InConfigFiles == false)
                {
                    errorList.Add(
                        Locale.Get("NaturalDocs.Engine", "Languages.txt.AlteredLanguageDoesntExist(name)", configFileLanguage.Name),
                        sourceFile, configFileLanguage.LineNumber
                        );

                    success = false;
                }
            }

            else             // define language, not alter
            {
                // Error if defining a language that already exists in the config files.  Having it exist otherwise is fine.
                if (languages.Contains(configFileLanguage.Name))
                {
                    if (languages[configFileLanguage.Name].InConfigFiles == true)
                    {
                        errorList.Add(
                            Locale.Get("NaturalDocs.Engine", "Languages.txt.LanguageAlreadyExists(name)", configFileLanguage.Name),
                            sourceFile, configFileLanguage.LineNumber
                            );

                        success = false;
                    }
                }
                else
                {
                    Language newLanguage = new Language(this, configFileLanguage.Name);
                    languages.Add(newLanguage);
                }

                if (isSystemFile)
                {
                    languages[configFileLanguage.Name].InSystemFile = true;
                }
                else
                {
                    languages[configFileLanguage.Name].InProjectFile = true;
                }
            }

            if (success == false)
            {
                return(false);
            }


            // Apply the properties.

            Language language = languages[configFileLanguage.Name];

            if (configFileLanguage.SimpleIdentifier != null)
            {
                language.SimpleIdentifier = configFileLanguage.SimpleIdentifier;
            }

            if (configFileLanguage.LineCommentStrings != null)
            {
                if (language.Type != Language.LanguageType.BasicSupport)
                {
                    Start_CantDefinePropertyError(configFileLanguage, language.Type, sourceFile, "Line Comment", errorList);
                    success = false;
                }
                else
                {
                    language.LineCommentStrings = configFileLanguage.LineCommentStrings;
                }
            }

            if (configFileLanguage.BlockCommentStringPairs != null)
            {
                if (language.Type != Language.LanguageType.BasicSupport)
                {
                    Start_CantDefinePropertyError(configFileLanguage, language.Type, sourceFile, "Block Comment", errorList);
                    success = false;
                }
                else
                {
                    language.BlockCommentStringPairs = configFileLanguage.BlockCommentStringPairs;
                }
            }

            if (configFileLanguage.MemberOperator != null)
            {
                if (language.Type != Language.LanguageType.BasicSupport && language.Type != Language.LanguageType.TextFile)
                {
                    Start_CantDefinePropertyError(configFileLanguage, language.Type, sourceFile, "Member Operator", errorList);
                    success = false;
                }
                else
                {
                    language.MemberOperator = configFileLanguage.MemberOperator;
                }
            }

            if (configFileLanguage.LineExtender != null)
            {
                if (language.Type != Language.LanguageType.BasicSupport)
                {
                    Start_CantDefinePropertyError(configFileLanguage, language.Type, sourceFile, "Line Extender", errorList);
                    success = false;
                }
                else
                {
                    language.LineExtender = configFileLanguage.LineExtender;
                }
            }

            if (configFileLanguage.EnumValue != null)
            {
                if (language.Type != Language.LanguageType.BasicSupport && language.Type != Language.LanguageType.TextFile)
                {
                    Start_CantDefinePropertyError(configFileLanguage, language.Type, sourceFile, "Enum Value", errorList);
                    success = false;
                }
                else
                {
                    language.EnumValue = (Language.EnumValues)configFileLanguage.EnumValue;
                }
            }

            if (configFileLanguage.CaseSensitive != null)
            {
                if (language.Type != Language.LanguageType.BasicSupport && language.Type != Language.LanguageType.TextFile)
                {
                    Start_CantDefinePropertyError(configFileLanguage, language.Type, sourceFile, "Case Sensitive", errorList);
                    success = false;
                }
                else
                {
                    language.CaseSensitive = (bool)configFileLanguage.CaseSensitive;
                }
            }

            string[] commentTypeNamesWithPrototypeEnders = configFileLanguage.GetCommentTypeNamesWithPrototypeEnders();

            if (commentTypeNamesWithPrototypeEnders != null)
            {
                if (language.Type != Language.LanguageType.BasicSupport)
                {
                    Start_CantDefinePropertyError(configFileLanguage, language.Type, sourceFile, "Prototype Enders", errorList);
                    success = false;
                }
                else
                {
                    foreach (string commentTypeName in commentTypeNamesWithPrototypeEnders)
                    {
                        CommentTypes.CommentType commentType = EngineInstance.CommentTypes.FromName(commentTypeName);

                        if (commentType == null)
                        {
                            errorList.Add(
                                Locale.Get("NaturalDocs.Engine", "Languages.txt.PrototypeEnderCommentTypeDoesntExist(name)", commentTypeName),
                                sourceFile, configFileLanguage.LineNumber
                                );

                            success = false;
                        }
                        else
                        {
                            string[]        prototypeEnderStrings = configFileLanguage.GetPrototypeEnderStrings(commentTypeName);
                            PrototypeEnders prototypeEnders       = new PrototypeEnders(prototypeEnderStrings);
                            language.SetPrototypeEnders(commentType.ID, prototypeEnders);
                        }
                    }
                }
            }


            // Apply the aliases, extensions, and shebang strings.

            if (configFileLanguage.Aliases != null)
            {
                // If using Replace Aliases, find all existing aliases pointing to this language and remove them.
                if (configFileLanguage.AlterLanguage == true && configFileLanguage.AddAliases == false)
                {
                    List <string> removedAliases = new List <string>();

                    foreach (KeyValuePair <string, Language> pair in aliases)
                    {
                        if ((object)pair.Value == (object)language)
                        {
                            removedAliases.Add(pair.Key);
                        }
                    }

                    foreach (string removedAlias in removedAliases)
                    {
                        aliases.Remove(removedAlias);
                    }
                }

                // Add new aliases.
                foreach (string alias in configFileLanguage.Aliases)
                {
                    aliases[alias] = language;
                }
            }

            if (configFileLanguage.Extensions != null)
            {
                // If using Replace Extensions, find all existing extensions pointing to this language and remove them.
                if (configFileLanguage.AlterLanguage == true && configFileLanguage.AddExtensions == false)
                {
                    List <string> removedExtensions = new List <string>();

                    foreach (KeyValuePair <string, Language> pair in extensions)
                    {
                        if ((object)pair.Value == (object)language)
                        {
                            removedExtensions.Add(pair.Key);
                        }
                    }

                    foreach (string removedExtension in removedExtensions)
                    {
                        extensions.Remove(removedExtension);
                    }
                }

                // Add new extensions.
                foreach (string extension in configFileLanguage.Extensions)
                {
                    if (ignoredExtensions.Contains(extension) == false)
                    {
                        extensions[extension] = language;
                    }
                }
            }

            if (configFileLanguage.ShebangStrings != null)
            {
                // If using Replace Shebang Strings, find all existing shebang strings pointing to this language and remove them.
                if (configFileLanguage.AlterLanguage == true && configFileLanguage.AddShebangStrings == false)
                {
                    List <string> removedShebangStrings = new List <string>();

                    foreach (KeyValuePair <string, Language> pair in shebangStrings)
                    {
                        if ((object)pair.Value == (object)language)
                        {
                            removedShebangStrings.Add(pair.Key);
                        }
                    }

                    foreach (string removedShebangString in removedShebangStrings)
                    {
                        shebangStrings.Remove(removedShebangString);
                    }
                }

                // Add new shebang strings.
                foreach (string shebangString in configFileLanguage.ShebangStrings)
                {
                    shebangStrings[shebangString] = language;
                }
            }


            return(success);
        }