Пример #1
0
        /// <summary>
        /// Parse the forward declaration of a class or struct
        /// </summary>
        /// <param name="OriginalReader">The current token reader</param>
        /// <param name="HeaderFile">The file to read from</param>
        /// <param name="SymbolToHeader">Map of symbol to the file containing it</param>
        /// <param name="Log">Writer for warnings and errors</param>
        /// <returns>True if a forward declaration was read, false otherwise</returns>
        bool ReadClassOrStructForwardDeclaration(TokenReader OriginalReader, SourceFile HeaderFile, Dictionary <Symbol, SourceFile> SymbolToHeader, TextWriter Log)
        {
            SymbolType Type;

            if (OriginalReader.Current.Text == "class")
            {
                Type = SymbolType.Class;
            }
            else if (OriginalReader.Current.Text == "struct")
            {
                Type = SymbolType.Struct;
            }
            else
            {
                return(false);
            }

            TokenReader Reader = new TokenReader(OriginalReader);

            if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines) || Reader.Current.Type != TokenType.Identifier)
            {
                return(false);
            }

            Token Identifier = Reader.Current;

            if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines) || Reader.Current.Text != ";")
            {
                return(false);
            }

            AddForwardDeclaration(HeaderFile, Identifier.Text, Type, SymbolToHeader, Log);
            OriginalReader.Set(Reader);
            return(true);
        }
Пример #2
0
        /// <summary>
        /// Try to skip over a template header
        /// </summary>
        /// <param name="OriginalReader">Tokens to parse</param>
        /// <param name="Fragment">Fragment containing these tokens</param>
        bool ReadTypedefHeader(TokenReader OriginalReader, SourceFragment Fragment)
        {
            TokenReader Reader = new TokenReader(OriginalReader);

            // Check for the typedef keyword
            Token PreviousToken = Reader.Current;

            if (Reader.Current.Text != "typedef" || !Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }

            // Scan to the next semicolon
            while (Reader.MoveNext(TokenReaderContext.IgnoreNewlines) && Reader.Current.Text != ";" && Reader.Current.Text != "{")
            {
                PreviousToken = Reader.Current;
            }

            // Ignore 'typedef struct' and 'typedef union' declarations.
            if (Reader.Current.Text == "{")
            {
                return(false);
            }

            // Try to add a symbol for the previous token. If it already exists, replace it.
            if (PreviousToken.Type == TokenType.Identifier && Rules.AllowSymbol(PreviousToken.Text))
            {
                AddSymbol(PreviousToken.Text, SymbolType.Typedef, null, Fragment, OriginalReader.TokenLocation);
            }

            // Move the original reader past the declaration
            OriginalReader.Set(Reader);
            return(true);
        }
Пример #3
0
        /// <summary>
        /// Skip over the declaration of an alias
        /// </summary>
        /// <param name="OriginalReader">The current token reader</param>
        /// <returns>True if a forward declaration was read, false otherwise</returns>
        bool SkipAliasDeclaration(TokenReader OriginalReader)
        {
            TokenReader Reader = new TokenReader(OriginalReader);

            if (Reader.Current.Text == "template")
            {
                if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
                {
                    return(false);
                }

                bool bMoveNext = true;
                if (!SkipTemplateArguments(Reader, ref bMoveNext) || !bMoveNext)
                {
                    return(false);
                }
            }

            if (Reader.Current.Text != "using")
            {
                return(false);
            }

            while (Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                if (Reader.Current.Text == ";")
                {
                    break;
                }
            }

            OriginalReader.Set(Reader);
            return(true);
        }
Пример #4
0
        /// <summary>
        /// Try to read a class or struct header
        /// </summary>
        /// <param name="Reader">Tokens to parse</param>
        /// <param name="Fragment">Fragment containing these tokens</param>
        bool ReadClassOrStructHeader(TokenReader OriginalReader, SourceFragment Fragment)
        {
            TokenReader Reader = new TokenReader(OriginalReader);

            // Make sure it's the right type
            SymbolType Type;

            if (Reader.Current.Text == "class")
            {
                Type = SymbolType.Class;
            }
            else if (Reader.Current.Text == "struct")
            {
                Type = SymbolType.Struct;
            }
            else
            {
                return(false);
            }

            // Move to the name
            string ClassOrStructKeyword = Reader.Current.Text;

            if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }

            // Skip over an optional DLL export declaration
            if (Reader.Current.Type == TokenType.Identifier && Reader.Current.Text.EndsWith("_API") && !Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }

            // Read the class name
            string Name = Reader.Current.Text;

            if (Reader.Current.Type != TokenType.Identifier || !Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }
            if (Reader.Current.Text != ":" && Reader.Current.Text != "{")
            {
                return(false);
            }

            // Create the symbol
            if (Rules.AllowSymbol(Name))
            {
                string ForwardDeclaration = String.Format("{0} {1};", ClassOrStructKeyword, Name);
                AddSymbol(Name, Type, ForwardDeclaration, Fragment, OriginalReader.TokenLocation);
            }

            // Move the original reader past the declaration
            OriginalReader.Set(Reader);
            return(true);
        }
        /// <summary>
        /// Parse an "enum class" declaration, and add a symbol for it
        /// </summary>
        /// <param name="Reader">Tokens to be parsed. On success, this is assigned to a new </param>
        /// <param name="Fragment">Fragment containing these tokens</param>
        bool ReadEnumClassHeader(TokenReader OriginalReader, SourceFragment Fragment)
        {
            TokenReader Reader = new TokenReader(OriginalReader);

            // Read the 'enum class' tokens
            if (Reader.Current.Text != "enum" || !Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }
            if (Reader.Current.Text != "class" || !Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }

            // Read the name, make sure we haven't read a definition for it already, and check it's an enum declaration
            string Name = Reader.Current.Text;

            if (Reader.Current.Type != TokenType.Identifier || !Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }
            if (Reader.Current.Text != ";" && Reader.Current.Text != ":" && Reader.Current.Text != "{")
            {
                return(false);
            }

            // Build the forward declaration for it
            StringBuilder ForwardDeclaration = new StringBuilder();

            ForwardDeclaration.AppendFormat("enum class {0}", Name);
            while (Reader.Current.Text != ";" && Reader.Current.Text != "{")
            {
                // Append the next token
                if (Reader.Current.HasLeadingSpace)
                {
                    ForwardDeclaration.Append(" ");
                }
                ForwardDeclaration.Append(Reader.Current.Text);

                // Try to move to the next token
                if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
                {
                    return(false);
                }
            }
            ForwardDeclaration.Append(";");

            // Create a symbol for it if it's an actual definition rather than a forward declaration
            if (Reader.Current.Text == "{" && Rules.AllowSymbol(Name))
            {
                AddSymbol(Name, SymbolType.Enumeration, ForwardDeclaration.ToString(), Fragment, OriginalReader.TokenLocation);
            }

            // Update the original reader to be the new location
            OriginalReader.Set(Reader);
            return(true);
        }
Пример #6
0
        /// <summary>
        /// Parse the forward declaration of a template class or struct
        /// </summary>
        /// <param name="OriginalReader">The current token reader</param>
        /// <param name="HeaderFile">The file to read from</param>
        /// <param name="SymbolToHeader">Map of symbol to the file containing it</param>
        /// <param name="Log">Writer for warnings and errors</param>
        /// <returns>True if a forward declaration was read, false otherwise</returns>
        bool ReadTemplateClassOrStructForwardDeclaration(TokenReader OriginalReader, SourceFile HeaderFile, Dictionary <Symbol, SourceFile> SymbolToHeader, TextWriter Log)
        {
            if (OriginalReader.Current.Text != "template")
            {
                return(false);
            }

            TokenReader Reader = new TokenReader(OriginalReader);

            if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }

            bool bMoveNext = true;

            if (!SkipTemplateArguments(Reader, ref bMoveNext) || !bMoveNext)
            {
                return(false);
            }

            SymbolType Type;

            if (Reader.Current.Text == "class")
            {
                Type = SymbolType.TemplateClass;
            }
            else if (Reader.Current.Text == "struct")
            {
                Type = SymbolType.TemplateStruct;
            }
            else
            {
                return(false);
            }

            if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines) || Reader.Current.Type != TokenType.Identifier)
            {
                return(false);
            }

            Token Identifier = Reader.Current;

            if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines) || Reader.Current.Text != ";")
            {
                return(false);
            }

            OriginalReader.Set(Reader);
            AddForwardDeclaration(HeaderFile, Identifier.Text, Type, SymbolToHeader, Log);
            return(true);
        }
