Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }