// ============ 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);
        }
 public virtual MemberPart Parse <T> (string member)
 {
     return(ParseAndProcess(NormaliseQuery(member), "Parse", (text, state) => {
         MemberPart parsed = MatchMember(state);
         state.MustBeEmpty();
         return parsed;
     }));
 }
        public virtual MemberProxy <T> Get <T> (string member)
        {
            string normalised = NormaliseQuery(member);

            return(ParseAndProcess(normalised, "Find", (text, state) => {
                MemberPart parsed = MatchMember(state);
                state.MustBeEmpty();
                MemberProxy <T> result = PartToProxy <T>(parsed);
                return result;
            }));
        }
        private MemberProxy <T> PartToProxy <T> (MemberPart member)
        {
            Type type = GetType((member.Parent ?? member).ToString());

            if (type == null)
            {
                return(null);
            }
            MemberInfo[] info = type.GetMember(member.MemberName, Public | BindingFlags.Instance | Static);
            if (info == null || info.Length <= 0)
            {
                info = type.GetMember(member.MemberName, NonPublic | BindingFlags.Instance | Static);
            }
            if (info.Length > 1)
            {
                Log(Warning, "Multiple matches ({1}) found for {0}", member, info.Length);
            }
            return(InfoToProxy <T>(info[0]));
        }