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