Пример #7
0
        /// <summary>
        /// Try to skip over a template header
        /// </summary>
        /// <param name="OriginalReader">Tokens to parse</param>
        /// <param name="Fragment">The fragment containing this symbol</param>
        bool SkipTemplateHeader(TokenReader OriginalReader)
        {
            TokenReader Reader = new TokenReader(OriginalReader);

            if (Reader.Current.Text != "template" || !Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }

            while (Reader.Current.Text != ";" && Reader.Current.Text != "{")
            {
                if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
                {
                    break;
                }
            }

            // Move the original reader past the declaration
            OriginalReader.Set(Reader);
            return(true);
        }
Пример #8
0
        /// <summary>
        /// Parse the forward declaration of an enum class
        /// </summary>
        /// <param name="OriginalReader">The current token reader</param>
        /// <param name="HeaderFile">The file to read from</param>
        /// <param name="SymbolToHeader">Map of symbol to the file containing it</param>
        /// <param name="Log">Writer for warnings and errors</param>
        /// <returns>True if a forward declaration was read, false otherwise</returns>
        bool ReadEnumClassForwardDeclaration(TokenReader OriginalReader, SourceFile HeaderFile, Dictionary <Symbol, SourceFile> SymbolToHeader, TextWriter Log)
        {
            if (OriginalReader.Current.Text != "enum")
            {
                return(false);
            }

            TokenReader Reader = new TokenReader(OriginalReader);

            if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }
            if (Reader.Current.Text == "class" && !Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }
            if (Reader.Current.Type != TokenType.Identifier)
            {
                return(false);
            }

            Token Identifier = Reader.Current;

            while (Reader.Current.Text != ";")
            {
                if (Reader.Current.Text == "{" || !Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
                {
                    return(false);
                }
            }

            AddForwardDeclaration(HeaderFile, Identifier.Text, SymbolType.Enumeration, SymbolToHeader, Log);
            OriginalReader.Set(Reader);
            return(true);
        }
Пример #9
0
        /// <summary>
        /// Try to read a template class or struct header
        /// </summary>
        /// <param name="Reader">Tokens to parse</param>
        /// <param name="Fragment">Fragment containing these tokens</param>
        bool ReadTemplateClassOrStructHeader(TokenReader OriginalReader, SourceFragment Fragment)
        {
            TokenReader Reader = new TokenReader(OriginalReader);

            // Check for the template keyword
            if (Reader.Current.Text != "template")
            {
                return(false);
            }

            // Create a buffer to store the template prefix
            List <Token> Tokens = new List <Token>();

            Tokens.Add(Reader.Current);

            // Check for the opening argument list
            if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines) || Reader.Current.Text != "<")
            {
                return(false);
            }

            // Read the argument list, keeping track of any symbols referenced along the way
            while (Tokens[Tokens.Count - 1].Text != ">")
            {
                Tokens.Add(Reader.Current);
                if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
                {
                    return(false);
                }
            }

            // Get the symbol type
            SymbolType Type;

            if (Reader.Current.Text == "class")
            {
                Type = SymbolType.TemplateClass;
            }
            else if (Reader.Current.Text == "struct")
            {
                Type = SymbolType.TemplateStruct;
            }
            else
            {
                return(false);
            }

            // Add the class or struct keyword
            Tokens.Add(Reader.Current);

            // Move to the name
            if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }

            // Skip over an optional DLL export declaration
            if (Reader.Current.Type == TokenType.Identifier && Reader.Current.Text.EndsWith("_API") && !Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }

            // Read the class name and check it's followed by a class body or inheritance list
            string Name = Reader.Current.Text;

            if (Reader.Current.Type != TokenType.Identifier || !Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }
            if (Reader.Current.Text != ":" && Reader.Current.Text != "{")
            {
                return(false);
            }

            // Create the symbol.
            if (Rules.AllowSymbol(Name))
            {
                // Only allow forward declarations of templates with class and typename arguments and no defaults (ie. no enums or class names which may have to be forward-declared separately).
                string ForwardDeclaration = null;
                if (!Tokens.Any(x => x.Text == "="))
                {
                    ForwardDeclaration = String.Format("{0} {1};", Token.Format(Tokens), Name);
                    for (int Idx = 2; Idx < Tokens.Count - 2; Idx += 3)
                    {
                        if (Tokens[Idx].Text != "class" && Tokens[Idx].Text != "typename")
                        {
                            ForwardDeclaration = null;
                            break;
                        }
                    }
                }
                AddSymbol(Name, Type, ForwardDeclaration, Fragment, OriginalReader.TokenLocation);
            }

            // Move the original reader past the declaration
            OriginalReader.Set(Reader);
            return(true);
        }
