view Implab.ServiceHost/Unity/TypeReferenceParser.cs @ 267:6b3e5c48131b v3

Working on Unity xml configuration
author cin
date Fri, 20 Apr 2018 19:05:12 +0300
parents
children 0be8a6ae8307
line wrap: on
line source

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Implab.ServiceHost.Unity {
    public class TypeReferenceParser {
        enum TokenType {
            None,

            Word,

            Dot,

            Comma,

            OpenList,

            CloseList,

            Eof
        }

        readonly Regex _tokens = new Regex(@"(\w+)|\s*([\.{},])\s*");

        TokenType m_token;

        string m_tokenValue;

        int m_pos;

        readonly string m_text;

        TokenType Token { get { return m_token; } }

        string TokenValue { get { return m_tokenValue; } }

        public TypeReferenceParser(string text) {
            Safe.ArgumentNotEmpty(text, nameof(text));
            m_text = text;
        }

        bool ReadToken() {
            if (m_pos >= m_text.Length) {
                m_token = TokenType.Eof;
                m_tokenValue = null;
                return false;
            }

            var m = _tokens.Match(m_text, m_pos);

            if (m.Success) {
                m_pos += m.Length;
                if (m.Groups[1].Success) {
                    m_token = TokenType.Word;
                    m_tokenValue = m.Groups[1].Value;
                } else if (m.Groups[2].Success) {
                    m_tokenValue = null;
                    switch (m.Groups[2].Value) {
                        case "{":
                            m_token = TokenType.OpenList;
                            break;
                        case "}":
                            m_token = TokenType.CloseList;
                            break;
                        case ".":
                            m_token = TokenType.Dot;
                            break;
                        case ",":
                            m_token = TokenType.Comma;
                            break;
                    }
                }
                return true;
            }
            throw new FormatException($"Failed to parse '{m_text}' at pos {m_pos}");
        }

        public TypeRerefence Pase() {

        }

        string[] ReadTypeName() {
            var parts = new List<string>();

            string current = null;
            bool stop = false;
            while ((!stop) && ReadToken()) {
                switch (Token) {
                    case TokenType.Word:
                        if (current != null)
                            ThrowUnexpectedToken();
                        current = TokenValue;
                        break;
                    case TokenType.Dot:
                        if (current == null)
                            ThrowUnexpectedToken();
                        parts.Add(current);
                        current = null;
                        break;
                    default:
                        stop = true;
                        break;
                }
            }
            if (current != null)
                parts.Add(current);

            if (parts.Count == 0)
                return null;

            return parts.ToArray();
        }

        TypeReference ReadTypeReference() {

            var parts = ReadTypeName();
            if (parts == null)
                return null;

            var typeReference = new TypeReference {
                        Namespace = string.Join(",", parts, 0, parts.Length - 1),
                        TypeName = parts[parts.Length - 1]
                    };

            switch (Token) {
                case TokenType.Eof:
                    break;
                case TokenType.OpenList:
                    typeReference.GenericParameters = ReadTypeReferenceList();
                    if(Token != TokenType.CloseList)
                        ThrowUnexpectedToken();
                    break;
                default:
                    ThrowUnexpectedToken();
                    break;
            }

            return typeReference;
        }

        TypeReference[] ReadTypeReferenceList() {
            throw new NotImplementedException();
        }

        void ReadDot() {
            if (!ReadToken() || Token != TokenType.Dot)
                ThrowUnexpectedToken();
        }

        void ThrowUnexpectedToken() {
            throw new FormatException($"Unexpected '{Token}' at {m_pos}");
        }


    }
}