public static TypeDecl EnsureTypeWithoutNameInTemplate(string[] tokens, ref int index) { int oldIndex = index; TypeDecl type = null; try { type = EnsureTypeWithoutName(tokens, ref index); } catch (ArgumentException) { index = oldIndex; } if (CppParser.Token(tokens, ref index, ">") || CppParser.Token(tokens, ref index, ",")) { index--; } else { index = oldIndex; CppParser.SkipUntilInTemplate(tokens, ref index, ">", ","); index--; type = new ConstantTypeDecl { Value = tokens .Skip(oldIndex) .Take(index - oldIndex) .Aggregate((a, b) => a + " " + b), }; } return(type); }
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.EnsureTypeWithoutName(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; } while (index < tokens.Length && tokens[index].Length >= 3 && tokens[index].StartsWith("///")) { index++; } decl.Children.Add(new EnumItemDecl { Name = CppParser.EnsureId(tokens, ref index), }); 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; try { templateDecl.Specialization.Add(CppTypeParser.EnsureTypeWithoutName(tokens, ref index)); } catch (ArgumentException) { index = oldIndex; CppParser.SkipUntilInTemplate(tokens, ref index, ",", ">"); index--; templateDecl.Specialization.Add(new ConstantTypeDecl { Value = tokens .Skip(oldIndex) .Take(index - oldIndex) .Aggregate((a, b) => a + " " + b), }); } 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, }; 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 { 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, ":")) { CppParser.SkipUntil(tokens, ref index, "{"); } else { 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 void ParseTypeContinue(string[] tokens, ref int index, out CallingConvention callingConvention, out TypeDecl decl, out Action <TypeDecl> continuation, out string name) { callingConvention = CallingConvention.Default; decl = null; continuation = null; name = null; if (CppParser.Token(tokens, ref index, "__cdecl")) { callingConvention = CallingConvention.CDecl; } else if (CppParser.Token(tokens, ref index, "__clrcall")) { callingConvention = CallingConvention.ClrCall; } else if (CppParser.Token(tokens, ref index, "__stdcall")) { callingConvention = CallingConvention.StdCall; } else if (CppParser.Token(tokens, ref index, "__fastcall")) { callingConvention = CallingConvention.FastCall; } else if (CppParser.Token(tokens, ref index, "__thiscall")) { callingConvention = CallingConvention.ThisCall; } else if (CppParser.Token(tokens, ref index, "__vectorcall")) { callingConvention = CallingConvention.VectorCall; } TypeDecl beforeDecl = null; Action <TypeDecl> beforeContinuation = null; ParseTypeContinueBeforeName(tokens, ref index, out beforeDecl, out beforeContinuation, out name); TypeDecl middleDecl = null; Action <TypeDecl> middleContinuation = null; if (name == null) { int middleIndex = index; bool recursive = false; if (CppParser.Token(tokens, ref middleIndex, "(")) { string token = null; CppParser.SkipUntil(tokens, ref middleIndex, out token, ",", ")"); if (token == ")") { recursive = tokens[middleIndex] == "(" || tokens[middleIndex] == "["; } } if (recursive) { CppParser.EnsureToken(tokens, ref index, "("); var middleCallingConvention = CallingConvention.Default; ParseTypeContinue(tokens, ref index, out middleCallingConvention, out middleDecl, out middleContinuation, out name); CppParser.EnsureToken(tokens, ref index, ")"); if (middleCallingConvention != CallingConvention.Default) { if (callingConvention == CallingConvention.Default) { callingConvention = middleCallingConvention; } else { throw new ArgumentException("Failed to parse."); } } } } TypeDecl afterDecl = null; Action <TypeDecl> afterContinuation = null; ParseTypeContinueAfterName(tokens, ref index, ref callingConvention, out afterDecl, out afterContinuation); decl = middleDecl; continuation = middleContinuation; if (afterDecl != null) { if (decl == null) { decl = afterDecl; } else { continuation(afterDecl); } continuation = afterContinuation; } if (beforeDecl != null) { if (decl == null) { decl = beforeDecl; } else { continuation(beforeDecl); } continuation = beforeContinuation; } }
internal static void ParseTypeContinueAfterName(string[] tokens, ref int index, ref CallingConvention callingConvention, out TypeDecl decl, out Action <TypeDecl> continuation) { decl = null; continuation = null; while (true) { if (CppParser.Token(tokens, ref index, "[")) { var oldIndex = index; CppParser.SkipUntil(tokens, ref index, "]"); var arrayDecl = new ArrayTypeDecl { Expression = tokens .Skip(oldIndex) .Take(index - 1 - oldIndex) .Aggregate("", (a, b) => a == "" ? b : a + " " + b), }; if (decl == null) { continuation = x => arrayDecl.Element = x; } else { arrayDecl.Element = decl; } decl = arrayDecl; } else if (CppParser.Token(tokens, ref index, "(")) { var funcDecl = new FunctionTypeDecl { Const = false, CallingConvention = callingConvention, Parameters = new List <VarDecl>(), }; callingConvention = CallingConvention.Default; if (decl == null) { continuation = x => funcDecl.ReturnType = x; } else { funcDecl.ReturnType = decl; } decl = funcDecl; bool skipParameters = false; if (CppParser.Token(tokens, ref index, "void")) { if (CppParser.Token(tokens, ref index, ")")) { skipParameters = true; } else { index--; } } if (!skipParameters && !CppParser.Token(tokens, ref index, ")")) { while (true) { string name = null; var parameterType = EnsureType(tokens, ref index, out name); funcDecl.Parameters.Add(new VarDecl { Static = false, Name = name, Type = parameterType, }); if (CppParser.Token(tokens, ref index, "=")) { CppParser.SkipUntilInTemplate(tokens, ref index, ",", ")", ";"); index--; } if (CppParser.Token(tokens, ref index, ")")) { break; } CppParser.EnsureToken(tokens, ref index, ","); } } while (true) { if (CppParser.Token(tokens, ref index, "const")) { funcDecl.Const = true; } else if (CppParser.Token(tokens, ref index, "override")) { } else { break; } } } else { break; } } }
static void ParseTypeContinueBeforeName(string[] tokens, ref int index, out TypeDecl decl, out Action <TypeDecl> continuation, out string name) { decl = null; continuation = null; name = null; while (true) { Decoration?decoration = null; if (CppParser.Token(tokens, ref index, "const")) { decoration = Decoration.Const; } else if (CppParser.Token(tokens, ref index, "volatile")) { decoration = Decoration.Volatile; } else if (CppParser.Token(tokens, ref index, "*")) { decoration = Decoration.Pointer; } else if (CppParser.Token(tokens, ref index, "&")) { if (CppParser.Token(tokens, ref index, "&")) { decoration = Decoration.RightRef; } else { decoration = Decoration.LeftRef; } } else if (CppParser.Token(tokens, ref index, ".")) { CppParser.EnsureToken(tokens, ref index, "."); CppParser.EnsureToken(tokens, ref index, "."); var vaDecl = new VariadicArgumentTypeDecl { }; if (decl == null) { continuation = x => vaDecl.Element = x; } else { vaDecl.Element = decl; } decl = vaDecl; } else { TypeDecl classType = null; if (ParseMiniType(tokens, ref index, out classType)) { if (CppParser.Token(tokens, ref index, ":")) { CppParser.EnsureToken(tokens, ref index, ":"); var classMemberTypeDecl = new ClassMemberTypeDecl { ClassType = classType, }; if (decl == null) { continuation = x => classMemberTypeDecl.Element = x; } else { classMemberTypeDecl.Element = decl; } decl = classMemberTypeDecl; } else { var subType = classType as SubTypeDecl; var refType = classType as RefTypeDecl; if (subType != null) { name = subType.Name; var classMemberTypeDecl = new ClassMemberTypeDecl { ClassType = subType.Parent, }; if (decl == null) { continuation = x => classMemberTypeDecl.Element = x; } else { classMemberTypeDecl.Element = decl; } decl = classMemberTypeDecl; } else if (refType != null) { name = refType.Name; } else { throw new ArgumentException("Failed to parse."); } if (name == "operator") { if (tokens[index + 1] == "(") { name += " " + tokens[index]; index += 1; } else if (tokens[index + 2] == "(") { name += " " + tokens[index] + tokens[index + 1]; index += 2; } else { throw new ArgumentException("Failed to parse."); } } break; } } else { break; } } if (decoration != null) { var decorateDecl = new DecorateTypeDecl { Decoration = decoration.Value, }; if (decl == null) { continuation = x => decorateDecl.Element = x; } else { decorateDecl.Element = decl; } decl = decorateDecl; } } }
public static bool ParseMiniType(string[] tokens, ref int index, out TypeDecl decl) { decl = null; if (CppParser.Token(tokens, ref index, "const")) { decl = new DecorateTypeDecl { Decoration = Decoration.Const, Element = EnsureMiniType(tokens, ref index), }; return(true); } else if (CppParser.Token(tokens, ref index, "volatile")) { decl = new DecorateTypeDecl { Decoration = Decoration.Volatile, Element = EnsureMiniType(tokens, ref index), }; return(true); } else if (CppParser.Token(tokens, ref index, "signed")) { decl = new DecorateTypeDecl { Decoration = Decoration.Signed, Element = EnsureMiniType(tokens, ref index), }; return(true); } else if (CppParser.Token(tokens, ref index, "unsigned")) { decl = new DecorateTypeDecl { Decoration = Decoration.Unsigned, Element = EnsureMiniType(tokens, ref index), }; return(true); } else if (CppParser.Token(tokens, ref index, "decltype")) { CppParser.EnsureToken(tokens, ref index, "("); int oldIndex = index; CppParser.SkipUntil(tokens, ref index, ")"); decl = new DeclTypeDecl { Expression = tokens .Skip(oldIndex) .Take(index - 1 - oldIndex) .Aggregate((a, b) => a + " " + b), }; return(true); } else if (CppParser.Token(tokens, ref index, "false") || CppParser.Token(tokens, ref index, "true")) { decl = new ConstantTypeDecl { Value = tokens[index - 1], }; return(true); } else { if (index < tokens.Length) { int value = 0; if (int.TryParse(tokens[index], out value)) { index++; decl = new ConstantTypeDecl { Value = tokens[index - 1], }; return(true); } } string token = null; CppParser.Token(tokens, ref index, "typename"); if (CppParser.Id(tokens, ref index, out token)) { if (token == "L" && index < tokens.Length) { if (tokens[index].StartsWith("\"")) { token += tokens[index]; index++; } } decl = new RefTypeDecl { Name = token, }; if (token != "operator") { while (true) { if (CppParser.Token(tokens, ref index, "<")) { var genericDecl = new GenericTypeDecl { Element = decl, TypeArguments = new List <TypeDecl>(), }; decl = genericDecl; if (!CppParser.Token(tokens, ref index, ">")) { while (true) { genericDecl.TypeArguments.Add(EnsureTypeWithoutNameInTemplate(tokens, ref index)); if (CppParser.Token(tokens, ref index, ">")) { break; } else { CppParser.EnsureToken(tokens, ref index, ","); } } } } else if (CppParser.Token(tokens, ref index, ":")) { CppParser.EnsureToken(tokens, ref index, ":"); CppParser.Token(tokens, ref index, "template"); if (CppParser.Id(tokens, ref index, out token)) { decl = new SubTypeDecl { Parent = decl, Name = token, }; } else { index -= 2; break; } } else { break; } } } return(true); } else { return(false); } } }