1 package de.fhdw.wtf.parser;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Iterator;
6 import java.util.List;
7
8 import de.fhdw.wtf.common.ast.AttributeModifier;
9 import de.fhdw.wtf.common.ast.AttributeModifierFindable;
10 import de.fhdw.wtf.common.ast.AttributeModifierMutable;
11 import de.fhdw.wtf.common.ast.AttributeModifierPrior;
12 import de.fhdw.wtf.common.ast.AttributeModifierSymmetric;
13 import de.fhdw.wtf.common.ast.AttributeModifierTransient;
14 import de.fhdw.wtf.common.ast.visitor.AttributModifierVisitor;
15 import de.fhdw.wtf.common.exception.parser.AbstractParserException;
16 import de.fhdw.wtf.common.exception.parser.AttributeModifierAlreadyAddedException;
17 import de.fhdw.wtf.common.exception.parser.NoSemicolonException;
18 import de.fhdw.wtf.common.stream.TokenStream;
19 import de.fhdw.wtf.common.token.IdentifierToken;
20 import de.fhdw.wtf.common.token.Token;
21
22
23
24
25 public final class AttributeModifierParser {
26
27
28
29
30 private final TokenStream stream;
31
32
33
34
35 private final Collection<AbstractParserException> exceptions;
36
37
38
39
40
41
42
43
44
45 private AttributeModifierParser(final TokenStream stream, final Collection<AbstractParserException> exceptions) {
46 this.stream = stream;
47 this.exceptions = exceptions;
48 }
49
50
51
52
53
54
55
56
57
58
59 static AttributeModifierParser create(final TokenStream stream, final Collection<AbstractParserException> exceptions) {
60 return new AttributeModifierParser(stream, exceptions);
61 }
62
63
64
65
66
67
68
69
70
71
72 List<AttributeModifier> parse() throws AbstractParserException {
73 final List<AttributeModifier> modifiers = new ArrayList<>();
74 while (this.stream.hasNext()) {
75 if (this.stream.peek().isSemicolonToken()) {
76 break;
77 } else {
78 try {
79 final AttributeModifier modifier = this.parseAttributeModifier(modifiers);
80 modifiers.add(modifier);
81 } catch (final AttributeModifierAlreadyAddedException e) {
82 this.stream.removeFirst();
83 this.exceptions.add(e);
84 }
85 }
86 }
87 return modifiers;
88 }
89
90
91
92
93
94
95
96
97
98
99
100 private AttributeModifier parseAttributeModifier(final Collection<AttributeModifier> modifiers)
101 throws AbstractParserException {
102
103 final Token nextToken = this.stream.peek();
104 if (nextToken.isAttributeModifierToken()) {
105 if (containsAttributeModifier(modifiers, nextToken)) {
106 throw AttributeModifierAlreadyAddedException.create(nextToken);
107 }
108 if (nextToken.isPriorModifierToken()) {
109 this.stream.removeFirst();
110 return AttributeModifierPrior.create(nextToken, this.stream.peek());
111 }
112 if (nextToken.isTransientToken()) {
113 this.stream.removeFirst();
114 return AttributeModifierTransient.create(nextToken, this.stream.peek());
115 }
116 if (nextToken.isFindableToken()) {
117 this.stream.removeFirst();
118 return AttributeModifierFindable.create(nextToken, this.stream.peek());
119 }
120 if (nextToken.isMutableToken()) {
121 this.stream.removeFirst();
122 return AttributeModifierMutable.create(nextToken, this.stream.peek());
123 }
124 if (nextToken.isSymmetricToken()) {
125 this.stream.removeFirst();
126 ParserUtils.requireAndRemoveBracketOpenToken(this.stream);
127 final IdentifierToken symmetricIdentifier = ParserUtils.requireAndRemoveIdentifier(this.stream);
128 final Token lastToken = ParserUtils.requireAndRemoveBracketCloseToken(this.stream);
129 final AttributeModifierSymmetric symmetricModifier =
130 AttributeModifierSymmetric.create(nextToken, symmetricIdentifier, this.stream.peek());
131 symmetricModifier.setLastToken(lastToken);
132 return symmetricModifier;
133 }
134 }
135 throw NoSemicolonException.create(nextToken);
136 }
137
138
139
140
141
142
143
144
145
146
147 private static boolean containsAttributeModifier(final Collection<AttributeModifier> modifiers, final Token modifier) {
148 final Iterator<AttributeModifier> i = modifiers.iterator();
149 while (i.hasNext()) {
150 final AttributeModifier current = i.next();
151 if (current.accept(new AttributModifierVisitor() {
152
153 @Override
154 public boolean handle(final AttributeModifierPrior prior) {
155 return modifier.isPriorModifierToken();
156 }
157
158 @Override
159 public boolean handle(final AttributeModifierTransient tranzient) {
160 return modifier.isTransientToken();
161 }
162
163 @Override
164 public boolean handle(final AttributeModifierFindable findable) {
165 return modifier.isFindableToken();
166 }
167
168 @Override
169 public boolean handle(final AttributeModifierMutable mutable) {
170 return modifier.isMutableToken();
171 }
172
173 @Override
174 public boolean handle(final AttributeModifierSymmetric symmetric) {
175 return modifier.isSymmetricToken();
176 }
177 })) {
178 return true;
179 }
180 }
181 return false;
182 }
183 }