// ============ Parser ============

        private MemberPart MatchMember(TextParser state)
        {
            MemberPart lastMember = null;

            do
            {
                string fullpart = state.TakeTill('.', ',', '<', '(');
                if (fullpart.Length <= 0)
                {
                    break;
                }
                lastMember = new MemberPart()
                {
                    MemberName = fullpart, Parent = lastMember
                };
                if (state.Next == '<')
                {
                    lastMember.GenericTypes = MatchMemberList('<', state, '>')?.ToArray();
                }
                if (state.Next == '(')
                {
                    lastMember.Parameters = MatchMemberList('(', state, ')')?.ToArray();
                }
                if (state.IsEmpty || state.Next != '.')
                {
                    break;
                }
                state.Advance();
            } while (true);
            if (lastMember == null)
            {
                state.Error("Identifier expected");
            }
            return(lastMember);
        }
        private List <MemberPart> MatchMemberList(TextParser state)
        {
            List <MemberPart> result = new List <MemberPart>();
            MemberPart        nextMatch;

            do
            {
                nextMatch = MatchMember(state);
                if (nextMatch == null)
                {
                    break;
                }
                result.Add(nextMatch);
                if (state.Next != ',')
                {
                    break;
                }
                state.Advance();
            } while (true);
            return(result.Count <= 0 ? null : result);
        }