1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.themis.lethe.analysis;
18
19 import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
20 import io.github.tonywasher.joceanus.themis.exc.ThemisDataException;
21 import io.github.tonywasher.joceanus.themis.lethe.analysis.ThemisAnalysisDataMap.ThemisAnalysisDataType;
22
23 import java.util.ArrayList;
24 import java.util.Deque;
25 import java.util.List;
26 import java.util.ListIterator;
27
28
29
30
31 public interface ThemisAnalysisGeneric {
32
33
34
35
36
37
38 static boolean isGeneric(final ThemisAnalysisLine pLine) {
39
40 return pLine.startsWithChar(ThemisAnalysisChar.GENERIC_OPEN);
41 }
42
43
44
45
46 class ThemisAnalysisGenericBase
47 implements ThemisAnalysisGeneric {
48
49
50
51 private final ThemisAnalysisLine theContents;
52
53
54
55
56
57
58
59 ThemisAnalysisGenericBase(final ThemisAnalysisLine pLine) throws OceanusException {
60
61 final int myEnd = pLine.findEndOfNestedSequence(0, 0, ThemisAnalysisChar.GENERIC_CLOSE, ThemisAnalysisChar.GENERIC_OPEN);
62 if (myEnd < 0) {
63 throw new ThemisDataException("End character not found");
64 }
65
66
67 theContents = pLine.stripUpToPosition(myEnd);
68 theContents.stripStartChar(ThemisAnalysisChar.GENERIC_OPEN);
69 theContents.stripEndChar(ThemisAnalysisChar.GENERIC_CLOSE);
70 }
71
72
73
74
75
76
77
78
79 ThemisAnalysisGenericBase(final ThemisAnalysisParser pParser,
80 final ThemisAnalysisLine pLine) throws OceanusException {
81
82 final ThemisAnalysisScanner myScanner = new ThemisAnalysisScanner(pParser);
83
84
85 final Deque<ThemisAnalysisElement> myLines = myScanner.scanForGeneric(pLine);
86
87
88 theContents = new ThemisAnalysisLine(myLines);
89 theContents.stripStartChar(ThemisAnalysisChar.GENERIC_OPEN);
90 theContents.stripEndChar(ThemisAnalysisChar.GENERIC_CLOSE);
91 }
92
93
94
95
96
97
98 ThemisAnalysisLine getLine() {
99 return theContents;
100 }
101
102 @Override
103 public String toString() {
104 return "" + ThemisAnalysisChar.GENERIC_OPEN + theContents + ThemisAnalysisChar.GENERIC_CLOSE;
105 }
106 }
107
108
109
110
111 class ThemisAnalysisGenericRef
112 implements ThemisAnalysisGeneric {
113
114
115
116 private final ThemisAnalysisGenericBase theBase;
117
118
119
120
121 private final List<ThemisAnalysisReference> theReferences;
122
123
124
125
126
127
128
129
130 ThemisAnalysisGenericRef(final ThemisAnalysisParser pParser,
131 final ThemisAnalysisGenericBase pBase) throws OceanusException {
132
133 theBase = pBase;
134 theReferences = new ArrayList<>();
135 final ThemisAnalysisDataMap myDataMap = pParser.getDataMap();
136
137
138 final ThemisAnalysisLine myLine = new ThemisAnalysisLine(theBase.getLine());
139
140
141 while (true) {
142
143 if (myLine.startsWithChar(ThemisAnalysisChar.COMMA)) {
144 myLine.stripStartChar(ThemisAnalysisChar.COMMA);
145 }
146
147
148 final String myToken = myLine.peekNextToken();
149 if (myToken.isEmpty()) {
150 return;
151 }
152
153
154 if (myToken.length() == 1 && myToken.charAt(0) == ThemisAnalysisChar.QUESTION) {
155
156 myLine.stripNextToken();
157
158
159 final List<ThemisAnalysisReference> myRefs = new ArrayList<>();
160
161
162 final String myNext = myLine.peekNextToken();
163 if (myNext.equals(ThemisAnalysisKeyWord.EXTENDS.getKeyWord())
164 || myNext.equals(ThemisAnalysisKeyWord.SUPER.getKeyWord())) {
165
166 myLine.stripNextToken();
167 ThemisAnalysisReference myRef = ThemisAnalysisParser.parseDataType(myDataMap, myLine);
168 myRefs.add(myRef);
169
170
171 while (myLine.getLength() > 0 && myLine.startsWithChar(ThemisAnalysisChar.AND)) {
172 myLine.stripStartChar(ThemisAnalysisChar.AND);
173 myRef = ThemisAnalysisParser.parseDataType(myDataMap, myLine);
174 myRefs.add(myRef);
175 }
176 }
177
178 final ThemisAnalysisGenericVar myVar = new ThemisAnalysisGenericVar(myToken, myRefs);
179 theReferences.add(new ThemisAnalysisReference(myVar, null, null));
180
181
182 } else {
183 final ThemisAnalysisReference myReference = ThemisAnalysisParser.parseDataType(myDataMap, myLine);
184 myReference.resolveGeneric(pParser);
185 theReferences.add(myReference);
186 }
187 }
188 }
189
190
191
192
193
194
195 public List<ThemisAnalysisReference> getReferences() {
196 return theReferences;
197 }
198
199 @Override
200 public String toString() {
201 return theBase.toString();
202 }
203 }
204
205
206
207
208 class ThemisAnalysisGenericVarList
209 implements ThemisAnalysisGeneric {
210
211
212
213 private final ThemisAnalysisGenericBase theBase;
214
215
216
217
218 private final List<ThemisAnalysisGenericVar> theVariables;
219
220
221
222
223
224
225
226
227 ThemisAnalysisGenericVarList(final ThemisAnalysisParser pParser,
228 final ThemisAnalysisGenericBase pBase) throws OceanusException {
229
230 theBase = pBase;
231 theVariables = new ArrayList<>();
232 final ThemisAnalysisDataMap myDataMap = pParser.getDataMap();
233
234
235 final ThemisAnalysisLine myLine = new ThemisAnalysisLine(theBase.getLine());
236
237
238 while (true) {
239
240 if (myLine.startsWithChar(ThemisAnalysisChar.COMMA)) {
241 myLine.stripStartChar(ThemisAnalysisChar.COMMA);
242 }
243
244
245 final String myName = myLine.stripNextToken();
246 if (myName.length() == 0) {
247 addToDataList(pParser);
248 return;
249 }
250
251
252 final List<ThemisAnalysisReference> myRefs = new ArrayList<>();
253
254
255 final String myNext = myLine.peekNextToken();
256 if (myNext.equals(ThemisAnalysisKeyWord.EXTENDS.getKeyWord())) {
257
258 myLine.stripNextToken();
259 ThemisAnalysisReference myRef = ThemisAnalysisParser.parseDataType(myDataMap, myLine);
260 myRefs.add(myRef);
261
262
263 while (myLine.getLength() > 0 && myLine.startsWithChar(ThemisAnalysisChar.AND)) {
264 myLine.stripStartChar(ThemisAnalysisChar.AND);
265 myRef = ThemisAnalysisParser.parseDataType(myDataMap, myLine);
266 myRefs.add(myRef);
267 }
268 }
269
270
271 final ThemisAnalysisGenericVar myVar = new ThemisAnalysisGenericVar(myName, myRefs);
272 theVariables.add(myVar);
273 }
274 }
275
276
277
278
279
280
281
282 private void addToDataList(final ThemisAnalysisParser pParser) throws OceanusException {
283
284 final ThemisAnalysisDataMap myMap = pParser.getDataMap();
285
286
287 final ListIterator<ThemisAnalysisGenericVar> myIterator = theVariables.listIterator(theVariables.size());
288 while (myIterator.hasPrevious()) {
289 final ThemisAnalysisGenericVar myVar = myIterator.previous();
290
291
292 myMap.declareGenericVar(myVar);
293 myVar.resolveGeneric(pParser);
294 }
295 }
296
297 @Override
298 public String toString() {
299 return theBase.toString();
300 }
301 }
302
303
304
305
306 class ThemisAnalysisGenericVar
307 implements ThemisAnalysisGeneric, ThemisAnalysisDataType {
308
309
310
311 private final String theName;
312
313
314
315
316 private final List<ThemisAnalysisReference> theReferences;
317
318
319
320
321
322
323
324 ThemisAnalysisGenericVar(final String pName,
325 final List<ThemisAnalysisReference> pReferences) {
326
327 theName = pName;
328 theReferences = pReferences;
329 }
330
331
332
333
334
335
336 String getName() {
337 return theName;
338 }
339
340
341
342
343
344
345
346 public void resolveGeneric(final ThemisAnalysisParser pParser) throws OceanusException {
347
348 for (ThemisAnalysisReference myRef : theReferences) {
349 myRef.resolveGeneric(pParser);
350 }
351 }
352
353 @Override
354 public String toString() {
355 return theName;
356 }
357 }
358 }