Example #1
0
        public static bool ParseType(string[] tokens, ref int index, out TypeDecl decl, out string name)
        {
            decl = null;
            name = null;
            TypeDecl miniType = null;

            if (ParseMiniType(tokens, ref index, out miniType))
            {
                CallingConvention callingConvention = CallingConvention.Default;
                TypeDecl          continuationDecl  = null;
                Action <TypeDecl> continuation      = null;
                ParseTypeContinue(tokens, ref index, out callingConvention, out continuationDecl, out continuation, out name);
                if (callingConvention != CallingConvention.Default)
                {
                    throw new ArgumentException("Failed to parse.");
                }
                if (continuationDecl != null)
                {
                    continuation(miniType);
                    decl = continuationDecl;
                }
                else
                {
                    decl = miniType;
                }
                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #2
0
        public static TypeDecl EnsureType(string[] tokens, ref int index, out string name)
        {
            TypeDecl decl = null;

            if (!ParseType(tokens, ref index, out decl, out name))
            {
                throw new ArgumentException("Failed to parse.");
            }
            return(decl);
        }
Example #3
0
        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 (Parser.Token(tokens, ref index, "__cdecl"))
            {
                callingConvention = CallingConvention.CDecl;
            }
            else if (Parser.Token(tokens, ref index, "__clrcall"))
            {
                callingConvention = CallingConvention.ClrCall;
            }
            else if (Parser.Token(tokens, ref index, "__stdcall"))
            {
                callingConvention = CallingConvention.StdCall;
            }
            else if (Parser.Token(tokens, ref index, "__fastcall"))
            {
                callingConvention = CallingConvention.FastCall;
            }
            else if (Parser.Token(tokens, ref index, "__thiscall"))
            {
                callingConvention = CallingConvention.ThisCall;
            }
            else if (Parser.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 (Parser.Token(tokens, ref middleIndex, "("))
                {
                    string token = null;
                    Parser.SkipUntil(tokens, ref middleIndex, out token, ",", ")");
                    if (token == ")")
                    {
                        recursive = tokens[middleIndex] == "(" || tokens[middleIndex] == "[";
                    }
                }

                if (recursive)
                {
                    Parser.EnsureToken(tokens, ref index, "(");
                    var middleCallingConvention = CallingConvention.Default;
                    ParseTypeContinue(tokens, ref index, out middleCallingConvention, out middleDecl, out middleContinuation, out name);
                    Parser.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;
            }
        }
Example #4
0
        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 (Parser.Token(tokens, ref index, "["))
                {
                    Parser.SkipUntil(tokens, ref index, "]");
                    var arrayDecl = new ArrayTypeDecl();
                    if (decl == null)
                    {
                        continuation = x => arrayDecl.Element = x;
                    }
                    else
                    {
                        arrayDecl.Element = decl;
                    }
                    decl = arrayDecl;
                }
                else if (Parser.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 (Parser.Token(tokens, ref index, "void"))
                    {
                        if (Parser.Token(tokens, ref index, ")"))
                        {
                            skipParameters = true;
                        }
                        else
                        {
                            index--;
                        }
                    }

                    if (!skipParameters && !Parser.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 (Parser.Token(tokens, ref index, "="))
                            {
                                Parser.SkipUntilInTemplate(tokens, ref index, ",", ")", ";");
                                index--;
                            }

                            if (Parser.Token(tokens, ref index, ")"))
                            {
                                break;
                            }
                            Parser.EnsureToken(tokens, ref index, ",");
                        }
                    }

                    while (true)
                    {
                        if (Parser.Token(tokens, ref index, "const"))
                        {
                            funcDecl.Const = true;
                        }
                        else if (Parser.Token(tokens, ref index, "override"))
                        {
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                else
                {
                    break;
                }
            }
        }
Example #5
0
        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 (Parser.Token(tokens, ref index, "const"))
                {
                    decoration = Decoration.Const;
                }
                else if (Parser.Token(tokens, ref index, "volatile"))
                {
                    decoration = Decoration.Volatile;
                }
                else if (Parser.Token(tokens, ref index, "*"))
                {
                    decoration = Decoration.Pointer;
                }
                else if (Parser.Token(tokens, ref index, "&"))
                {
                    decoration = Decoration.LeftRef;
                }
                else if (Parser.Token(tokens, ref index, "&&"))
                {
                    decoration = Decoration.RightRef;
                }
                else if (Parser.Token(tokens, ref index, "."))
                {
                    Parser.EnsureToken(tokens, ref index, ".");
                    Parser.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 (Parser.Token(tokens, ref index, ":"))
                        {
                            Parser.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;
                }
            }
        }
Example #6
0
        static bool ParseMiniType(string[] tokens, ref int index, out TypeDecl decl)
        {
            decl = null;
            if (Parser.Token(tokens, ref index, "const"))
            {
                decl = new DecorateTypeDecl
                {
                    Decoration = Decoration.Const,
                    Element    = EnsureMiniType(tokens, ref index),
                };
                return(true);
            }
            else if (Parser.Token(tokens, ref index, "volatile"))
            {
                decl = new DecorateTypeDecl
                {
                    Decoration = Decoration.Volatile,
                    Element    = EnsureMiniType(tokens, ref index),
                };
                return(true);
            }
            else if (Parser.Token(tokens, ref index, "signed"))
            {
                decl = new DecorateTypeDecl
                {
                    Decoration = Decoration.Signed,
                    Element    = EnsureMiniType(tokens, ref index),
                };
                return(true);
            }
            else if (Parser.Token(tokens, ref index, "unsigned"))
            {
                decl = new DecorateTypeDecl
                {
                    Decoration = Decoration.Unsigned,
                    Element    = EnsureMiniType(tokens, ref index),
                };
                return(true);
            }
            else if (Parser.Token(tokens, ref index, "decltype"))
            {
                Parser.EnsureToken(tokens, ref index, "(");
                int oldIndex = index;
                Parser.SkipUntil(tokens, ref index, ")");

                decl = new DeclTypeDecl
                {
                    Expression = tokens
                                 .Skip(oldIndex)
                                 .Take(index - 1 - oldIndex)
                                 .Aggregate((a, b) => a + " " + b),
                };
                return(true);
            }
            else if (Parser.Token(tokens, ref index, "false") || Parser.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;
                Parser.Token(tokens, ref index, "typename");
                if (Parser.Id(tokens, ref index, out token))
                {
                    decl = new RefTypeDecl
                    {
                        Name = token,
                    };

                    if (token != "operator")
                    {
                        while (true)
                        {
                            if (Parser.Token(tokens, ref index, "<"))
                            {
                                var genericDecl = new GenericTypeDecl
                                {
                                    Element       = decl,
                                    TypeArguments = new List <TypeDecl>(),
                                };
                                decl = genericDecl;

                                if (!Parser.Token(tokens, ref index, ">"))
                                {
                                    while (true)
                                    {
                                        genericDecl.TypeArguments.Add(EnsureTypeWithoutName(tokens, ref index));

                                        if (Parser.Token(tokens, ref index, ">"))
                                        {
                                            break;
                                        }
                                        else
                                        {
                                            Parser.EnsureToken(tokens, ref index, ",");
                                        }
                                    }
                                }
                            }
                            else if (Parser.Token(tokens, ref index, ":"))
                            {
                                Parser.EnsureToken(tokens, ref index, ":");
                                Parser.Token(tokens, ref index, "template");
                                if (Parser.Id(tokens, ref index, out token))
                                {
                                    decl = new SubTypeDecl
                                    {
                                        Parent = decl,
                                        Name   = token,
                                    };
                                }
                                else
                                {
                                    index -= 2;
                                    break;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                    }

                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }
Example #7
0
        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);
        }