static SymbolDecl[] ParseSymbol(string[] tokens, ref int index) { while (index < tokens.Length && tokens[index].Length >= 3 && tokens[index].StartsWith("///")) { index++; } if (Parser.Token(tokens, ref index, "public") || Parser.Token(tokens, ref index, "protected") || Parser.Token(tokens, ref index, "private")) { index--; return(null); } TemplateDecl templateDecl = null; if (Parser.Token(tokens, ref index, "template")) { templateDecl = new TemplateDecl { TypeParameters = new List <string>(), Specialization = new List <TypeDecl>(), }; Parser.EnsureToken(tokens, ref index, "<"); if (!Parser.Token(tokens, ref index, ">")) { while (true) { string token = null; Parser.SkipUntilInTemplate(tokens, ref index, out token, ",", ">", "="); index -= 2; templateDecl.TypeParameters.Add(Parser.EnsureId(tokens, ref index)); index++; if (token == "=") { Parser.SkipUntilInTemplate(tokens, ref index, out token, ",", ">"); } if (token == ">") { break; } } } } if (Parser.Token(tokens, ref index, "friend")) { int oldIndex = index - 1; string token = null; Parser.SkipUntil(tokens, ref index, out token, ";", "{"); if (token == ";") { return(null); } else { index = oldIndex; tokens[index] = "static"; } } if (Parser.Token(tokens, ref index, "namespace")) { if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } var decl = new NamespaceDecl(); decl.Name = Parser.EnsureId(tokens, ref index); Parser.EnsureToken(tokens, ref index, "{"); ParseSymbols(tokens, ref index, decl); Parser.EnsureToken(tokens, ref index, "}"); return(new SymbolDecl[] { decl }); } else if (Parser.Token(tokens, ref index, "using")) { if (Parser.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(Parser.EnsureId(tokens, ref index)); while (!Parser.Token(tokens, ref index, ";")) { Parser.EnsureToken(tokens, ref index, ":"); Parser.EnsureToken(tokens, ref index, ":"); decl.Path.Add(Parser.EnsureId(tokens, ref index)); } return(new SymbolDecl[] { decl }); } else { string name = null; if (Parser.Id(tokens, ref index, out name)) { if (templateDecl != null) { if (Parser.Token(tokens, ref index, "<")) { while (true) { templateDecl.Specialization.Add(TypeDecl.EnsureTypeWithoutName(tokens, ref index)); if (Parser.Token(tokens, ref index, ">")) { break; } Parser.EnsureToken(tokens, ref index, ","); } } } if (Parser.Token(tokens, ref index, "=")) { SymbolDecl decl = new TypedefDecl { Name = name, Type = TypeDecl.EnsureTypeWithoutName(tokens, ref index), }; Parser.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."); } Parser.SkipUntil(tokens, ref index, ";"); } } else if (Parser.Token(tokens, ref index, "typedef")) { if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } string name = null; var type = TypeDecl.EnsureTypeWithName(tokens, ref index, out name); Parser.EnsureToken(tokens, ref index, ";"); var decl = new TypedefDecl(); decl.Name = name; decl.Type = type; return(new SymbolDecl[] { decl }); } else if (Parser.Token(tokens, ref index, "enum")) { if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } Parser.Token(tokens, ref index, "class"); string name = Parser.EnsureId(tokens, ref index); if (Parser.Token(tokens, ref index, ":")) { TypeDecl.EnsureTypeWithoutName(tokens, ref index); } if (!Parser.Token(tokens, ref index, ";")) { Parser.EnsureToken(tokens, ref index, "{"); var decl = new EnumDecl { Name = name, Children = new List <SymbolDecl>(), }; while (true) { if (Parser.Token(tokens, ref index, "}")) { break; } while (index < tokens.Length && tokens[index].Length >= 3 && tokens[index].StartsWith("///")) { index++; } decl.Children.Add(new EnumItemDecl { Name = Parser.EnsureId(tokens, ref index), }); string token = null; Parser.SkipUntil(tokens, ref index, out token, ",", "}"); if (token == "}") { break; } } if (Parser.Id(tokens, ref index, out name)) { var varDecl = new VarDecl { Static = false, Name = name, Type = new RefTypeDecl { Name = decl.Name, }, }; Parser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl, varDecl }); } else { Parser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl }); } } } else if (Parser.Token(tokens, ref index, "struct") || Parser.Token(tokens, ref index, "class") || Parser.Token(tokens, ref index, "union")) { if (Parser.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); Parser.EnsureToken(tokens, ref index, "}"); Parser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl }); } else { string name = Parser.EnsureId(tokens, ref index); if (!Parser.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 (Parser.Token(tokens, ref index, "<")) { if (!Parser.Token(tokens, ref index, ">")) { while (true) { int oldIndex = index; try { templateDecl.Specialization.Add(TypeDecl.EnsureTypeWithoutName(tokens, ref index)); } catch (ArgumentException) { index = oldIndex; Parser.SkipUntilInTemplate(tokens, ref index, ",", ">"); index--; templateDecl.Specialization.Add(new ConstantTypeDecl { Value = tokens .Skip(oldIndex) .Take(index - oldIndex) .Aggregate((a, b) => a + " " + b), }); } if (Parser.Token(tokens, ref index, ">")) { break; } Parser.EnsureToken(tokens, ref index, ","); } } } } Parser.Token(tokens, ref index, "abstract"); if (Parser.Token(tokens, ref index, ":")) { while (true) { Access access = classDecl.ClassType == ClassType.Class ? Access.Private : Access.Public; Parser.Token(tokens, ref index, "virtual"); if (Parser.Token(tokens, ref index, "private")) { access = Access.Private; } else if (Parser.Token(tokens, ref index, "protected")) { access = Access.Protected; } else if (Parser.Token(tokens, ref index, "public")) { access = Access.Public; } Parser.Token(tokens, ref index, "virtual"); classDecl.BaseTypes.Add(new BaseTypeDecl { Access = access, Type = TypeDecl.EnsureTypeWithoutName(tokens, ref index), }); if (!Parser.Token(tokens, ref index, ",")) { break; } } } Parser.EnsureToken(tokens, ref index, "{"); while (true) { if (Parser.Token(tokens, ref index, "}")) { break; } Access access = classDecl.ClassType == ClassType.Class ? Access.Private : Access.Public; if (Parser.Token(tokens, ref index, "private")) { access = Access.Private; Parser.EnsureToken(tokens, ref index, ":"); } else if (Parser.Token(tokens, ref index, "protected")) { access = Access.Protected; Parser.EnsureToken(tokens, ref index, ":"); } else if (Parser.Token(tokens, ref index, "public")) { access = Access.Public; Parser.EnsureToken(tokens, ref index, ":"); } ParseSymbols(tokens, ref index, classDecl, access); } SymbolDecl decl = classDecl; if (templateDecl != null) { templateDecl.Element = decl; decl = templateDecl; } if (Parser.Id(tokens, ref index, out name)) { var varDecl = new VarDecl { Static = false, Name = name, Type = new RefTypeDecl { Name = classDecl.Name, }, }; Parser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl, varDecl }); } else { Parser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl }); } } } } else if (!Parser.Token(tokens, ref index, ";")) { Function function = Function.Function; { int oldIndex = index; string name = null; if (Parser.Id(tokens, ref index, out name)) { if (Parser.Token(tokens, ref index, "(")) { Parser.SkipUntil(tokens, ref index, ")"); if (Parser.Token(tokens, ref index, ";") || Parser.Token(tokens, ref index, "=") || Parser.Token(tokens, ref index, ":") || Parser.Token(tokens, ref index, "{")) { function = Function.Constructor; } } index = oldIndex; } else if (Parser.Token(tokens, ref index, "~")) { function = Function.Destructor; } } if (function == Function.Function) { Virtual virtualFunction = Virtual.Normal; Parser.Token(tokens, ref index, "extern"); Parser.Token(tokens, ref index, "mutable"); if (Parser.Token(tokens, ref index, "virtual")) { virtualFunction = Virtual.Virtual; } else if (Parser.Token(tokens, ref index, "static")) { virtualFunction = Virtual.Static; } Parser.Token(tokens, ref index, "inline"); Parser.Token(tokens, ref index, "__forceinline"); if (Parser.Token(tokens, ref index, "operator")) { TypeDecl returnType = null; { int oldIndex = index; Parser.SkipUntilInTemplate(tokens, ref index, "("); int modify = --index; tokens[modify] = "$"; index = oldIndex; returnType = TypeDecl.EnsureTypeWithoutName(tokens, ref index); if (index != modify) { throw new ArgumentException("Failed to parse."); } tokens[modify] = "("; } var decl = new FuncDecl { Virtual = global::Parser.Virtual.Normal, Name = "operator", Function = function, }; TypeDecl functionType = null; Action <TypeDecl> continuation = null; CallingConvention callingConvention = CallingConvention.Default; TypeDecl.ParseTypeContinueAfterName(tokens, ref index, ref callingConvention, out functionType, out continuation); continuation(returnType); decl.Type = functionType; if (!Parser.Token(tokens, ref index, ";")) { Parser.EnsureToken(tokens, ref index, "{"); Parser.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 (TypeDecl.ParseType(tokens, ref index, out type, out name)) { if (name == null) { throw new ArgumentException("Failed to parse."); } if (type is FunctionTypeDecl) { if (Parser.Token(tokens, ref index, "=")) { if (Parser.Token(tokens, ref index, "0")) { virtualFunction = Virtual.Abstract; } else { Parser.EnsureToken(tokens, ref index, "default", "delete"); } } var decl = new FuncDecl { Virtual = virtualFunction, Name = name, Type = type, Function = Function.Function, }; if (!Parser.Token(tokens, ref index, ";")) { Parser.EnsureToken(tokens, ref index, "{"); Parser.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 (Parser.Token(tokens, ref index, "=")) { Parser.SkipUntil(tokens, ref index, ";"); } else { Parser.EnsureToken(tokens, ref index, ";"); } var decl = new VarDecl { Static = virtualFunction == Virtual.Static, Name = name, Type = type, }; return(new SymbolDecl[] { decl }); } } } } else { var decl = new FuncDecl { Virtual = global::Parser.Virtual.Normal, Name = (function == Function.Constructor ? "" : "~") + Parser.EnsureId(tokens, ref index), Function = function, }; TypeDecl functionType = null; Action <TypeDecl> continuation = null; CallingConvention callingConvention = CallingConvention.Default; TypeDecl.ParseTypeContinueAfterName(tokens, ref index, ref callingConvention, out functionType, out continuation); continuation(new RefTypeDecl { Name = "void" }); decl.Type = functionType; if (Parser.Token(tokens, ref index, "=")) { Parser.EnsureToken(tokens, ref index, "default", "delete"); } if (!Parser.Token(tokens, ref index, ";")) { if (Parser.Token(tokens, ref index, ":")) { Parser.SkipUntil(tokens, ref index, "{"); } else { Parser.EnsureToken(tokens, ref index, "{"); } Parser.SkipUntil(tokens, ref index, "}"); } return(new SymbolDecl[] { decl }); } } return(null); }