diff Implab.ServiceHost/Unity/TypeReferenceParser.cs @ 278:6691aff01de1 v3

Implab: added XmlDefaultSeializer (SerializersPool is now obsolete) Implab.ServiceHost: rewritten TypeReference (added support for nested types), stable API
author cin
date Thu, 03 May 2018 09:59:44 +0300
parents 963b17c275be
children
line wrap: on
line diff
--- a/Implab.ServiceHost/Unity/TypeReferenceParser.cs	Sat Apr 28 18:48:09 2018 +0300
+++ b/Implab.ServiceHost/Unity/TypeReferenceParser.cs	Thu May 03 09:59:44 2018 +0300
@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Text.RegularExpressions;
 
 namespace Implab.ServiceHost.Unity {
@@ -21,10 +22,12 @@
 
             CloseArray,
 
+            Plus,
+
             Eof
         }
 
-        readonly Regex _tokens = new Regex(@"([\w\+]+)|\s*([\.{},\[\]])\s*");
+        readonly Regex _tokens = new Regex(@"\G(?:([\w]+)|\s*([\+\.{},\[\]])\s*)", RegexOptions.Compiled);
 
         TokenType m_token;
 
@@ -83,6 +86,9 @@
                         case "]":
                             m_token = TokenType.CloseArray;
                             break;
+                        case "+":
+                            m_token = TokenType.Plus;
+                            break;
                     }
                 }
                 return true;
@@ -97,7 +103,7 @@
             return result;
         }
 
-        string[] ReadTypeName() {
+        string[] ReadQTypeName() {
             var parts = new List<string>();
 
             string current = null;
@@ -129,31 +135,95 @@
             return parts.ToArray();
         }
 
+        string ReadNQTypeName() {
+            ReadToken();
+            if (Token != TokenType.Word)
+                ThrowUnexpectedToken();
+            return TokenValue;
+        }
+
         TypeReference ReadTypeReference() {
 
-            var parts = ReadTypeName();
+            var parts = ReadQTypeName();
             if (parts == null)
                 return null;
 
-            var typeReference = new TypeReference {
-                Namespace = string.Join(".", parts, 0, parts.Length - 1),
-                TypeName = parts[parts.Length - 1]
-            };
+            var genericParameters = ReadGenericParams();
+
+            var typeReference = TypeReference.Create(
+                string.Join(".", parts, 0, parts.Length - 1),
+                parts[parts.Length - 1],
+                genericParameters.Length
+            );
+
+            if (genericParameters.Length > 0 && genericParameters.All(x => x != null))
+                typeReference = typeReference.MakeGenericType(genericParameters);
+
+            typeReference = ReadArraySpec(typeReference);
+
+            if(Token == TokenType.Plus)
+                return ReadNestedType(typeReference);
+
+            return typeReference;
+        }
+
+        TypeReference ReadNestedType(TypeReference declaringType) {
+            var name = ReadNQTypeName();
+            if(string.IsNullOrEmpty(name))
+                throw new FormatException("Nested type name can't be empty");
+            ReadToken();
+            
+            var genericParameters = ReadGenericParams();
+
+            var typeReference = declaringType.Create(
+                name,
+                genericParameters.Length
+            );
 
-            switch (Token) {
-                case TokenType.OpenList:
-                    typeReference.GenericParameters = ReadTypeReferenceList();
-                    if (Token != TokenType.CloseList)
-                        ThrowUnexpectedToken();
-                    ReadToken();
-                    break;
+            if (genericParameters.Length > 0 && genericParameters.All(x => x != null))
+                typeReference = typeReference.MakeGenericType(genericParameters);
+
+            typeReference = ReadArraySpec(typeReference);
+
+            if(Token == TokenType.Plus)
+                return ReadNestedType(typeReference);
+
+            return typeReference;
+        }
+
+        TypeReference[] ReadGenericParams() {
+            if (Token == TokenType.OpenList) {
+                var genericParameters = ReadTypeReferenceList();
+                if (Token != TokenType.CloseList)
+                    ThrowUnexpectedToken();
+                ReadToken();
+
+                return genericParameters;
+            }
+
+            return Array.Empty<TypeReference>();
+        }
+
+        TypeReference ReadArraySpec(TypeReference typeReference) {
+            while (Token == TokenType.OpenArray) {
+                var rank = CountRank();
+                if (Token != TokenType.CloseArray)
+                    ThrowUnexpectedToken();
+                
+                typeReference = typeReference.MakeArrayType(rank);
+                
+                ReadToken();
             }
 
             return typeReference;
         }
 
-        int CountDimentions() {
-            return 0;
+        int CountRank() {
+            int rank = 0;
+            do {
+                rank++;
+            } while(ReadToken() && Token == TokenType.Comma);
+            return rank;
         }
 
         TypeReference[] ReadTypeReferenceList() {