1 package de.fhdw.wtf.parser;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.List;
6 import java.util.Vector;
7
8 import de.fhdw.wtf.common.ast.Constructor;
9 import de.fhdw.wtf.common.ast.ConstructorByTypeAndSignatureState;
10 import de.fhdw.wtf.common.ast.ConstructorReference;
11 import de.fhdw.wtf.common.ast.Name;
12 import de.fhdw.wtf.common.ast.type.ByNameState;
13 import de.fhdw.wtf.common.ast.type.ClassType;
14 import de.fhdw.wtf.common.ast.type.ProductType;
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.stream.TokenStream;
19 import de.fhdw.wtf.common.token.Token;
20 import de.fhdw.wtf.common.token.symbols.BracketCloseToken;
21 import de.fhdw.wtf.common.token.symbols.SemicolonToken;
22
23
24
25
26 final class ConstructorParser {
27
28
29
30
31 private final TokenStream stream;
32
33
34
35
36 private final Collection<AbstractParserException> exceptions;
37
38
39
40
41
42
43
44
45
46 private ConstructorParser(final TokenStream stream, final Collection<AbstractParserException> exceptions) {
47 this.stream = stream;
48 this.exceptions = exceptions;
49 }
50
51
52
53
54
55
56
57
58
59
60 protected static ConstructorParser create(final TokenStream stream,
61 final Collection<AbstractParserException> exceptions) {
62 return new ConstructorParser(stream, exceptions);
63 }
64
65
66
67
68
69
70
71
72
73
74
75
76 protected Constructor parse(final Token firstToken, final ClassType owner) throws AbstractParserException {
77 final Collection<ConstructorReference> superConstructors = new Vector<>();
78 final Token firstTokenProduct = this.stream.peek();
79 final ProductType params = ProductType.create(firstTokenProduct);
80 this.parseParameters(params);
81 this.parseConstructorReferences(superConstructors);
82 this.stream.removeFirst();
83
84
85 final Constructor newConstructor = Constructor.create(params, owner, superConstructors, firstToken);
86 return newConstructor;
87 }
88
89
90
91
92
93
94
95
96
97 private void parseConstructorReferences(final Collection<ConstructorReference> superConstructors)
98 throws AbstractParserException {
99 if (!this.stream.peek().isSemicolonToken()) {
100 ParserUtils.requireAndRemoveEqualToken(this.stream);
101 while (this.stream.hasNext() && this.stream.peek().isIdentifierToken()) {
102 final Name typeForConstructorName = NameParser.createNameParser(this.stream).parse();
103 final ByNameState byName = ByNameState.create(typeForConstructorName);
104 final List<Type> parameters = new ArrayList<>();
105 this.parseParameters(parameters);
106
107 final ConstructorByTypeAndSignatureState byTypeAndSignatureState =
108 ConstructorByTypeAndSignatureState.create(
109 TypeProxy.create(typeForConstructorName.getFirstToken(), byName),
110 parameters);
111
112 superConstructors.add(ConstructorReference.create(byTypeAndSignatureState));
113 if (this.stream.peek().isPlusSymbolToken()) {
114 ParserUtils.requireAndRemovePlusSymbol(this.stream);
115 }
116 }
117 }
118 ParserUtils.requireSemicolonToken(this.stream);
119 }
120
121
122
123
124
125
126
127
128
129
130 private void parseParameters(final List<Type> parameters) throws AbstractParserException {
131 ParserUtils.requireAndRemoveBracketOpenToken(this.stream);
132 while (this.stream.hasNext() && this.stream.peek().isIdentifierToken()) {
133 parameters.add(TypeParser.create(this.stream, this.exceptions).parse());
134 if (this.stream.peek().isCommaToken()) {
135 this.stream.removeFirst();
136 }
137 }
138 ParserUtils.requireAndRemoveBracketCloseToken(this.stream);
139 }
140
141
142
143
144
145
146
147
148
149 private void parseParameters(final ProductType parameters) throws AbstractParserException {
150 ParserUtils.requireAndRemoveBracketOpenToken(this.stream);
151 while (this.stream.hasNext() && this.stream.peek().isIdentifierToken()) {
152 parameters.addElement(ParameterParser.create(this.stream, this.exceptions).parse());
153 if (this.stream.peek().isCommaToken()) {
154 this.stream.removeFirst();
155 }
156 }
157 ParserUtils.requireAndRemoveBracketCloseToken(this.stream);
158 parameters.setLastToken(this.stream.peek());
159 }
160 }