Skip to content

Method: containsAttributeModifier(Collection, Token)

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: * Parser to parse the given TokenStream to {@link AttributeModifier}s.
24: */
25: public final class AttributeModifierParser {
26:         
27:         /**
28:          * Tokenstream.
29:          */
30:         private final TokenStream stream;
31:         
32:         /**
33:          * Collection for exceptions.
34:          */
35:         private final Collection<AbstractParserException> exceptions;
36:         
37:         /**
38:          * Constrcutor of {@link AttributeModifierParser}.
39:          *
40:          * @param stream
41:          * tokenstream
42:          * @param exceptions
43:          * collection for exceptions
44:          */
45:         private AttributeModifierParser(final TokenStream stream, final Collection<AbstractParserException> exceptions) {
46:                 this.stream = stream;
47:                 this.exceptions = exceptions;
48:         }
49:         
50:         /**
51:          * Creates a {@link AttributeModifierParser}-Object.
52:          *
53:          * @param stream
54:          * tokenstream
55:          * @param exceptions
56:          * collection for exceptions
57:          * @return the {@link AttributeModifierParser}-Object.
58:          */
59:         static AttributeModifierParser create(final TokenStream stream, final Collection<AbstractParserException> exceptions) {
60:                 return new AttributeModifierParser(stream, exceptions);
61:         }
62:         
63:         /**
64:          * Parses the next series of Tokens of this.stream to AttributeModifiers until a SemicolonToken occurs. If one of
65:          * the Tokens between the first element of this.stream and the next SemicolonToken is not a AttributeModifierToken,
66:          * a NoAttributeModifierException will be thrown.
67:          *
68:          * @return found attribute modifiers
69:          * @throws AbstractParserException
70:          * possible Exceptions
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:          * Checks if the next Token of this.stream is a AttributeModifierToken and returns it, if it is. Otherwise a
92:          * {@link NoSemicolonException} will be returned.
93:          *
94:          * @param modifiers
95:          * already found modfiers
96:          * @return attribute Modifier
97:          * @throws AbstractParserException
98:          * possible Exception
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:          * Returns true if <code>modifiers</code> contains a modifier of the type of <code>modifier</code>, otherwise false.
140:          *
141:          * @param modifiers
142:          * : Modifiers of {@link AttributeModifier}.
143:          * @param modifier
144:          * : modifier to search for.
145:          * @return Boolean
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: }