annotate Implab.ServiceHost/Unity/TypeReferenceParser.cs @ 268:0be8a6ae8307 v3

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