1 package de.fhdw.wtf.parser;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.List;
6
7 import de.fhdw.wtf.common.ast.Group;
8 import de.fhdw.wtf.common.ast.GroupElement;
9 import de.fhdw.wtf.common.ast.Name;
10 import de.fhdw.wtf.common.exception.parser.AbstractParserException;
11 import de.fhdw.wtf.common.exception.parser.NoSemicolonException;
12 import de.fhdw.wtf.common.stream.TokenStream;
13 import de.fhdw.wtf.common.token.IdentifierToken;
14 import de.fhdw.wtf.common.token.Token;
15
16
17
18
19 final class GroupParser {
20
21
22
23 private final TokenStream stream;
24
25
26
27
28 private final Collection<AbstractParserException> exceptions;
29
30
31
32
33
34
35
36
37
38 private GroupParser(final TokenStream stream, final Collection<AbstractParserException> exceptions) {
39 this.stream = stream;
40 this.exceptions = exceptions;
41 }
42
43
44
45
46
47
48
49
50
51
52 static GroupParser create(final TokenStream stream, final Collection<AbstractParserException> exceptions) {
53 return new GroupParser(stream, exceptions);
54 }
55
56
57
58
59
60
61
62
63
64
65
66
67
68 Group parse(final Name groupName, final Token firstToken) {
69 final List<GroupElement> groups = new ArrayList<>();
70 final Group group = Group.create(groupName, groups, firstToken);
71 try {
72 ParserUtils.requireAndRemoveEqualToken(this.stream);
73 ParserUtils.requireAndRemoveSquareBracketOpenToken(this.stream);
74 } catch (final AbstractParserException e) {
75 if (this.stream.hasNext() && this.stream.peek().isSquareBracketOpenToken()) {
76 this.stream.next();
77 }
78 this.exceptions.add(e);
79 }
80 while (this.stream.hasNext() && !(this.stream.peek().isEndToken()) && !this.checkGroupEnd()) {
81 try {
82 final IdentifierToken idtoken = ParserUtils.requireAndRemoveIdentifier(this.stream);
83 final Token nextToken = this.stream.peek();
84 ParserUtils.requireAndRemoveColonToken(this.stream);
85 ParserUtils.requireGroupElement(this.stream);
86 final Name newName = groupName.addName(idtoken, nextToken);
87 newName.setFirstToken(idtoken);
88
89
90 groups.add(this.parseGroupElement(newName));
91 } catch (final AbstractParserException e) {
92 this.exceptions.add(e);
93 ParserUtils.skipToSemicolonToken(this.stream);
94
95
96 if (this.stream.peek().isEndToken()) {
97 return group;
98 } else {
99 continue;
100 }
101 }
102 }
103 try {
104 ParserUtils.requireSemicolonToken(this.stream);
105 this.stream.next();
106 group.setLastToken(this.stream.peek());
107 } catch (final NoSemicolonException e) {
108 this.exceptions.add(e);
109 }
110 return group;
111 }
112
113
114
115
116
117
118
119
120
121
122
123 private GroupElement parseGroupElement(final Name name) throws AbstractParserException {
124 final Token nextToken = this.stream.next();
125 if (nextToken.isClassToken()) {
126 return RegularClassParser.create(this.stream, this.exceptions).parse(name, name.getFirstToken());
127 } else if (nextToken.isExceptionToken()) {
128 return ExceptionClassParser.create(this.stream, this.exceptions).parse(name, name.getFirstToken());
129 } else {
130 return this.parse(name, name.getFirstToken());
131 }
132 }
133
134
135
136
137
138
139 private boolean checkGroupEnd() {
140 if (!this.stream.peek().isSquareBracketCloseToken()) {
141 return false;
142 }
143 this.stream.removeFirst();
144 return true;
145 }
146 }