Source code: org/sablecc/sablecc/GenAlts.java
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * This file is part of SableCC. *
3 * See the file "LICENSE" for copyright information and the *
4 * terms and conditions for copying, distribution and *
5 * modification of SableCC. *
6 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
7
8 package org.sablecc.sablecc;
9
10 import org.sablecc.sablecc.analysis.*;
11 import org.sablecc.sablecc.node.*;
12 import java.util.*;
13 import com.sun.java.util.collections.*;
14 import java.io.*;
15
16 public class GenAlts extends DepthFirstAdapter
17 {
18 private MacroExpander macros;
19 private ResolveIds ids;
20 private File pkgDir;
21 private String pkgName;
22 private List elemList;
23
24 private String currentProd;
25 ElemInfo info;
26 // final GenAlts instance = this;
27
28 public GenAlts(ResolveIds ids)
29 {
30 this.ids = ids;
31
32 try
33 {
34 macros = new MacroExpander(
35 new InputStreamReader(
36 getClass().getResourceAsStream("alternatives.txt")));
37 }
38 catch(IOException e)
39 {
40 throw new RuntimeException("unable to open alternatives.txt.");
41 }
42
43 pkgDir = new File(ids.pkgDir, "node");
44 pkgName = ids.pkgName.equals("") ? "node" : ids.pkgName + ".node";
45
46 if(!pkgDir.exists())
47 {
48 if(!pkgDir.mkdir())
49 {
50 throw new RuntimeException("Unable to create " + pkgDir.getAbsolutePath());
51 }
52 }
53 }
54
55 public void inProd1(Prod1 node)
56 {
57 currentProd = (String) ids.names.get(node);
58 }
59
60 public void inAlt1(Alt1 node)
61 {
62 inAlt(node);
63 }
64
65 public void inAlt2(Alt2 node)
66 {
67 inAlt(node);
68 }
69
70 public void inAlt(Alt node)
71 {
72 elemList = new TypedLinkedList(ElemInfoCast.instance);
73 }
74
75 public void inElem1(Elem1 tnode)
76 {
77 info = new ElemInfo();
78
79 info.name = (String) ids.names.get(tnode);
80 info.type = (String) ids.elemTypes.get(tnode);
81 info.operator = ElemInfo.NONE;
82
83 tnode.getNode4().apply(new DepthFirstAdapter()
84 {
85 public void caseUnOp1(UnOp1 node)
86 {
87 info.operator = ElemInfo.STAR;
88 }
89
90 public void caseUnOp2(UnOp2 node)
91 {
92 info.operator = ElemInfo.QMARK;
93 }
94
95 public void caseUnOp3(UnOp3 node)
96 {
97 info.operator = ElemInfo.PLUS;
98 }
99 });
100
101 elemList.add(info);
102 info = null;
103 }
104
105 public void outAlt1(Alt1 node)
106 {
107 outAlt(node);
108 }
109
110 public void outAlt2(Alt2 node)
111 {
112 outAlt(node);
113 }
114
115 public void outAlt(Alt node)
116 {
117 String name = (String) ids.names.get(node);
118
119 BufferedWriter file;
120
121 try
122 {
123 file = new BufferedWriter(
124 new FileWriter(
125 new File(pkgDir, name + ".java")));
126 }
127 catch(IOException e)
128 {
129 throw new RuntimeException("Unable to create " + new File(pkgDir, name + ".java").getAbsolutePath());
130 }
131
132 try
133 {
134 boolean hasOperator = false;
135
136 macros.apply(file, "AlternativeHeader", new String[] {pkgName,
137 ids.pkgName.equals("") ? "analysis" : ids.pkgName + ".analysis",
138 name, currentProd});
139
140 for(Iterator i = elemList.iterator(); i.hasNext();)
141 {
142 ElemInfo info = (ElemInfo) i.next();
143
144 switch(info.operator)
145 {
146 case ElemInfo.QMARK:
147 case ElemInfo.NONE:
148 {
149 macros.apply(file, "NodeElement",
150 new String[] {info.type,
151 nodeName(info.name)});
152 }
153 break;
154 case ElemInfo.STAR:
155 case ElemInfo.PLUS:
156 {
157 hasOperator = true;
158 macros.apply(file, "ListElement",
159 new String[] {info.name, nodeName(info.name)});
160 }
161 break;
162 }
163 }
164
165 macros.apply(file, "ConstructorHeader",
166 new String[] {name});
167 macros.apply(file, "ConstructorBodyHeader", null);
168 macros.apply(file, "ConstructorBodyTail", null);
169
170
171 if(elemList.size() > 0)
172 {
173 macros.apply(file, "ConstructorHeader",
174 new String[] {name});
175
176 for(Iterator i = elemList.iterator(); i.hasNext();)
177 {
178 ElemInfo info = (ElemInfo) i.next();
179
180 switch(info.operator)
181 {
182 case ElemInfo.QMARK:
183 case ElemInfo.NONE:
184 {
185 macros.apply(file, "ConstructorHeaderDeclNode",
186 new String[] {info.type, nodeName(info.name), i.hasNext() ? "," : ""});
187 }
188 break;
189 case ElemInfo.STAR:
190 case ElemInfo.PLUS:
191 {
192 macros.apply(file, "ConstructorHeaderDeclList",
193 new String[] {"List", nodeName(info.name), i.hasNext() ? "," : ""});
194 }
195 break;
196 }
197 }
198
199 macros.apply(file, "ConstructorBodyHeader", null);
200
201 for(Iterator i = elemList.iterator(); i.hasNext();)
202 {
203 ElemInfo info = (ElemInfo) i.next();
204
205 switch(info.operator)
206 {
207 case ElemInfo.QMARK:
208 case ElemInfo.NONE:
209 {
210 macros.apply(file, "ConstructorBodyNode",
211 new String[] {info.name, nodeName(info.name)});
212 }
213 break;
214 case ElemInfo.STAR:
215 case ElemInfo.PLUS:
216 {
217 macros.apply(file, "ConstructorBodyList",
218 new String[] {nodeName(info.name)});
219 }
220 break;
221 }
222 }
223
224 macros.apply(file, "ConstructorBodyTail", null);
225 }
226
227 if(hasOperator)
228 {
229 macros.apply(file, "ConstructorHeader",
230 new String[] {name});
231
232 for(Iterator i = elemList.iterator(); i.hasNext();)
233 {
234 ElemInfo info = (ElemInfo) i.next();
235
236 switch(info.operator)
237 {
238 case ElemInfo.NONE:
239 case ElemInfo.QMARK:
240 {
241 macros.apply(file, "ConstructorHeaderDeclNode",
242 new String[] {info.type, nodeName(info.name), i.hasNext() ? "," : ""});
243 }
244 break;
245 case ElemInfo.STAR:
246 case ElemInfo.PLUS:
247 {
248 macros.apply(file, "ConstructorHeaderDeclList",
249 new String[] {"X" + info.type,
250 nodeName(info.name), i.hasNext() ? "," : ""});
251 }
252 break;
253 }
254 }
255
256 macros.apply(file, "ConstructorBodyHeader", null);
257
258 for(Iterator i = elemList.iterator(); i.hasNext();)
259 {
260 ElemInfo info = (ElemInfo) i.next();
261
262 switch(info.operator)
263 {
264 case ElemInfo.NONE:
265 case ElemInfo.QMARK:
266 {
267 macros.apply(file, "ConstructorBodyNode",
268 new String[] {info.name, nodeName(info.name)});
269 }
270 break;
271 case ElemInfo.STAR:
272 case ElemInfo.PLUS:
273 {
274 macros.apply(file, "ConstructorBodyPlus",
275 new String[] {nodeName(info.name), info.type});
276 }
277 break;
278 }
279 }
280
281 macros.apply(file, "ConstructorBodyTail", null);
282 }
283
284 //****************
285 macros.apply(file, "CloneHeader",
286 new String[] {name});
287
288 for(Iterator i = elemList.iterator(); i.hasNext();)
289 {
290 ElemInfo info = (ElemInfo) i.next();
291
292 switch(info.operator)
293 {
294 case ElemInfo.QMARK:
295 case ElemInfo.NONE:
296 {
297 macros.apply(file, "CloneBodyNode",
298 new String[] {info.type, nodeName(info.name), i.hasNext() ? "," : ""});
299 }
300 break;
301 case ElemInfo.STAR:
302 case ElemInfo.PLUS:
303 {
304 macros.apply(file, "CloneBodyList",
305 new String[] {nodeName(info.name), i.hasNext() ? "," : ""});
306 }
307 break;
308 }
309 }
310
311 macros.apply(file, "CloneTail", null);
312 //****************
313
314 macros.apply(file, "Apply", new String[] {name});
315
316 for(Iterator i = elemList.iterator(); i.hasNext();)
317 {
318 ElemInfo info = (ElemInfo) i.next();
319
320 switch(info.operator)
321 {
322 case ElemInfo.QMARK:
323 case ElemInfo.NONE:
324 {
325 macros.apply(file, "GetSetNode",
326 new String[] {info.type, info.name, nodeName(info.name)});
327 }
328 break;
329 case ElemInfo.STAR:
330 case ElemInfo.PLUS:
331 {
332 macros.apply(file, "GetSetList",
333 new String[] {info.name, nodeName(info.name)});
334 }
335 break;
336 }
337 }
338
339 macros.apply(file, "ToStringHeader", null);
340 for(Iterator i = elemList.iterator(); i.hasNext();)
341 {
342 ElemInfo info = (ElemInfo) i.next();
343
344 switch(info.operator)
345 {
346 case ElemInfo.QMARK:
347 case ElemInfo.NONE:
348 {
349 macros.apply(file, "ToStringBodyNode",
350 new String[] {nodeName(info.name)});
351 }
352 break;
353 case ElemInfo.STAR:
354 case ElemInfo.PLUS:
355 {
356 macros.apply(file, "ToStringBodyList",
357 new String[] {nodeName(info.name)});
358 }
359 break;
360 }
361 }
362 macros.apply(file, "ToStringTail", null);
363
364 macros.apply(file, "RemoveChildHeader", null);
365 for(Iterator i = elemList.iterator(); i.hasNext();)
366 {
367 ElemInfo info = (ElemInfo) i.next();
368
369 switch(info.operator)
370 {
371 case ElemInfo.QMARK:
372 case ElemInfo.NONE:
373 {
374 macros.apply(file, "RemoveChildNode",
375 new String[] {nodeName(info.name)});
376 }
377 break;
378 case ElemInfo.STAR:
379 case ElemInfo.PLUS:
380 {
381 macros.apply(file, "RemoveChildList",
382 new String[] {nodeName(info.name)});
383 }
384 break;
385 }
386 }
387 macros.apply(file, "RemoveChildTail", null);
388 /* */
389 macros.apply(file, "ReplaceChildHeader", null);
390 for(Iterator i = elemList.iterator(); i.hasNext();)
391 {
392 ElemInfo info = (ElemInfo) i.next();
393
394 switch(info.operator)
395 {
396 case ElemInfo.QMARK:
397 case ElemInfo.NONE:
398 {
399 macros.apply(file, "ReplaceChildNode",
400 new String[] {nodeName(info.name), info.name, info.type});
401 }
402 break;
403 case ElemInfo.STAR:
404 case ElemInfo.PLUS:
405 {
406 macros.apply(file, "ReplaceChildList",
407 new String[] {nodeName(info.name)});
408 }
409 break;
410 }
411 }
412 macros.apply(file, "ReplaceChildTail", null);
413
414 /* */
415 for(Iterator i = elemList.iterator(); i.hasNext();)
416 {
417 ElemInfo info = (ElemInfo) i.next();
418
419 switch(info.operator)
420 {
421 case ElemInfo.STAR:
422 case ElemInfo.PLUS:
423 {
424 macros.apply(file, "Cast",
425 new String[] {info.name, info.type, name});
426 }
427 break;
428 }
429 }
430
431 macros.apply(file, "AlternativeTail", null);
432 }
433 catch(IOException e)
434 {
435 throw new RuntimeException("An error occured while writing to " +
436 new File(pkgDir, name + ".java").getAbsolutePath());
437 }
438
439 try
440 {
441 file.close();
442 }
443 catch(IOException e)
444 {
445 }
446
447 elemList = null;
448 }
449
450 public static String nodeName(String s)
451 {
452 StringBuffer result = new StringBuffer(s);
453
454 if(result.length() > 0)
455 {
456 result.setCharAt(0, Character.toLowerCase(result.charAt(0)));
457 }
458
459 return result.toString();
460 }
461
462 private static class ElemInfo
463 {
464 final static int NONE = 0;
465 final static int STAR = 1;
466 final static int QMARK = 2;
467 final static int PLUS = 3;
468
469 String name;
470 String type;
471 int operator;
472 }
473
474 private static class ElemInfoCast implements Cast
475 {
476 public final static ElemInfoCast instance = new ElemInfoCast();
477
478 private ElemInfoCast()
479 {
480 }
481
482 public Object cast(Object o)
483 {
484 return (ElemInfo) o;
485 }
486 }
487 }
488