Mercurial > pub > ImplabNet
annotate Implab.ServiceHost/Unity/TypeReferenceParser.cs @ 280:f07be402ab02 v3
Added Trace<T>.Debug(...) method for debug messages
Added ContainerBuilde.LoadConfig(Uri) method
author | cin |
---|---|
date | Fri, 25 May 2018 19:15:26 +0300 |
parents | 6691aff01de1 |
children |
rev | line source |
---|---|
267 | 1 using System; |
2 using System.Collections.Generic; | |
278
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
3 using System.Linq; |
267 | 4 using System.Text.RegularExpressions; |
5 | |
6 namespace Implab.ServiceHost.Unity { | |
268 | 7 internal class TypeReferenceParser { |
267 | 8 enum TokenType { |
9 None, | |
10 | |
11 Word, | |
12 | |
13 Dot, | |
14 | |
15 Comma, | |
16 | |
17 OpenList, | |
18 | |
19 CloseList, | |
20 | |
277 | 21 OpenArray, |
22 | |
23 CloseArray, | |
24 | |
278
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
25 Plus, |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
26 |
267 | 27 Eof |
28 } | |
29 | |
278
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
30 readonly Regex _tokens = new Regex(@"\G(?:([\w]+)|\s*([\+\.{},\[\]])\s*)", RegexOptions.Compiled); |
267 | 31 |
32 TokenType m_token; | |
33 | |
34 string m_tokenValue; | |
35 | |
36 int m_pos; | |
37 | |
268 | 38 int m_tokenPos; |
39 | |
267 | 40 readonly string m_text; |
41 | |
42 TokenType Token { get { return m_token; } } | |
43 | |
44 string TokenValue { get { return m_tokenValue; } } | |
45 | |
268 | 46 int TokenPos { get { return m_tokenPos; } } |
47 | |
267 | 48 public TypeReferenceParser(string text) { |
49 Safe.ArgumentNotEmpty(text, nameof(text)); | |
50 m_text = text; | |
51 } | |
52 | |
53 bool ReadToken() { | |
54 if (m_pos >= m_text.Length) { | |
55 m_token = TokenType.Eof; | |
56 m_tokenValue = null; | |
57 return false; | |
58 } | |
59 | |
60 var m = _tokens.Match(m_text, m_pos); | |
61 | |
62 if (m.Success) { | |
268 | 63 m_tokenPos = m_pos; |
267 | 64 m_pos += m.Length; |
65 if (m.Groups[1].Success) { | |
66 m_token = TokenType.Word; | |
67 m_tokenValue = m.Groups[1].Value; | |
68 } else if (m.Groups[2].Success) { | |
69 m_tokenValue = null; | |
70 switch (m.Groups[2].Value) { | |
71 case "{": | |
72 m_token = TokenType.OpenList; | |
73 break; | |
74 case "}": | |
75 m_token = TokenType.CloseList; | |
76 break; | |
77 case ".": | |
78 m_token = TokenType.Dot; | |
79 break; | |
80 case ",": | |
81 m_token = TokenType.Comma; | |
82 break; | |
277 | 83 case "[": |
84 m_token = TokenType.OpenArray; | |
85 break; | |
86 case "]": | |
87 m_token = TokenType.CloseArray; | |
88 break; | |
278
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
89 case "+": |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
90 m_token = TokenType.Plus; |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
91 break; |
267 | 92 } |
93 } | |
94 return true; | |
95 } | |
96 throw new FormatException($"Failed to parse '{m_text}' at pos {m_pos}"); | |
97 } | |
98 | |
268 | 99 public TypeReference Parse() { |
100 var result = ReadTypeReference(); | |
277 | 101 if (Token != TokenType.Eof) |
268 | 102 ThrowUnexpectedToken(); |
103 return result; | |
267 | 104 } |
105 | |
278
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
106 string[] ReadQTypeName() { |
267 | 107 var parts = new List<string>(); |
108 | |
109 string current = null; | |
110 bool stop = false; | |
111 while ((!stop) && ReadToken()) { | |
112 switch (Token) { | |
113 case TokenType.Word: | |
114 if (current != null) | |
115 ThrowUnexpectedToken(); | |
116 current = TokenValue; | |
117 break; | |
118 case TokenType.Dot: | |
119 if (current == null) | |
120 ThrowUnexpectedToken(); | |
121 parts.Add(current); | |
122 current = null; | |
123 break; | |
124 default: | |
125 stop = true; | |
126 break; | |
127 } | |
128 } | |
129 if (current != null) | |
130 parts.Add(current); | |
131 | |
132 if (parts.Count == 0) | |
133 return null; | |
134 | |
135 return parts.ToArray(); | |
136 } | |
137 | |
278
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
138 string ReadNQTypeName() { |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
139 ReadToken(); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
140 if (Token != TokenType.Word) |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
141 ThrowUnexpectedToken(); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
142 return TokenValue; |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
143 } |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
144 |
267 | 145 TypeReference ReadTypeReference() { |
146 | |
278
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
147 var parts = ReadQTypeName(); |
267 | 148 if (parts == null) |
149 return null; | |
150 | |
278
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
151 var genericParameters = ReadGenericParams(); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
152 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
153 var typeReference = TypeReference.Create( |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
154 string.Join(".", parts, 0, parts.Length - 1), |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
155 parts[parts.Length - 1], |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
156 genericParameters.Length |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
157 ); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
158 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
159 if (genericParameters.Length > 0 && genericParameters.All(x => x != null)) |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
160 typeReference = typeReference.MakeGenericType(genericParameters); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
161 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
162 typeReference = ReadArraySpec(typeReference); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
163 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
164 if(Token == TokenType.Plus) |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
165 return ReadNestedType(typeReference); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
166 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
167 return typeReference; |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
168 } |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
169 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
170 TypeReference ReadNestedType(TypeReference declaringType) { |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
171 var name = ReadNQTypeName(); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
172 if(string.IsNullOrEmpty(name)) |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
173 throw new FormatException("Nested type name can't be empty"); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
174 ReadToken(); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
175 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
176 var genericParameters = ReadGenericParams(); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
177 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
178 var typeReference = declaringType.Create( |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
179 name, |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
180 genericParameters.Length |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
181 ); |
267 | 182 |
278
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
183 if (genericParameters.Length > 0 && genericParameters.All(x => x != null)) |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
184 typeReference = typeReference.MakeGenericType(genericParameters); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
185 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
186 typeReference = ReadArraySpec(typeReference); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
187 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
188 if(Token == TokenType.Plus) |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
189 return ReadNestedType(typeReference); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
190 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
191 return typeReference; |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
192 } |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
193 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
194 TypeReference[] ReadGenericParams() { |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
195 if (Token == TokenType.OpenList) { |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
196 var genericParameters = ReadTypeReferenceList(); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
197 if (Token != TokenType.CloseList) |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
198 ThrowUnexpectedToken(); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
199 ReadToken(); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
200 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
201 return genericParameters; |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
202 } |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
203 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
204 return Array.Empty<TypeReference>(); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
205 } |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
206 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
207 TypeReference ReadArraySpec(TypeReference typeReference) { |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
208 while (Token == TokenType.OpenArray) { |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
209 var rank = CountRank(); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
210 if (Token != TokenType.CloseArray) |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
211 ThrowUnexpectedToken(); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
212 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
213 typeReference = typeReference.MakeArrayType(rank); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
214 |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
215 ReadToken(); |
267 | 216 } |
217 | |
218 return typeReference; | |
219 } | |
220 | |
278
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
221 int CountRank() { |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
222 int rank = 0; |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
223 do { |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
224 rank++; |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
225 } while(ReadToken() && Token == TokenType.Comma); |
6691aff01de1
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
cin
parents:
277
diff
changeset
|
226 return rank; |
277 | 227 } |
228 | |
267 | 229 TypeReference[] ReadTypeReferenceList() { |
268 | 230 var list = new List<TypeReference>(); |
267 | 231 |
268 | 232 do { |
233 var typeReference = ReadTypeReference(); | |
234 list.Add(typeReference); | |
235 } while (Token == TokenType.Comma); | |
236 | |
237 return list.ToArray(); | |
267 | 238 } |
239 | |
240 void ThrowUnexpectedToken() { | |
268 | 241 throw new FormatException($"Unexpected '{Token}' at pos {TokenPos}: -->{m_text.Substring(TokenPos, Math.Min(m_text.Length - TokenPos, 10))}"); |
267 | 242 } |
243 | |
244 } | |
245 } |