1 package org.andromda.translation.ocl.parser;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.Iterator;
6 import java.util.LinkedList;
7 import java.util.List;
8 import java.util.Map;
9 import org.andromda.translation.ocl.analysis.AnalysisAdapter;
10 import org.andromda.translation.ocl.analysis.DepthFirstAdapter;
11 import org.andromda.translation.ocl.lexer.Lexer;
12 import org.andromda.translation.ocl.node.AActualParameterList;
13 import org.andromda.translation.ocl.node.ABarFeatureCallParameterOption;
14 import org.andromda.translation.ocl.node.AColonFeatureCallParameterOption;
15 import org.andromda.translation.ocl.node.ACommaExpression;
16 import org.andromda.translation.ocl.node.ACommaFeatureCallParameterOption;
17 import org.andromda.translation.ocl.node.AConcreteFeatureCallParameters;
18 import org.andromda.translation.ocl.node.AEqualExpression;
19 import org.andromda.translation.ocl.node.AFeatureCallParameters;
20 import org.andromda.translation.ocl.node.AIterateDeclarator;
21 import org.andromda.translation.ocl.node.AIterateFeatureCallParameterOption;
22 import org.andromda.translation.ocl.node.APathName;
23 import org.andromda.translation.ocl.node.AStandardDeclarator;
24 import org.andromda.translation.ocl.node.ATypeDeclaration;
25 import org.andromda.translation.ocl.node.AVariableDeclaration;
26 import org.andromda.translation.ocl.node.AVariableDeclarationList;
27 import org.andromda.translation.ocl.node.AVariableDeclarationListTail;
28 import org.andromda.translation.ocl.node.Node;
29 import org.andromda.translation.ocl.node.PExpression;
30 import org.andromda.translation.ocl.node.PFeatureCallParameterOption;
31 import org.andromda.translation.ocl.node.TName;
32
33
34
35
36 public class OclParser
37 extends Parser
38 {
39
40
41
42 protected Node oclNode;
43
44
45
46
47
48
49 public OclParser(Lexer lexer)
50 {
51 super(lexer);
52 }
53
54
55
56
57 protected void filter()
58 {
59 oclNode = node;
60 oclNode.apply(handler);
61 node = oclNode;
62 }
63
64
65
66
67 protected SyntaxHandler handler = new SyntaxHandler();
68
69
70
71
72 private class SyntaxHandler
73 extends AnalysisAdapter
74 {
75
76
77
78
79
80 public void caseAConcreteFeatureCallParameters(AConcreteFeatureCallParameters featureCallParameters)
81 {
82 boolean isDeclarator = false;
83 boolean isIterateDeclarator = false;
84
85 List tail = featureCallParameters.getFeatureCallParameterOption();
86 PFeatureCallParameterOption[] parameterOption = new PFeatureCallParameterOption[tail.size()];
87 Iterator iter = tail.iterator();
88
89 for (int ctr = 0; iter.hasNext(); ctr++)
90 {
91 PFeatureCallParameterOption option = (PFeatureCallParameterOption) iter.next();
92 parameterOption[ctr] = option;
93 isIterateDeclarator = option instanceof AIterateFeatureCallParameterOption;
94 if (!isIterateDeclarator)
95 {
96 isDeclarator = option instanceof ABarFeatureCallParameterOption;
97 }
98 }
99
100 if (isIterateDeclarator && !isDeclarator)
101 {
102 throw new OclParserException("Parser Error: Illegal feature call parameters format in \"" +
103 featureCallParameters + "\"; " + "must contain \";\" only if it contains \"|\"");
104 }
105 AFeatureCallParameters parameters;
106 if (isIterateDeclarator)
107 {
108 parameters = getParametersWithIterateDeclarator(featureCallParameters,
109 featureCallParameters.getExpression(), parameterOption);
110 }
111 else if (isDeclarator)
112 {
113 parameters = getParametersWithStandardDeclarator(featureCallParameters, parameterOption);
114 }
115 else
116 {
117 parameters = getParametersWithoutDeclarator(featureCallParameters,
118 featureCallParameters.getExpression(), parameterOption);
119 }
120 oclNode = parameters;
121 }
122
123
124
125
126
127
128
129
130
131 protected AFeatureCallParameters getParametersWithIterateDeclarator(
132 AConcreteFeatureCallParameters featureCallParameters, PExpression expression,
133 PFeatureCallParameterOption[] parameterOption)
134 {
135 AIterateDeclarator iteratorDeclarator = new AIterateDeclarator();
136
137 AColonFeatureCallParameterOption featureCallParameterOption0 = (AColonFeatureCallParameterOption) parameterOption[0];
138 AIterateFeatureCallParameterOption featureCallParameterOption1 = (AIterateFeatureCallParameterOption) parameterOption[1];
139 ABarFeatureCallParameterOption featureCallParameterOption2 = (ABarFeatureCallParameterOption) parameterOption[2];
140
141 AVariableDeclaration iterator = new AVariableDeclaration(getName(expression),
142 featureCallParameterOption0.getTypeDeclaration());
143 iteratorDeclarator.setIterator(iterator);
144 iteratorDeclarator.setSemicolon(featureCallParameterOption1.getSemicolon());
145
146 AVariableDeclaration accumulator = new AVariableDeclaration(featureCallParameterOption1.getName(),
147 featureCallParameterOption1.getTypeDeclaration());
148 iteratorDeclarator.setAccumulator(accumulator);
149
150 AEqualExpression equalExpression = new AEqualExpression(featureCallParameterOption1.getEqual(),
151 featureCallParameterOption1.getExpression());
152 iteratorDeclarator.setEqualExpression(equalExpression);
153 iteratorDeclarator.setBar(featureCallParameterOption2.getBar());
154 AActualParameterList params = new AActualParameterList(featureCallParameterOption2.getExpression(),
155 new ArrayList());
156 return new AFeatureCallParameters(featureCallParameters.getLParen(), iteratorDeclarator, params,
157 featureCallParameters.getRParen());
158 }
159
160
161
162
163
164
165
166
167 protected AFeatureCallParameters getParametersWithStandardDeclarator(
168 AConcreteFeatureCallParameters featureCallParameters, PFeatureCallParameterOption[] parameterOptions)
169 {
170
171 int parameterOptionNum = parameterOptions.length;
172
173
174
175
176
177
178
179 for (int ctr = 0; ctr < parameterOptionNum - 2; ctr++)
180 {
181 if (!(parameterOptions[ctr] instanceof ACommaFeatureCallParameterOption ||
182 parameterOptions[ctr] instanceof AColonFeatureCallParameterOption))
183 {
184 throw new OclParserException("OCL Parser Error: Feature call parameters with " +
185 "a standard declarator must have the format " +
186 "\"( name (: type)?, ... , name (: type)? | expression )\"");
187 }
188 }
189
190 ABarFeatureCallParameterOption barParameterType = (ABarFeatureCallParameterOption) parameterOptions[parameterOptionNum -
191 1];
192
193 AStandardDeclarator standardDeclarator = new AStandardDeclarator(
194 this.getVariableDeclarationList(featureCallParameters), barParameterType.getBar());
195 AActualParameterList params = new AActualParameterList(barParameterType.getExpression(), new ArrayList());
196 return new AFeatureCallParameters(featureCallParameters.getLParen(), standardDeclarator, params,
197 featureCallParameters.getRParen());
198 }
199
200
201
202
203
204
205
206
207
208 protected AFeatureCallParameters getParametersWithoutDeclarator(
209 AConcreteFeatureCallParameters featureCallParameters, PExpression expr,
210 PFeatureCallParameterOption[] parameterOption)
211 {
212
213 List paramList = new ArrayList();
214
215 for (int ctr = 0; ctr < parameterOption.length; ctr++)
216 {
217 if (!(parameterOption[ctr] instanceof ACommaFeatureCallParameterOption))
218 {
219 throw new OclParserException("parser error: declarator-less feature call paramaters must have the format " +
220 "\"( expr, ..., expr )\"");
221 }
222 ACommaFeatureCallParameterOption commaOption = (ACommaFeatureCallParameterOption) parameterOption[ctr];
223 ACommaExpression commaExpression = new ACommaExpression(commaOption.getComma(),
224 commaOption.getExpression());
225 paramList.add(commaExpression);
226 }
227
228 return new AFeatureCallParameters(featureCallParameters.getLParen(), null,
229 new AActualParameterList(expr, paramList), featureCallParameters.getRParen());
230 }
231
232
233
234
235
236
237
238
239 protected AVariableDeclarationList getVariableDeclarationList(AConcreteFeatureCallParameters params)
240 {
241 VariableDeclarationListFinder finder = new VariableDeclarationListFinder();
242 params.apply(finder);
243 return finder.getList();
244 }
245 }
246
247
248
249
250 private class VariableDeclarationListFinder
251 extends DepthFirstAdapter
252 {
253
254
255
256
257 private List orderedNames = new LinkedList();
258
259
260
261
262 private Map namesAndTypes = new HashMap();
263
264
265
266
267
268 public void inAPathName(APathName name)
269 {
270
271
272
273 if (this.namesAndTypes.isEmpty())
274 {
275 TName initialVariableName = name.getName();
276 this.orderedNames.add(initialVariableName);
277 this.namesAndTypes.put(((LinkedList)this.orderedNames).getLast(), null);
278 }
279 }
280
281
282
283
284
285 public void inACommaFeatureCallParameterOption(ACommaFeatureCallParameterOption commaName)
286 {
287 this.orderedNames.add(commaName);
288 this.namesAndTypes.put(commaName, null);
289 }
290
291
292
293
294
295 public void inATypeDeclaration(ATypeDeclaration type)
296 {
297 if (this.namesAndTypes.containsKey(((LinkedList)this.orderedNames).getLast()))
298 {
299 this.namesAndTypes.put(((LinkedList)this.orderedNames).getLast(), type);
300 }
301 }
302
303
304
305
306
307
308 public AVariableDeclarationList getList()
309 {
310
311 TName initialName = (TName) ((LinkedList)this.orderedNames).getFirst();
312
313 ATypeDeclaration typeDeclaration = (ATypeDeclaration) namesAndTypes.get(initialName);
314
315 List variableDeclarationListTails = new ArrayList();
316 if (!this.orderedNames.isEmpty())
317 {
318 int orderedNameSize = orderedNames.size();
319 for (int ctr = 1; ctr < orderedNameSize; ctr++)
320 {
321 ACommaFeatureCallParameterOption name = (ACommaFeatureCallParameterOption) this.orderedNames.get(
322 ctr);
323
324 ATypeDeclaration typeDecl = (ATypeDeclaration) this.namesAndTypes.get(name);
325
326 AVariableDeclaration variableDeclaration = new AVariableDeclaration(getName(name.getExpression()),
327 typeDecl);
328
329 variableDeclarationListTails.add(new AVariableDeclarationListTail(name.getComma(),
330 variableDeclaration, null));
331 }
332 }
333
334 AVariableDeclarationList list = new AVariableDeclarationList(
335 new AVariableDeclaration(initialName, typeDeclaration), null, variableDeclarationListTails);
336 return list;
337 }
338 }
339
340
341
342
343 private class NameFinder
344 extends DepthFirstAdapter
345 {
346 private TName foundName;
347
348
349
350
351
352 public void caseAPathName(APathName pathName)
353 {
354 this.foundName = pathName.getName();
355 }
356
357
358
359
360 public TName getName()
361 {
362 return this.foundName;
363 }
364 }
365
366
367
368
369
370
371
372 protected TName getName(PExpression expression)
373 {
374 NameFinder finder = new NameFinder();
375 expression.apply(finder);
376 return finder.getName();
377 }
378 }