private TypeId ParseTypeId() { // id always starts with a name var nameSegments = ParseNameSegmentsWithArity(); var typeIdBuilder = TypeIdBuilder.Create(); foreach (var(name, arity) in nameSegments) { typeIdBuilder = typeIdBuilder .AddNameSegment(name) .SetArity(arity); if (m_OuterTypes.Contains(typeIdBuilder.ToTypeId())) { typeIdBuilder = typeIdBuilder.BeginNestedType(); } } var type = typeIdBuilder.ToTypeId(); // if the type if followed by square brackets, the id refers to an array type // arrays of arrays are allowed, too type = ParseArraySuffix(type); // all token should be parsed now MatchToken(MemberIdTokenKind.Eof); return(type); }
private (TypeId definingType, string name) ParseMemberId() { // id always starts with a name var nameSegments = ParseNameSegmentsWithArity(); // there need to be at least 2 name segments: // - The defining type (might be a single name if type is defined in global namespace) // - The name of the member (method, field, property, event) if (nameSegments.Count < 2) { throw new MemberIdParserException("Invalid input, type member name requires name of defining type and member"); } // the last segment is the name of the member var lastSegment = nameSegments.Last(); // there mustn't be any (type) arity on the last segment // (method type parameters are handled separately in ParseMethoodId()) if (lastSegment.arity != 0) { throw new MemberIdParserException("Invalid input, unexpected arity suffix on member name"); } // all segments but the last are part of the name of the defining type nameSegments = nameSegments.Take(nameSegments.Count - 1).ToList(); var typeBuilder = TypeIdBuilder.Create(); foreach (var(name, arity) in nameSegments) { typeBuilder = typeBuilder .AddNameSegment(name) .SetArity(arity); if (m_OuterTypes.Contains(typeBuilder.ToTypeId())) { typeBuilder = typeBuilder.BeginNestedType(); } } return(typeBuilder.ToTypeId(), lastSegment.name); }
private TypeId ParseTypeName() { TypeId type; if (TestAndMatchToken(MemberIdTokenKind.Backtick)) { var index = Int32.Parse(MatchToken(MemberIdTokenKind.Number)); type = new GenericTypeParameterId(GenericTypeParameterId.MemberKind.Type, index); } else if (TestAndMatchToken(MemberIdTokenKind.DoubleBacktick)) { var index = Int32.Parse(MatchToken(MemberIdTokenKind.Number)); type = new GenericTypeParameterId(GenericTypeParameterId.MemberKind.Method, index); } else { var typeIdBuilder = TypeIdBuilder.Create(); // there needs to be at least one name segment typeIdBuilder = typeIdBuilder.AddNameSegment(MatchToken(MemberIdTokenKind.Name)); // consume all name tokens as long as the current token is a '.' // A open brace '{' indicates the start of a list of type arguments while (TestToken(MemberIdTokenKind.Dot, MemberIdTokenKind.OpenBrace)) { if (TestAndMatchToken(MemberIdTokenKind.Dot)) { // match a single name token and append it to the current type name var name = MatchToken(MemberIdTokenKind.Name); typeIdBuilder = typeIdBuilder.AddNameSegment(name); if (m_OuterTypes.Contains(typeIdBuilder.ToTypeId())) { typeIdBuilder = typeIdBuilder.BeginNestedType(); } } else if (TestAndMatchToken(MemberIdTokenKind.OpenBrace)) { // parse list of type arguments var typeArguments = ParseTypeNameList(); typeIdBuilder = typeIdBuilder.SetTypeArguments(typeArguments); if (m_OuterTypes.Contains(typeIdBuilder.ToTypeId())) { typeIdBuilder = typeIdBuilder.BeginNestedType(); } // type argument list must be followed by a '}' MatchToken(MemberIdTokenKind.CloseBrace); } else { // should never happen throw new InvalidOperationException(); } } type = typeIdBuilder.ToTypeId(); } // optional part: array declaration // if the type if followed by square brackets, the id refers to an array type // arrays of arrays are allowed, too type = ParseArraySuffix(type); // optional suffix: @ // if the type is followed by an '@' the parameter is being parsed by reference // (methods with 'out' or 'ref' parameter) if (TestAndMatchToken(MemberIdTokenKind.At)) { type = new ByReferenceTypeId(type); } return(type); }