/// <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); }
/// <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); }
/// <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); }
/// <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); }