1 package de.fhdw.wtf.parser;
2
3 import java.util.Collection;
4 import java.util.List;
5 import java.util.Vector;
6
7 import de.fhdw.wtf.common.ast.Attribute;
8 import de.fhdw.wtf.common.ast.Constructor;
9 import de.fhdw.wtf.common.ast.Name;
10 import de.fhdw.wtf.common.ast.Operation;
11 import de.fhdw.wtf.common.ast.type.ByNameState;
12 import de.fhdw.wtf.common.ast.type.ClassModifier;
13 import de.fhdw.wtf.common.ast.type.ClassType;
14 import de.fhdw.wtf.common.ast.type.ExceptionClassType;
15 import de.fhdw.wtf.common.ast.type.Type;
16 import de.fhdw.wtf.common.ast.type.TypeProxy;
17 import de.fhdw.wtf.common.exception.parser.AbstractParserException;
18 import de.fhdw.wtf.common.exception.parser.NoCurlyBracketOpenException;
19 import de.fhdw.wtf.common.exception.parser.NoEqualException;
20 import de.fhdw.wtf.common.exception.parser.NoPlusSymbolException;
21 import de.fhdw.wtf.common.exception.parser.NoSemicolonException;
22 import de.fhdw.wtf.common.stream.TokenStream;
23 import de.fhdw.wtf.common.token.IdentifierToken;
24 import de.fhdw.wtf.common.token.Token;
25
26
27
28
29
30
31
32 public final class ExceptionClassParser {
33
34
35
36
37 private final TokenStream stream;
38
39
40
41
42 private final Collection<AbstractParserException> exceptions;
43
44
45
46
47
48
49
50
51
52 private ExceptionClassParser(final TokenStream stream, final Collection<AbstractParserException> exceptions) {
53 this.stream = stream;
54 this.exceptions = exceptions;
55 }
56
57
58
59
60
61
62
63
64
65
66 protected static ExceptionClassParser create(final TokenStream stream,
67 final Collection<AbstractParserException> exceptions) {
68 return new ExceptionClassParser(stream, exceptions);
69 }
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 protected ClassType parse(final Name name, final Token firstToken) throws AbstractParserException {
85 try {
86 ParserUtils.requireAndRemoveEqualToken(this.stream);
87 } catch (final NoEqualException e) {
88 throw e;
89 }
90
91 final Collection<Attribute> attributes = new Vector<>();
92 final Collection<ClassModifier> modifiers = new Vector<>();
93 final Collection<ClassType> subTypes = new Vector<>();
94 final Collection<Operation> operations = new Vector<>();
95 final List<Type> superTypes = new Vector<>();
96 final Collection<Constructor> constructors = new Vector<>();
97 final ClassType classResult =
98 ExceptionClassType.create(
99 name,
100 modifiers,
101 attributes,
102 superTypes,
103 operations,
104 constructors,
105 firstToken,
106 subTypes);
107 try {
108 classResult.getSuperTypes().addAll(this.parseSuperTypes());
109 ParserUtils.requireAndRemoveCurlyBracketOpenToken(this.stream);
110 } catch (final NoCurlyBracketOpenException e) {
111 this.exceptions.add(e);
112
113
114 }
115 while (this.stream.hasNext() && !this.checkClassEnd() && !(this.stream.peek().isEndToken())) {
116 final Token currentToken = this.stream.peek();
117 if (currentToken.isIdentifierToken()) {
118 try {
119 final IdentifierToken token = ParserUtils.requireAndRemoveIdentifier(this.stream);
120 this.parseClassElement(
121 classResult,
122 constructors,
123 attributes,
124 operations,
125 token.stringRepresentation(),
126 classResult,
127 token);
128 } catch (final NoSemicolonException e) {
129 throw e;
130 } catch (final AbstractParserException e) {
131 this.exceptions.add(e);
132 ParserUtils.skipToSemicolonToken(this.stream);
133 continue;
134 }
135 } else if (currentToken.isBracketOpenToken()) {
136 this.parseConstructor(currentToken, constructors, classResult);
137 } else {
138 ParserUtils.requireAndRemoveCurlyBracketCloseToken(this.stream);
139 }
140 }
141 modifiers.addAll(ClassModifierParser.create(this.stream, this.exceptions).parse(classResult));
142 classResult.setLastToken(this.stream.peek());
143 return classResult;
144 }
145
146
147
148
149
150
151
152
153
154
155
156
157
158 private void parseConstructor(final Token firstToken,
159 final Collection<Constructor> constructors,
160 final ClassType owner) throws AbstractParserException {
161 constructors.add(ConstructorParser.create(this.stream, this.exceptions).parse(firstToken, owner));
162 }
163
164
165
166
167
168
169
170
171
172
173
174
175
176 private Collection<TypeProxy> parseSuperTypes() throws AbstractParserException {
177 final Collection<TypeProxy> superTypes = new Vector<>();
178
179 tryPossibleExceptions(this.stream.copy());
180
181 while (this.stream.hasNext() && this.stream.peek().isIdentifierToken()) {
182 final NameParser nameParser = NameParser.createNameParser(this.stream);
183 final Name currentSuperTypeName = nameParser.parse();
184
185 ParserUtils.requireAndRemovePlusSymbol(this.stream);
186 final ByNameState byName = ByNameState.create(currentSuperTypeName);
187 final TypeProxy typeProxy = TypeProxy.create(currentSuperTypeName.getFirstToken(), byName);
188 typeProxy.setLastToken(currentSuperTypeName.getLastToken());
189 superTypes.add(typeProxy);
190 }
191 return superTypes;
192 }
193
194
195
196
197
198
199
200
201
202
203 private static void tryPossibleExceptions(final TokenStream copy) throws AbstractParserException {
204 final Token firstPosition = copy.peek();
205
206 try {
207 while (copy.hasNext() && copy.peek().isIdentifierToken()) {
208 final NameParser nameParser = NameParser.createNameParser(copy);
209 nameParser.parse();
210 ParserUtils.requireAndRemovePlusSymbol(copy);
211 }
212 } catch (final NoPlusSymbolException e) {
213 if (copy.hasNext() && (copy.peek().isIdentifierToken() || copy.peek().isCurlyBracketOpenToken())) {
214 throw e;
215 } else {
216 throw NoCurlyBracketOpenException.create(firstPosition);
217 }
218 }
219 }
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242 private void parseClassElement(final ClassType classResult,
243 final Collection<Constructor> constructors,
244 final Collection<Attribute> attributes,
245 final Collection<Operation> operations,
246 final String name,
247 final ClassType containingType,
248 final IdentifierToken firstToken) throws AbstractParserException {
249 ParserUtils.requireAndRemoveColonToken(this.stream);
250 final Token nextToken = this.stream.peek();
251 if (nextToken.isDoubleSquareBracketOpenToken()) {
252 this.stream.removeFirst();
253 operations
254 .add(OperationParser.create(this.stream, this.exceptions).parse(name, containingType, firstToken));
255 } else {
256 attributes.add(AttributeParser.create(this.stream, this.exceptions).parse(name, firstToken));
257 }
258
259 }
260
261
262
263
264
265
266 private boolean checkClassEnd() {
267 if (!(this.stream.peek().isCurlyBracketCloseToken())) {
268 return false;
269 }
270 this.stream.removeFirst();
271 return true;
272 }
273 }