Source code: org/sablecc/sablecc/GenAnalyses.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 GenAnalyses extends DepthFirstAdapter
17 {
18 private MacroExpander macros;
19 private ResolveIds ids;
20 private File pkgDir;
21 private String pkgName;
22 private List elemList;
23 private List altList = new TypedLinkedList(AltInfoCast.instance);
24 private List tokenList = new TypedLinkedList(StringCast.instance);
25 private String mainProduction;
26
27 ElemInfo info;
28 // final GenAnalyses instance = this;
29
30 public GenAnalyses(ResolveIds ids)
31 {
32 this.ids = ids;
33
34 try
35 {
36 macros = new MacroExpander(
37 new InputStreamReader(
38 getClass().getResourceAsStream("analyses.txt")));
39 }
40 catch(IOException e)
41 {
42 throw new RuntimeException("unable to open analyses.txt.");
43 }
44
45 pkgDir = new File(ids.pkgDir, "analysis");
46 pkgName = ids.pkgName.equals("") ? "analysis" : ids.pkgName + ".analysis";
47
48 if(!pkgDir.exists())
49 {
50 if(!pkgDir.mkdir())
51 {
52 throw new RuntimeException("Unable to create " + pkgDir.getAbsolutePath());
53 }
54 }
55 }
56
57 public void inProd1(Prod1 node)
58 {
59 if(mainProduction == null)
60 {
61 mainProduction = (String) ids.names.get(node);
62 }
63 }
64
65 public void inTokenDef1(TokenDef1 node)
66 {
67 tokenList.add(ids.names.get(node));
68 }
69
70 public void inAlt1(Alt1 node)
71 {
72 inAlt(node);
73 }
74
75 public void inAlt2(Alt2 node)
76 {
77 inAlt(node);
78 }
79
80 public void inAlt(Alt node)
81 {
82 elemList = new TypedLinkedList(ElemInfoCast.instance);
83 }
84
85 public void inElem1(Elem1 tnode)
86 {
87 info = new ElemInfo();
88
89 info.name = (String) ids.names.get(tnode);
90 info.type = (String) ids.elemTypes.get(tnode);
91 info.operator = ElemInfo.NONE;
92
93 tnode.getNode4().apply(new DepthFirstAdapter()
94 {
95 public void caseUnOp1(UnOp1 node)
96 {
97 info.operator = ElemInfo.STAR;
98 }
99
100 public void caseUnOp2(UnOp2 node)
101 {
102 info.operator = ElemInfo.QMARK;
103 }
104
105 public void caseUnOp3(UnOp3 node)
106 {
107 info.operator = ElemInfo.PLUS;
108 }
109 });
110
111 elemList.add(info);
112 info = null;
113 }
114
115 public void outAlt1(Alt1 node)
116 {
117 outAlt(node);
118 }
119
120 public void outAlt2(Alt2 node)
121 {
122 outAlt(node);
123 }
124
125 public void outAlt(Alt node)
126 {
127 AltInfo info = new AltInfo();
128
129 info.name = (String) ids.names.get(node);
130 info.elems.addAll(elemList);
131 elemList = null;
132
133 altList.add(info);
134 }
135
136 public void outStart1(Start1 node)
137 {
138 createAnalysis();
139 createAnalysisAdapter();
140
141 if(mainProduction != null)
142 {
143 createDepthFirstAdapter();
144 createReversedDepthFirstAdapter();
145 }
146 }
147
148 public void createAnalysis()
149 {
150 BufferedWriter file;
151
152 try
153 {
154 file = new BufferedWriter(
155 new FileWriter(
156 new File(pkgDir, "Analysis.java")));
157 }
158 catch(IOException e)
159 {
160 throw new RuntimeException("Unable to create " + new File(pkgDir, "Analysis.java").getAbsolutePath());
161 }
162
163 try
164 {
165 macros.apply(file, "AnalysisHeader", new String[] {pkgName,
166 ids.pkgName.equals("") ? "node" : ids.pkgName + ".node"});
167
168 if(mainProduction != null)
169 {
170 macros.apply(file, "AnalysisStart", null);
171
172 for(Iterator i = altList.iterator(); i.hasNext();)
173 {
174 AltInfo info = (AltInfo) i.next();
175
176 macros.apply(file, "AnalysisBody",
177 new String[] {info.name});
178 }
179
180 file.newLine();
181 }
182
183 for(Iterator i = tokenList.iterator(); i.hasNext();)
184 {
185 macros.apply(file, "AnalysisBody",
186 new String[] {(String) i.next()});
187 }
188
189 macros.apply(file, "AnalysisTail", null);
190 }
191 catch(IOException e)
192 {
193 throw new RuntimeException("An error occured while writing to " +
194 new File(pkgDir, "Analysis.java").getAbsolutePath());
195 }
196
197 try
198 {
199 file.close();
200 }
201 catch(IOException e)
202 {
203 }
204 }
205
206 public void createAnalysisAdapter()
207 {
208 BufferedWriter file;
209
210 try
211 {
212 file = new BufferedWriter(
213 new FileWriter(
214 new File(pkgDir, "AnalysisAdapter.java")));
215 }
216 catch(IOException e)
217 {
218 throw new RuntimeException("Unable to create " + new File(pkgDir, "AnalysisAdapter.java").getAbsolutePath());
219 }
220
221 try
222 {
223 macros.apply(file, "AnalysisAdapterHeader", new String[] {pkgName,
224 ids.pkgName.equals("") ? "node" : ids.pkgName + ".node"});
225
226 if(mainProduction != null)
227 {
228 macros.apply(file, "AnalysisAdapterStart", null);
229
230 for(Iterator i = altList.iterator(); i.hasNext();)
231 {
232 AltInfo info = (AltInfo) i.next();
233
234 macros.apply(file, "AnalysisAdapterBody",
235 new String[] {info.name});
236 }
237 }
238
239 for(Iterator i = tokenList.iterator(); i.hasNext();)
240 {
241 macros.apply(file, "AnalysisAdapterBody",
242 new String[] {(String) i.next()});
243 }
244
245 macros.apply(file, "AnalysisAdapterTail", null);
246 }
247 catch(IOException e)
248 {
249 throw new RuntimeException("An error occured while writing to " +
250 new File(pkgDir, "AnalysisAdapter.java").getAbsolutePath());
251 }
252
253 try
254 {
255 file.close();
256 }
257 catch(IOException e)
258 {
259 }
260 }
261
262 public void createDepthFirstAdapter()
263 {
264 BufferedWriter file;
265
266 try
267 {
268 file = new BufferedWriter(
269 new FileWriter(
270 new File(pkgDir, "DepthFirstAdapter.java")));
271 }
272 catch(IOException e)
273 {
274 throw new RuntimeException("Unable to create " + new File(pkgDir, "DepthFirstAdapter.java").getAbsolutePath());
275 }
276
277 try
278 {
279 macros.apply(file, "DepthFirstAdapterHeader", new String[] {pkgName,
280 ids.pkgName.equals("") ? "node" : ids.pkgName + ".node",
281 mainProduction});
282
283 for(Iterator i = altList.iterator(); i.hasNext();)
284 {
285 AltInfo info = (AltInfo) i.next();
286
287 macros.apply(file, "DepthFirstAdapterInOut",
288 new String[] {info.name});
289
290 macros.apply(file, "DepthFirstAdapterCaseHeader",
291 new String[] {info.name});
292
293 for(Iterator j = info.elems.iterator(); j.hasNext();)
294 {
295 ElemInfo eInfo = (ElemInfo) j.next();
296
297 switch(eInfo.operator)
298 {
299 case ElemInfo.QMARK:
300 case ElemInfo.NONE:
301 {
302 macros.apply(file, "DepthFirstAdapterCaseBodyNode",
303 new String[] {eInfo.name});
304 }
305 break;
306 case ElemInfo.STAR:
307 case ElemInfo.PLUS:
308 {
309 macros.apply(file, "DepthFirstAdapterCaseBodyList",
310 new String[] {eInfo.name, eInfo.type});
311 }
312 break;
313 }
314 }
315
316 macros.apply(file, "DepthFirstAdapterCaseTail",
317 new String[] {info.name});
318
319 }
320
321 macros.apply(file, "DepthFirstAdapterTail", null);
322 }
323 catch(IOException e)
324 {
325 throw new RuntimeException("An error occured while writing to " +
326 new File(pkgDir, "DepthFirstAdapter.java").getAbsolutePath());
327 }
328
329 try
330 {
331 file.close();
332 }
333 catch(IOException e)
334 {
335 }
336 }
337
338 public void createReversedDepthFirstAdapter()
339 {
340 BufferedWriter file;
341
342 try
343 {
344 file = new BufferedWriter(
345 new FileWriter(
346 new File(pkgDir, "ReversedDepthFirstAdapter.java")));
347 }
348 catch(IOException e)
349 {
350 throw new RuntimeException("Unable to create " + new File(pkgDir, "ReversedDepthFirstAdapter.java").getAbsolutePath());
351 }
352
353 try
354 {
355 macros.apply(file, "ReversedDepthFirstAdapterHeader", new String[] {pkgName,
356 ids.pkgName.equals("") ? "node" : ids.pkgName + ".node",
357 mainProduction});
358
359 for(Iterator i = altList.iterator(); i.hasNext();)
360 {
361 AltInfo info = (AltInfo) i.next();
362
363 macros.apply(file, "DepthFirstAdapterInOut",
364 new String[] {info.name});
365
366 macros.apply(file, "DepthFirstAdapterCaseHeader",
367 new String[] {info.name});
368
369 for(ListIterator j = info.elems.listIterator(info.elems.size()); j.hasPrevious();)
370 {
371 ElemInfo eInfo = (ElemInfo) j.previous();
372
373 switch(eInfo.operator)
374 {
375 case ElemInfo.QMARK:
376 case ElemInfo.NONE:
377 {
378 macros.apply(file, "DepthFirstAdapterCaseBodyNode",
379 new String[] {eInfo.name});
380 }
381 break;
382 case ElemInfo.STAR:
383 case ElemInfo.PLUS:
384 {
385 macros.apply(file, "ReversedDepthFirstAdapterCaseBodyList",
386 new String[] {eInfo.name, eInfo.type});
387 }
388 break;
389 }
390 }
391
392 macros.apply(file, "DepthFirstAdapterCaseTail",
393 new String[] {info.name});
394
395 }
396
397 macros.apply(file, "DepthFirstAdapterTail", null);
398 }
399 catch(IOException e)
400 {
401 throw new RuntimeException("An error occured while writing to " +
402 new File(pkgDir, "ReversedDepthFirstAdapter.java").getAbsolutePath());
403 }
404
405 try
406 {
407 file.close();
408 }
409 catch(IOException e)
410 {
411 }
412 }
413
414 private static class ElemInfo
415 {
416 final static int NONE = 0;
417 final static int STAR = 1;
418 final static int QMARK = 2;
419 final static int PLUS = 3;
420
421 String name;
422 String type;
423 int operator;
424 }
425
426 private static class ElemInfoCast implements Cast
427 {
428 final static ElemInfoCast instance = new ElemInfoCast();
429
430 private ElemInfoCast()
431 {
432 }
433
434 public Object cast(Object o)
435 {
436 return (ElemInfo) o;
437 }
438 }
439
440 private static class AltInfo
441 {
442 String name;
443 final List elems = new TypedLinkedList(ElemInfoCast.instance);
444 }
445
446 private static class AltInfoCast implements Cast
447 {
448 final static AltInfoCast instance = new AltInfoCast();
449
450 private AltInfoCast()
451 {
452 }
453
454 public Object cast(Object o)
455 {
456 return (AltInfo) o;
457 }
458 }
459 }
460
461