Пример #10
0
        /// <summary>
        /// Parse an "enum class" declaration, and add a symbol for it
        /// </summary>
        /// <param name="Reader">Tokens to be parsed. On success, this is assigned to a new </param>
        /// <param name="Fragment">Fragment containing these tokens</param>
        bool ReadEnumClassHeader(TokenReader OriginalReader, SourceFragment Fragment)
        {
            TokenReader Reader = new TokenReader(OriginalReader);

            // Read the UENUM prefix if present. We don't want to forward-declare types that need to be parsed by UHT, because it needs the definition.
            bool bIsUENUM = false;

            if (Reader.Current.Text == "UENUM")
            {
                if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines) || Reader.Current.Text != "(")
                {
                    return(false);
                }
                while (Reader.Current.Text != ")")
                {
                    if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
                    {
                        return(false);
                    }
                }
                if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
                {
                    return(false);
                }
                bIsUENUM = true;
            }

            // Read the 'enum class' tokens
            if (Reader.Current.Text != "enum" || !Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }
            if (Reader.Current.Text != "class" || !Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }

            // Read the name, make sure we haven't read a definition for it already, and check it's an enum declaration
            string Name = Reader.Current.Text;

            if (Reader.Current.Type != TokenType.Identifier || !Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
            {
                return(false);
            }
            if (Reader.Current.Text != ";" && Reader.Current.Text != ":" && Reader.Current.Text != "{")
            {
                return(false);
            }

            // Build the forward declaration for it. Don't forward-declare UENUM types because UHT needs to parse their definition first.
            string ForwardDeclaration = null;

            if (!bIsUENUM)
            {
                StringBuilder ForwardDeclarationBuilder = new StringBuilder();
                ForwardDeclarationBuilder.AppendFormat("enum class {0}", Name);
                while (Reader.Current.Text != ";" && Reader.Current.Text != "{")
                {
                    // Append the next token
                    if (Reader.Current.HasLeadingSpace)
                    {
                        ForwardDeclarationBuilder.Append(" ");
                    }
                    ForwardDeclarationBuilder.Append(Reader.Current.Text);

                    // Try to move to the next token
                    if (!Reader.MoveNext(TokenReaderContext.IgnoreNewlines))
                    {
                        return(false);
                    }
                }
                ForwardDeclarationBuilder.Append(";");
                ForwardDeclaration = ForwardDeclarationBuilder.ToString();
            }

            // Create a symbol for it if it's an actual definition rather than a forward declaration
            if (Reader.Current.Text == "{" && Rules.AllowSymbol(Name))
            {
                AddSymbol(Name, SymbolType.Enumeration, ForwardDeclaration, Fragment, OriginalReader.TokenLocation);
            }

            // Update the original reader to be the new location
            OriginalReader.Set(Reader);
            return(true);
        }