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