267
|
1 using System;
|
|
2 using System.Collections.Generic;
|
|
3 using System.Text.RegularExpressions;
|
|
4
|
|
5 namespace Implab.ServiceHost.Unity {
|
268
|
6 internal class TypeReferenceParser {
|
267
|
7 enum TokenType {
|
|
8 None,
|
|
9
|
|
10 Word,
|
|
11
|
|
12 Dot,
|
|
13
|
|
14 Comma,
|
|
15
|
|
16 OpenList,
|
|
17
|
|
18 CloseList,
|
|
19
|
277
|
20 OpenArray,
|
|
21
|
|
22 CloseArray,
|
|
23
|
267
|
24 Eof
|
|
25 }
|
|
26
|
277
|
27 readonly Regex _tokens = new Regex(@"([\w\+]+)|\s*([\.{},\[\]])\s*");
|
267
|
28
|
|
29 TokenType m_token;
|
|
30
|
|
31 string m_tokenValue;
|
|
32
|
|
33 int m_pos;
|
|
34
|
268
|
35 int m_tokenPos;
|
|
36
|
267
|
37 readonly string m_text;
|
|
38
|
|
39 TokenType Token { get { return m_token; } }
|
|
40
|
|
41 string TokenValue { get { return m_tokenValue; } }
|
|
42
|
268
|
43 int TokenPos { get { return m_tokenPos; } }
|
|
44
|
267
|
45 public TypeReferenceParser(string text) {
|
|
46 Safe.ArgumentNotEmpty(text, nameof(text));
|
|
47 m_text = text;
|
|
48 }
|
|
49
|
|
50 bool ReadToken() {
|
|
51 if (m_pos >= m_text.Length) {
|
|
52 m_token = TokenType.Eof;
|
|
53 m_tokenValue = null;
|
|
54 return false;
|
|
55 }
|
|
56
|
|
57 var m = _tokens.Match(m_text, m_pos);
|
|
58
|
|
59 if (m.Success) {
|
268
|
60 m_tokenPos = m_pos;
|
267
|
61 m_pos += m.Length;
|
|
62 if (m.Groups[1].Success) {
|
|
63 m_token = TokenType.Word;
|
|
64 m_tokenValue = m.Groups[1].Value;
|
|
65 } else if (m.Groups[2].Success) {
|
|
66 m_tokenValue = null;
|
|
67 switch (m.Groups[2].Value) {
|
|
68 case "{":
|
|
69 m_token = TokenType.OpenList;
|
|
70 break;
|
|
71 case "}":
|
|
72 m_token = TokenType.CloseList;
|
|
73 break;
|
|
74 case ".":
|
|
75 m_token = TokenType.Dot;
|
|
76 break;
|
|
77 case ",":
|
|
78 m_token = TokenType.Comma;
|
|
79 break;
|
277
|
80 case "[":
|
|
81 m_token = TokenType.OpenArray;
|
|
82 break;
|
|
83 case "]":
|
|
84 m_token = TokenType.CloseArray;
|
|
85 break;
|
267
|
86 }
|
|
87 }
|
|
88 return true;
|
|
89 }
|
|
90 throw new FormatException($"Failed to parse '{m_text}' at pos {m_pos}");
|
|
91 }
|
|
92
|
268
|
93 public TypeReference Parse() {
|
|
94 var result = ReadTypeReference();
|
277
|
95 if (Token != TokenType.Eof)
|
268
|
96 ThrowUnexpectedToken();
|
|
97 return result;
|
267
|
98 }
|
|
99
|
|
100 string[] ReadTypeName() {
|
|
101 var parts = new List<string>();
|
|
102
|
|
103 string current = null;
|
|
104 bool stop = false;
|
|
105 while ((!stop) && ReadToken()) {
|
|
106 switch (Token) {
|
|
107 case TokenType.Word:
|
|
108 if (current != null)
|
|
109 ThrowUnexpectedToken();
|
|
110 current = TokenValue;
|
|
111 break;
|
|
112 case TokenType.Dot:
|
|
113 if (current == null)
|
|
114 ThrowUnexpectedToken();
|
|
115 parts.Add(current);
|
|
116 current = null;
|
|
117 break;
|
|
118 default:
|
|
119 stop = true;
|
|
120 break;
|
|
121 }
|
|
122 }
|
|
123 if (current != null)
|
|
124 parts.Add(current);
|
|
125
|
|
126 if (parts.Count == 0)
|
|
127 return null;
|
|
128
|
|
129 return parts.ToArray();
|
|
130 }
|
|
131
|
|
132 TypeReference ReadTypeReference() {
|
|
133
|
|
134 var parts = ReadTypeName();
|
|
135 if (parts == null)
|
|
136 return null;
|
|
137
|
|
138 var typeReference = new TypeReference {
|
268
|
139 Namespace = string.Join(".", parts, 0, parts.Length - 1),
|
|
140 TypeName = parts[parts.Length - 1]
|
|
141 };
|
267
|
142
|
|
143 switch (Token) {
|
|
144 case TokenType.OpenList:
|
|
145 typeReference.GenericParameters = ReadTypeReferenceList();
|
268
|
146 if (Token != TokenType.CloseList)
|
267
|
147 ThrowUnexpectedToken();
|
268
|
148 ReadToken();
|
267
|
149 break;
|
|
150 }
|
|
151
|
|
152 return typeReference;
|
|
153 }
|
|
154
|
277
|
155 int CountDimentions() {
|
|
156 return 0;
|
|
157 }
|
|
158
|
267
|
159 TypeReference[] ReadTypeReferenceList() {
|
268
|
160 var list = new List<TypeReference>();
|
267
|
161
|
268
|
162 do {
|
|
163 var typeReference = ReadTypeReference();
|
|
164 list.Add(typeReference);
|
|
165 } while (Token == TokenType.Comma);
|
|
166
|
|
167 return list.ToArray();
|
267
|
168 }
|
|
169
|
|
170 void ThrowUnexpectedToken() {
|
268
|
171 throw new FormatException($"Unexpected '{Token}' at pos {TokenPos}: -->{m_text.Substring(TokenPos, Math.Min(m_text.Length - TokenPos, 10))}");
|
267
|
172 }
|
|
173
|
|
174 }
|
|
175 } |