static void Main(string[] args) { var input = new Dictionary <string, GlobalDecl>(); for (int i = 0; i < args.Length / 2; i++) { var tag = args[i * 2]; var fileName = args[i * 2 + 1]; Console.WriteLine("Reading " + fileName + " ..."); var xml = XDocument.Load(fileName); var decl = (GlobalDecl)SymbolDecl.Deserialize(xml.Root); decl.BuildSymbolTree(null, tag); input.Add(tag, decl); } Console.WriteLine("De-duplicating ..."); var symbolGroup = new Dictionary <string, List <SymbolDecl> >(); GroupSymbolsByOverloadKey(input.Values, symbolGroup); foreach (var pair in symbolGroup) { var groups = pair.Value .GroupBy(x => x.ContentKey) .ToArray(); foreach (var group in groups) { var decls = group.ToArray(); var tags = decls .Select(x => x.Tags) .OrderBy(x => x) .Aggregate((a, b) => a + ";" + b); foreach (var decl in decls) { decl.Tags = tags; } } } Console.WriteLine("Resolving Symbols ..."); var symbolResolving = symbolGroup .SelectMany(x => x.Value) .ToArray(); var environment = new ResolveEnvironment(input.Values); foreach (var symbol in symbolResolving) { symbol.Resolve(environment); } var output = args[args.Length - 1]; var xmlErrors = environment.Errors.Where(x => x.StartsWith("(Xml)")).ToArray(); var warnings = environment.Errors.Where(x => x.StartsWith("(Warning)")).ToArray(); var errors = environment.Errors.Where(x => x.StartsWith("(Error)")).ToArray(); Console.WriteLine("Xml Errors: " + xmlErrors.Length); Console.WriteLine("Warnings: " + warnings.Length); Console.WriteLine("Errors: " + errors.Length); using (var writer = new StreamWriter(output + ".errors.txt", false, Encoding.UTF8)) { writer.WriteLine("=======================XML ERROR======================="); foreach (var message in xmlErrors) { writer.WriteLine(message); } writer.WriteLine(); writer.WriteLine("========================WARNING========================"); foreach (var message in warnings) { writer.WriteLine(message); } writer.WriteLine(); writer.WriteLine("=========================ERROR========================="); foreach (var message in errors) { writer.WriteLine(message); } } Console.WriteLine("Saving ..."); var symbolSaving = symbolGroup .ToDictionary( x => x.Key, x => x.Value .GroupBy(y => y.Tags) .Select(y => y.First()) .ToArray() ) .GroupBy(x => GetNamespaceSymbol(x.Value.First())) .ToDictionary( x => x.Key, x => x.ToDictionary( y => y.Key, y => y.Value ) ) ; var outputXml = new XDocument( new XElement("CppXmlDocument", symbolSaving.Select(x => new XElement("Namespace", new XAttribute("Name", x.Key is GlobalDecl ? "" : (x.Key as NamespaceDecl).NameKey), x.Value.Select(y => new XElement("Symbol", new XAttribute("OverloadKey", y.Key), y.Value .Select(z => z.Parent is TemplateDecl ? z.Parent : z) .Select(z => z.Serialize()) )) )) ) ); outputXml.Save(output); }
static SymbolDecl[] ParseSymbolInternal(string[] tokens, ref int index) { if (CppParser.Token(tokens, ref index, "public") || CppParser.Token(tokens, ref index, "protected") || CppParser.Token(tokens, ref index, "private")) { index--; return(null); } TemplateDecl templateDecl = null; if (CppParser.Token(tokens, ref index, "template")) { templateDecl = new TemplateDecl { TypeParameters = new List <TypeParameterDecl>(), Specialization = new List <TypeDecl>(), }; CppParser.EnsureToken(tokens, ref index, "<"); if (!CppParser.Token(tokens, ref index, ">")) { while (true) { string token = null; CppParser.SkipUntilInTemplate(tokens, ref index, out token, ",", ">", "="); index -= 2; templateDecl.TypeParameters.Add(new TypeParameterDecl { Name = CppParser.EnsureId(tokens, ref index), }); index++; if (token == "=") { CppParser.SkipUntilInTemplate(tokens, ref index, out token, ",", ">"); } if (token == ">") { break; } } } } if (CppParser.Token(tokens, ref index, "friend")) { int oldIndex = index - 1; string token = null; CppParser.SkipUntil(tokens, ref index, out token, ";", "{"); if (token == ";") { return(null); } else { index = oldIndex; tokens[index] = "static"; } } if (CppParser.Token(tokens, ref index, "namespace")) { if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } var decl = new NamespaceDecl(); decl.Name = CppParser.EnsureId(tokens, ref index); CppParser.EnsureToken(tokens, ref index, "{"); ParseSymbols(tokens, ref index, decl); CppParser.EnsureToken(tokens, ref index, "}"); return(new SymbolDecl[] { decl }); } else if (CppParser.Token(tokens, ref index, "using")) { if (CppParser.Token(tokens, ref index, "namespace")) { if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } var decl = new UsingNamespaceDecl(); decl.Path = new List <string>(); decl.Path.Add(CppParser.EnsureId(tokens, ref index)); while (!CppParser.Token(tokens, ref index, ";")) { CppParser.EnsureToken(tokens, ref index, ":"); CppParser.EnsureToken(tokens, ref index, ":"); decl.Path.Add(CppParser.EnsureId(tokens, ref index)); } return(new SymbolDecl[] { decl }); } else { string name = null; if (CppParser.Id(tokens, ref index, out name)) { if (templateDecl != null) { if (CppParser.Token(tokens, ref index, "<")) { while (true) { templateDecl.Specialization.Add(CppTypeParser.EnsureTypeWithoutNameInTemplate(tokens, ref index)); if (CppParser.Token(tokens, ref index, ">")) { break; } CppParser.EnsureToken(tokens, ref index, ","); } } } if (CppParser.Token(tokens, ref index, "=")) { SymbolDecl decl = new TypedefDecl { Name = name, Type = CppTypeParser.EnsureTypeWithoutName(tokens, ref index), }; CppParser.EnsureToken(tokens, ref index, ";"); if (templateDecl != null) { templateDecl.Element = decl; decl = templateDecl; } return(new SymbolDecl[] { decl }); } } if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } CppParser.SkipUntil(tokens, ref index, ";"); } } else if (CppParser.Token(tokens, ref index, "typedef")) { if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } string name = null; var type = CppTypeParser.EnsureTypeWithName(tokens, ref index, out name); CppParser.EnsureToken(tokens, ref index, ";"); var decl = new TypedefDecl(); decl.Name = name; decl.Type = type; return(new SymbolDecl[] { decl }); } else if (CppParser.Token(tokens, ref index, "enum")) { if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } bool enumClass = CppParser.Token(tokens, ref index, "class"); string name = CppParser.EnsureId(tokens, ref index); if (CppParser.Token(tokens, ref index, ":")) { CppTypeParser.EnsureTypeWithoutName(tokens, ref index); } if (!CppParser.Token(tokens, ref index, ";")) { CppParser.EnsureToken(tokens, ref index, "{"); var decl = new EnumDecl { Name = name, EnumClass = enumClass, Children = new List <SymbolDecl>(), }; while (true) { if (CppParser.Token(tokens, ref index, "}")) { break; } string document = null; while (index < tokens.Length && tokens[index].Length >= 3 && tokens[index].StartsWith("///")) { var line = tokens[index]; if (document == null) { document = ""; } document += line.StartsWith("/// ") || line.StartsWith("///\t") ? line.Substring(4) : line.Substring(3); document += "\r\n"; index++; } decl.Children.Add(new EnumItemDecl { Name = CppParser.EnsureId(tokens, ref index), Document = document, }); string token = null; CppParser.SkipUntil(tokens, ref index, out token, ",", "}"); if (token == "}") { break; } } if (CppParser.Id(tokens, ref index, out name)) { var varDecl = new VarDecl { Static = false, Name = name, Type = new RefTypeDecl { Name = decl.Name, }, }; CppParser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl, varDecl }); } else { CppParser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl }); } } } else if (CppParser.Token(tokens, ref index, "struct") || CppParser.Token(tokens, ref index, "class") || CppParser.Token(tokens, ref index, "union")) { if (CppParser.Token(tokens, ref index, "{")) { if (tokens[index - 2] == "class") { throw new ArgumentException("Failed to parse."); } var decl = new GroupedFieldDecl { Grouping = tokens[index - 2] == "struct" ? Grouping.Struct : Grouping.Union, }; ParseSymbols(tokens, ref index, decl); CppParser.EnsureToken(tokens, ref index, "}"); CppParser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl }); } else { string name = CppParser.EnsureId(tokens, ref index); if (!CppParser.Token(tokens, ref index, ";")) { var classDecl = new ClassDecl { ClassType = tokens[index - 2] == "struct" ? ClassType.Struct : tokens[index - 2] == "class" ? ClassType.Class : ClassType.Union, BaseTypes = new List <BaseTypeDecl>(), Name = name, }; if (templateDecl != null) { if (CppParser.Token(tokens, ref index, "<")) { if (!CppParser.Token(tokens, ref index, ">")) { while (true) { int oldIndex = index; templateDecl.Specialization.Add(CppTypeParser.EnsureTypeWithoutNameInTemplate(tokens, ref index)); if (CppParser.Token(tokens, ref index, ">")) { break; } CppParser.EnsureToken(tokens, ref index, ","); } } } } CppParser.Token(tokens, ref index, "abstract"); if (CppParser.Token(tokens, ref index, ":")) { while (true) { Access access = classDecl.ClassType == ClassType.Class ? Access.Private : Access.Public; CppParser.Token(tokens, ref index, "virtual"); if (CppParser.Token(tokens, ref index, "private")) { access = Access.Private; } else if (CppParser.Token(tokens, ref index, "protected")) { access = Access.Protected; } else if (CppParser.Token(tokens, ref index, "public")) { access = Access.Public; } CppParser.Token(tokens, ref index, "virtual"); classDecl.BaseTypes.Add(new BaseTypeDecl { Access = access, Type = CppTypeParser.EnsureTypeWithoutName(tokens, ref index), }); if (!CppParser.Token(tokens, ref index, ",")) { break; } } } CppParser.EnsureToken(tokens, ref index, "{"); while (true) { if (CppParser.Token(tokens, ref index, "}")) { break; } Access access = classDecl.ClassType == ClassType.Class ? Access.Private : Access.Public; if (CppParser.Token(tokens, ref index, "private")) { access = Access.Private; CppParser.EnsureToken(tokens, ref index, ":"); } else if (CppParser.Token(tokens, ref index, "protected")) { access = Access.Protected; CppParser.EnsureToken(tokens, ref index, ":"); } else if (CppParser.Token(tokens, ref index, "public")) { access = Access.Public; CppParser.EnsureToken(tokens, ref index, ":"); } ParseSymbols(tokens, ref index, classDecl, access); } SymbolDecl decl = classDecl; if (templateDecl != null) { templateDecl.Element = decl; decl = templateDecl; } if (CppParser.Id(tokens, ref index, out name)) { var varDecl = new VarDecl { Static = false, Name = name, Type = new RefTypeDecl { Name = classDecl.Name, }, }; CppParser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl, varDecl }); } else { CppParser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl }); } } } } else if (!CppParser.Token(tokens, ref index, ";")) { Function function = Function.Function; { int oldIndex = index; string name = null; if (CppParser.Id(tokens, ref index, out name)) { if (CppParser.Token(tokens, ref index, "(")) { CppParser.SkipUntil(tokens, ref index, ")"); if (CppParser.Token(tokens, ref index, ";") || CppParser.Token(tokens, ref index, "=") || CppParser.Token(tokens, ref index, ":") || CppParser.Token(tokens, ref index, "{")) { function = Function.Constructor; } } index = oldIndex; } else if (CppParser.Token(tokens, ref index, "~")) { function = Function.Destructor; } } if (function == Function.Function) { Virtual virtualFunction = Virtual.Normal; CppParser.Token(tokens, ref index, "extern"); CppParser.Token(tokens, ref index, "mutable"); if (CppParser.Token(tokens, ref index, "virtual")) { virtualFunction = Virtual.Virtual; } else if (CppParser.Token(tokens, ref index, "static")) { virtualFunction = Virtual.Static; } CppParser.Token(tokens, ref index, "inline"); CppParser.Token(tokens, ref index, "__forceinline"); if (CppParser.Token(tokens, ref index, "operator")) { TypeDecl returnType = null; { int oldIndex = index; CppParser.SkipUntilInTemplate(tokens, ref index, "("); int modify = --index; tokens[modify] = "$"; index = oldIndex; returnType = CppTypeParser.EnsureTypeWithoutName(tokens, ref index); if (index != modify) { throw new ArgumentException("Failed to parse."); } tokens[modify] = "("; } var decl = new FuncDecl { Virtual = Virtual.Normal, Name = "operator", Function = function, }; TypeDecl functionType = null; Action <TypeDecl> continuation = null; CallingConvention callingConvention = CallingConvention.Default; CppTypeParser.ParseTypeContinueAfterName(tokens, ref index, ref callingConvention, out functionType, out continuation); continuation(returnType); decl.Type = functionType; if (!CppParser.Token(tokens, ref index, ";")) { CppParser.EnsureToken(tokens, ref index, "{"); CppParser.SkipUntil(tokens, ref index, "}"); } if (templateDecl != null) { templateDecl.Element = decl; return(new SymbolDecl[] { templateDecl }); } else { return(new SymbolDecl[] { decl }); } } else { string name = null; TypeDecl type = null; if (CppTypeParser.ParseType(tokens, ref index, out type, out name)) { if (name == null) { throw new ArgumentException("Failed to parse."); } if (type is FunctionTypeDecl) { if (CppParser.Token(tokens, ref index, "=")) { if (CppParser.Token(tokens, ref index, "0")) { virtualFunction = Virtual.Abstract; } else { CppParser.EnsureToken(tokens, ref index, "default", "delete"); } } var decl = new FuncDecl { Virtual = virtualFunction, Name = name, Type = type, Function = Function.Function, }; { var funcType = (FunctionTypeDecl)type; var returnType = funcType.ReturnType as RefTypeDecl; if (returnType != null && returnType.Name == "auto") { if (CppParser.Token(tokens, ref index, "-")) { CppParser.EnsureToken(tokens, ref index, ">"); TypeDecl newReturnType = CppTypeParser.EnsureTypeWithoutName(tokens, ref index); funcType.ReturnType = newReturnType; } } if (!CppParser.Token(tokens, ref index, ";")) { CppParser.EnsureToken(tokens, ref index, "{"); CppParser.SkipUntil(tokens, ref index, "}"); } } if (templateDecl != null) { templateDecl.Element = decl; return(new SymbolDecl[] { templateDecl }); } else { return(new SymbolDecl[] { decl }); } } else { if (virtualFunction != Virtual.Normal && virtualFunction != Virtual.Static) { throw new ArgumentException("Failed to parse."); } if (CppParser.Token(tokens, ref index, "=")) { CppParser.SkipUntil(tokens, ref index, ";"); } else if (CppParser.Token(tokens, ref index, "{")) { CppParser.SkipUntil(tokens, ref index, "}"); } else { CppParser.EnsureToken(tokens, ref index, ";"); } if (!(type is ClassMemberTypeDecl)) { var decl = new VarDecl { Static = virtualFunction == Virtual.Static, Name = name, Type = type, }; return(new SymbolDecl[] { decl }); } } } } } else { var decl = new FuncDecl { Virtual = Virtual.Normal, Name = (function == Function.Constructor ? "" : "~") + CppParser.EnsureId(tokens, ref index), Function = function, }; TypeDecl functionType = null; Action <TypeDecl> continuation = null; CallingConvention callingConvention = CallingConvention.Default; CppTypeParser.ParseTypeContinueAfterName(tokens, ref index, ref callingConvention, out functionType, out continuation); continuation(new RefTypeDecl { Name = "void" }); decl.Type = functionType; if (CppParser.Token(tokens, ref index, "=")) { CppParser.EnsureToken(tokens, ref index, "default", "delete"); } if (!CppParser.Token(tokens, ref index, ";")) { if (CppParser.Token(tokens, ref index, ":")) { do { CppTypeParser.EnsureMiniType(tokens, ref index); if (CppParser.Token(tokens, ref index, "(")) { CppParser.SkipUntil(tokens, ref index, ")"); } else if (CppParser.Token(tokens, ref index, "{")) { CppParser.SkipUntil(tokens, ref index, "}"); } else { throw new ArgumentException("Failed to parse."); } }while (CppParser.Token(tokens, ref index, ",")); } CppParser.EnsureToken(tokens, ref index, "{"); CppParser.SkipUntil(tokens, ref index, "}"); } if (templateDecl != null) { templateDecl.Element = decl; return(new SymbolDecl[] { templateDecl }); } else { return(new SymbolDecl[] { decl }); } } } return(null); }
static string GetDisplayName(SymbolDecl decl) { { var templateDecl = decl as TemplateDecl; if (templateDecl != null) { decl = templateDecl.Element; } } if (decl is ClassDecl) { switch (((ClassDecl)decl).ClassType) { case ClassType.Class: return(decl.Name + " class"); case ClassType.Struct: return(decl.Name + " struct"); case ClassType.Union: return(decl.Name + " union"); default: throw new ArgumentException(); } } else if (decl is EnumDecl) { return(decl.Name + " enum"); } else if (decl is FuncDecl) { var parent = decl.Parent as ClassDecl; if (parent != null) { if (parent.Name == decl.Name) { return(decl.Name + " constructor"); } else if ("~" + parent.Name == decl.Name) { return(decl.Name + " destructor"); } else { return(decl.Name + " method"); } } else { return(decl.Name + " function"); } } else if (decl is VarDecl) { if (decl.Parent is ClassDecl || decl.Parent is GroupedFieldDecl) { return(decl.Name + " field"); } else if (decl.Parent is FuncDecl) { return(decl.Name + " parameter"); } else { return(decl.Name + " variable"); } } else if (decl is TypedefDecl) { return(decl.Name + " typedecl"); } else { throw new ArgumentException(); } }
static void FixSymbolLinks(SymbolDecl decl, Dictionary <string, string> symbolFileMapping) { FixSymbolDeclVisitor.Execute(decl, symbolFileMapping); }
static void Main(string[] args) { Console.WriteLine("Reading " + args[0] + " ..."); var xml = XDocument.Load(args[0]); var xmlNss = xml.Root .Elements("Namespace") .GroupBy(xmlNs => xmlNs.Attribute("Name").Value) .ToDictionary( g => g.Key, g => g.SelectMany(xmlNs => xmlNs.Elements("Symbol")).ToArray() ); var symbols = xml.Root .Elements("Namespace") .GroupBy(xmlNs => xmlNs.Attribute("Name").Value) .ToDictionary( g => g.Key, g => { return(g .SelectMany(xmlNs => xmlNs.Elements("Symbol")) .Select(xmlSymbol => { var key = xmlSymbol.Attribute("OverloadKey").Value; var symbolDecls = xmlSymbol .Elements() .Select(xmlDecl => { var decl = SymbolDecl.Deserialize(xmlDecl); decl.BuildSymbolTree(null, null); return decl; }) .ToArray(); return Tuple.Create(key, symbolDecls); }) .ToArray()); } ); var output = Path.GetFullPath(args[1]); if (!output.EndsWith("\\")) { output += "\\"; } Console.WriteLine("Writing nss.xml ..."); var namespaceNames = symbols.Keys .ToDictionary( ns => ns, ns => ns .Split(new[] { "::" }, StringSplitOptions.RemoveEmptyEntries) .Aggregate("", (a, b) => a == "" ? b : a + "." + b) ); var outputNss = new XDocument( new XElement("Namespaces", namespaceNames .OrderBy(p => p.Key) .Select(p => new XElement("Namespace", new XAttribute("Key", p.Key), new XAttribute("DisplayName", (p.Key == "" ? "::" : p.Key.Substring(2)) + " namespace"), new XAttribute("UrlName", p.Value), new XAttribute("Doc", symbols[p.Key].SelectMany(t => t.Item2.Select(s => s)).Any(ContainsDocument)) ) ) ) ); outputNss.Save(output + "nss.xml"); Console.WriteLine("Writing ns(*).xml ..."); var symbolNames = symbols .SelectMany(x => x.Value.Select(t => t.Item1)) .ToDictionary( x => x, x => x .Replace("::", ".") .Replace(":", "#") .Replace("|", "$") .Replace("/", "%") .Replace("*", "^") .Replace("<", "{") .Replace(">", "}") .Substring(1) ); foreach (var nsp in symbols) { var outputNs = new XDocument( new XElement("Namespace", new XAttribute("DisplayName", nsp.Key), nsp.Value .GroupBy(t => GetDisplayName(t.Item2[0])) .OrderBy(g => g.Key) .Select(g => new XElement("Overloads", new XAttribute("DisplayName", g.Key), g .Select(t => new XElement("Symbol", new XAttribute("Key", t.Item2.First().OverloadKey ?? t.Item2.First().Children[0].OverloadKey), new XAttribute("UrlName", symbolNames[t.Item1]), new XAttribute("Doc", t.Item2.Any(ContainsDocument)) ) ) ) ) ) ); outputNs.Save(output + "ns(" + namespaceNames[nsp.Key] + ").xml"); } Console.WriteLine("Writing t(*).xml ..."); var symbolFileMapping = new Dictionary <string, string>(); foreach (var nsp in symbols) { Console.WriteLine("t(*).xml: " + nsp.Key); var stGroup = nsp.Value .GroupBy(st => GetUrlNameForKey(symbolNames[st.Item1])) .ToDictionary(g => g.Key, g => g.ToArray()); foreach (var stGroupPair in stGroup) { var urlName = stGroupPair.Key; var outputSymbol = new XDocument( new XElement("OverloadingSymbolTrees", stGroupPair.Value .Select(st => new XElement("OverloadingSymbolTree", new XAttribute("Key", symbolNames[st.Item1]), CreateSymbolTree(namespaceNames[nsp.Key], symbolNames[st.Item1], st.Item2, symbolFileMapping).Root ) ) ) ); outputSymbol.Save(output + "t(" + urlName + ").xml"); } } Console.WriteLine("Writing s(*).xml ..."); foreach (var nss in namespaceNames) { symbolFileMapping.Add(nss.Key, "ns:" + nss.Value); } foreach (var nsp in symbols) { Console.WriteLine("s(*).xml: " + nsp.Key); var stGroup = nsp.Value .GroupBy(st => GetUrlNameForKey(symbolNames[st.Item1])) .ToDictionary(g => g.Key, g => g.ToArray()); foreach (var stGroupPair in stGroup) { foreach (var st in stGroupPair.Value) { foreach (var decl in st.Item2) { FixSymbolLinks(decl, symbolFileMapping); } } var urlName = stGroupPair.Key; var outputSymbol = new XDocument( new XElement("OverloadingSymbols", stGroupPair.Value .Select(st => new XElement("Symbols", new XAttribute("Key", symbolNames[st.Item1]), st.Item2.Select(decl => decl.Serialize()) ) ) ) ); outputSymbol.Save(output + "s(" + urlName + ").xml"); } } }