Skip to content

Method: handle(ClassModifierAbstract)

1: package de.fhdw.wtf.parser;
2:
3: import java.util.ArrayList;
4: import java.util.Collection;
5: import java.util.Iterator;
6:
7: import de.fhdw.wtf.common.ast.type.ClassModifier;
8: import de.fhdw.wtf.common.ast.type.ClassModifierAbstract;
9: import de.fhdw.wtf.common.ast.type.ClassModifierService;
10: import de.fhdw.wtf.common.ast.type.ClassModifierTransient;
11: import de.fhdw.wtf.common.ast.type.ClassModifierVisitable;
12: import de.fhdw.wtf.common.ast.type.ClassType;
13: import de.fhdw.wtf.common.ast.visitor.ClassModifierVisitor;
14: import de.fhdw.wtf.common.exception.parser.AbstractParserException;
15: import de.fhdw.wtf.common.exception.parser.ClassModifierAlreadyAddedException;
16: import de.fhdw.wtf.common.exception.parser.NoSemicolonException;
17: import de.fhdw.wtf.common.stream.TokenStream;
18: import de.fhdw.wtf.common.token.Token;
19:
20: /**
21: * Parses a given Tokenstream to {@link ClassModifier}s ( {@link ClassModifierAbstract}, {@link ClassModifierTransient},
22: * {@link ClassModifierService}).
23: */
24: public final class ClassModifierParser {
25:         /**
26:          * Tokenstream.
27:          */
28:         private final TokenStream stream;
29:         /**
30:          * Collection for exceptions.
31:          */
32:         private final Collection<AbstractParserException> exceptions;
33:         
34:         /**
35:          * Constrcutor of {@link ClassModifierParser}.
36:          *
37:          * @param stream
38:          * tokenstream
39:          * @param exceptions
40:          * collection for exceptions
41:          */
42:         private ClassModifierParser(final TokenStream stream, final Collection<AbstractParserException> exceptions) {
43:                 this.stream = stream;
44:                 this.exceptions = exceptions;
45:         }
46:         
47:         /**
48:          * Creates a {@link ClassModifierParser}-Object.
49:          *
50:          * @param stream
51:          * tokenstream
52:          * @param exceptions
53:          * collection for exceptions
54:          * @return the {@link ClassModifierParser}-Object.
55:          */
56:         static ClassModifierParser create(final TokenStream stream, final Collection<AbstractParserException> exceptions) {
57:                 return new ClassModifierParser(stream, exceptions);
58:         }
59:         
60:         /**
61:          * Parses the next series of Tokens of this.stream to ClassModifiers until a SemicolonToken occurs. If one of the
62:          * Tokens between the first element of this.stream and the next SemicolonToken is not a subtype of
63:          * ClassModifierToken, a {@link NoSemicolonException} will be thrown.
64:          *
65:          * @param currentClass
66:          * class
67:          * @throws AbstractParserException
68:          * {@link NoSemicolonException}
69:          * @return modifiers
70:          */
71:         Collection<ClassModifier> parse(final ClassType currentClass) throws AbstractParserException {
72:                 final Collection<ClassModifier> result = new ArrayList<>();
73:                 while (this.stream.hasNext()) {
74:                         if (this.stream.peek().isSemicolonToken()) {
75:                                 this.stream.next();
76:                                 currentClass.setLastToken(this.stream.peek());
77:                                 break;
78:                         } else {
79:                                 try {
80:                                         result.add(this.parseClassModifier(result));
81:                                 } catch (final ClassModifierAlreadyAddedException e3) {
82:                                         this.stream.removeFirst();
83:                                         this.exceptions.add(e3);
84:                                 }
85:                         }
86:                 }
87:                 return result;
88:         }
89:         
90:         /**
91:          * Checks if the next Token of this.stream is a ClassModifierToken and returns it, if it is. Otherwise a
92:          * NoClassModifierException will be returned.
93:          *
94:          * @param modifiers
95:          * list of modifiers
96:          * @throws ClassModifierAlreadyAddedException
97:          * ClassModifierAlreadyAddedException
98:          * @throws NoSemicolonException
99:          * NoSemicolonException
100:          * @return ClassModifier
101:          */
102:         private ClassModifier parseClassModifier(final Collection<ClassModifier> modifiers) throws NoSemicolonException,
103:                         ClassModifierAlreadyAddedException {
104:                 final Token nextToken = this.stream.peek();
105:                 if (nextToken.isClassModifierToken()) {
106:                         if (containsClassModifier(modifiers, nextToken)) {
107:                                 throw ClassModifierAlreadyAddedException.create(nextToken);
108:                         }
109:                         if (nextToken.isAbstractModifierToken()) {
110:                                 this.stream.removeFirst();
111:                                 return ClassModifierAbstract.create(nextToken, this.stream.peek());
112:                         }
113:                         if (nextToken.isServiceToken()) {
114:                                 this.stream.removeFirst();
115:                                 return ClassModifierService.create(nextToken, this.stream.peek());
116:                         }
117:                         if (nextToken.isTransientToken()) {
118:                                 this.stream.removeFirst();
119:                                 return ClassModifierTransient.create(nextToken, this.stream.peek());
120:                         }
121:                         if (nextToken.isVisitableToken()) {
122:                                 this.stream.removeFirst();
123:                                 return ClassModifierVisitable.create(nextToken, this.stream.peek());
124:                         }
125:                 }
126:                 throw NoSemicolonException.create(nextToken);
127:         }
128:         
129:         /**
130:          * Checks if <code>modifiers</code> contains a modifier of the type of <code>modifier</code>.
131:          *
132:          * @param modifiers
133:          * : Collection to be searched in
134:          *
135:          * @param modifier
136:          * : Modifiers of {@link ClassModifier} to search for
137:          * @return : <true> if <code>modifiers</code> contains <code>modifier</code> , <false> otherwise
138:          */
139:         private static boolean containsClassModifier(final Collection<ClassModifier> modifiers, final Token modifier) {
140:                 final Iterator<ClassModifier> i = modifiers.iterator();
141:                 while (i.hasNext()) {
142:                         final ClassModifier current = i.next();
143:                         if (current.accept(new ClassModifierVisitor() {
144:                                 @Override
145:                                 public boolean handle(final ClassModifierAbstract abstract1) {
146:                                         return modifier.isAbstractModifierToken();
147:                                 }
148:                                 
149:                                 @Override
150:                                 public boolean handle(final ClassModifierTransient tranzient) {
151:                                         return modifier.isTransientToken();
152:                                 }
153:                                 
154:                                 @Override
155:                                 public boolean handle(final ClassModifierService service) {
156:                                         return modifier.isServiceToken();
157:                                 }
158:                                 
159:                                 @Override
160:                                 public boolean handle(final ClassModifierVisitable visitable) {
161:                                         return modifier.isVisitableToken();
162:                                 }
163:                         })) {
164:                                 return true;
165:                         }
166:                 }
167:                 return false;
168:         }
169: }