Source code: org/sablecc/sablecc/GenLexer.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 java.util.*;
11 import com.sun.java.util.collections.*;
12 import org.sablecc.sablecc.analysis.*;
13 import org.sablecc.sablecc.node.*;
14 import java.io.*;
15 import java.util.List;
16 import java.util.ArrayList;
17 import java.util.Iterator;
18
19 public class GenLexer extends AnalysisAdapter
20 {
21 private MacroExpander macros;
22 private ResolveIds ids;
23 private File pkgDir;
24 private String pkgName;
25 private AcceptStates[] acceptStatesArray;
26 private Transitions transitions;
27
28 public GenLexer(ResolveIds ids)
29 {
30 this.ids = ids;
31
32 try
33 {
34 macros = new MacroExpander(
35 new InputStreamReader(
36 getClass().getResourceAsStream("lexer.txt")));
37 }
38 catch(IOException e)
39 {
40 throw new RuntimeException("unable to open lexer.txt.");
41 }
42
43 pkgDir = new File(ids.pkgDir, "lexer");
44 pkgName = ids.pkgName.equals("") ? "lexer" : ids.pkgName + ".lexer";
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 caseStart1(Start1 tree)
56 {
57 String[] names;
58 int numStates = Math.max(1, ids.stateList.size());
59
60 acceptStatesArray = new AcceptStates[numStates];
61 names = new String[numStates];
62
63 if(ids.stateList.size() == 0)
64 {
65 names[0] = "INITIAL";
66 }
67 else
68 {
69 Iterator iter = ids.stateList.iterator();
70 for(int i = 0; i < numStates; i++)
71 {
72 names[i] = (String) iter.next();
73 }
74 }
75
76 for(int i = 0; i < numStates; i++)
77 {
78 System.out.println(" State: " + names[i]);
79
80 System.out.println(" - Constructing NFA.");
81 ConstructNFA nfaConstructor = new ConstructNFA(ids, names[i]);
82 tree.apply(nfaConstructor);
83 System.out.println();
84
85 NFA nfa = (NFA) nfaConstructor.getOut(tree);
86 nfaConstructor = null;
87
88 System.out.println(" - Constructing DFA.");
89 DFA dfa = new DFA(nfa);
90 System.out.println();
91
92 System.out.println(" - resolving ACCEPT states.");
93 acceptStatesArray[i] = new AcceptStates(dfa, ids, names[i]);
94 tree.apply(acceptStatesArray[i]);
95 }
96
97 transitions = new Transitions();
98 tree.apply(transitions);
99
100 createLexerException();
101 createLexer();
102 }
103
104 private void createLexerException()
105 {
106 BufferedWriter file;
107
108 try
109 {
110 file = new BufferedWriter(
111 new FileWriter(
112 new File(pkgDir, "LexerException.java")));
113 }
114 catch(IOException e)
115 {
116 throw new RuntimeException("Unable to create " + new File(pkgDir, "LexerException.java").getAbsolutePath());
117 }
118
119 try
120 {
121 macros.apply(file, "LexerException", new String[] {pkgName});
122 }
123 catch(IOException e)
124 {
125 throw new RuntimeException("An error occured while writing to " +
126 new File(pkgDir, "LexerException.java").getAbsolutePath());
127 }
128
129 try
130 {
131 file.close();
132 }
133 catch(IOException e)
134 {
135 }
136 }
137
138 private void createLexer()
139 {
140 BufferedWriter file;
141
142 try
143 {
144 file = new BufferedWriter(
145 new FileWriter(
146 new File(pkgDir, "Lexer.java")));
147 }
148 catch(IOException e)
149 {
150 throw new RuntimeException("Unable to create " + new File(pkgDir, "Lexer.java").getAbsolutePath());
151 }
152
153 try
154 {
155 String startState = "INITIAL";
156 if(ids.stateList.size() > 0)
157 {
158 startState = (String) ids.stateList.getFirst();
159 }
160
161 macros.apply(file, "LexerHeader", new String[] {pkgName,
162 ids.pkgName.equals("") ? "node" : ids.pkgName + ".node",
163 startState});
164
165 for(ListIterator i = ids.tokenList.listIterator(); i.hasNext();)
166 {
167 String name = (String) i.next();
168 Node node = (Node) ids.tokens.get(name);
169 boolean fixed = ((Boolean) ids.fixedTokens.get(node)).booleanValue();
170
171 if(fixed)
172 {
173 macros.apply(file, "LexerFixedToken",
174 new String[] {"" + i.previousIndex(), name});
175 }
176 else
177 {
178 macros.apply(file, "LexerVariableToken",
179 new String[] {"" + i.previousIndex(), name});
180 }
181
182 Map map = (Map) transitions.tokenStates.get(node);
183 if(map.size() > 0)
184 {
185 macros.apply(file, "TokenSwitchHeader", null);
186
187 for(Iterator j = map.entrySet().iterator(); j.hasNext();)
188 {
189 Map.Entry entry = (Map.Entry) j.next();
190
191 macros.apply(file, "TokenCase",
192 new String[] {ids.stateList.indexOf((String) entry.getKey()) + "",
193 (String) entry.getValue()});
194 }
195
196 macros.apply(file, "TokenSwitchTail", null);
197 }
198
199 macros.apply(file, "LexerTokenTail", null);
200 }
201
202 macros.apply(file, "LexerBody1");
203
204 for(ListIterator i = ids.tokenList.listIterator(); i.hasNext();)
205 {
206 String name = (String) i.next();
207 Node node = (Node) ids.tokens.get(name);
208 boolean fixed = ((Boolean) ids.fixedTokens.get(node)).booleanValue();
209
210 if(fixed)
211 {
212 macros.apply(file, "LexerNewFixedToken",
213 new String[] {"" + i.previousIndex(), name});
214 }
215 else
216 {
217 macros.apply(file, "LexerNewVariableToken",
218 new String[] {"" + i.previousIndex(), name});
219 }
220 }
221
222 macros.apply(file, "LexerBody2");
223
224 DataOutputStream out = new DataOutputStream(
225 new BufferedOutputStream(
226 new FileOutputStream(
227 new File(pkgDir, "lexer.dat"))));
228
229 out.writeInt(acceptStatesArray.length);
230 for(int accSt = 0; accSt < acceptStatesArray.length; accSt++)
231 {
232 DFA dfa = acceptStatesArray[accSt].dfa;
233
234 file.write(" { // " + acceptStatesArray[accSt].stateName + System.getProperty("line.separator"));
235 List outerArray = new ArrayList();
236
237 for(int i = 0; i < dfa.states.size(); i++)
238 {
239 List innerArray = new ArrayList();
240
241 DFA.State state = (DFA.State) dfa.states.get(i);
242 file.write(" {");
243
244 for(int j = 0; j < state.transitions.size(); j++)
245 {
246 DFA.Transition transition =
247 (DFA.Transition) state.transitions.get(j);
248
249 file.write("{" + ((int) transition.interval().start) + ", " +
250 ((int) transition.interval().end) + ", " +
251 transition.destination + "}, ");
252
253 innerArray.add(new int[] {
254 ((int) transition.interval().start),
255 ((int) transition.interval().end),
256 transition.destination});
257 }
258
259 file.write("}," + System.getProperty("line.separator"));
260
261 outerArray.add(innerArray);
262 }
263 file.write(" }" + System.getProperty("line.separator"));
264
265 out.writeInt(outerArray.size());
266 for(Iterator e = outerArray.iterator(); e.hasNext();)
267 {
268 List innerArray = (List) e.next();
269 out.writeInt(innerArray.size());
270 for(Iterator n = innerArray.iterator(); n.hasNext();)
271 {
272 int[] array = (int[]) n.next();
273
274 for(int i = 0; i < 3; i++)
275 {
276 out.writeInt(array[i]);
277 }
278 }
279 }
280 }
281
282 macros.apply(file, "LexerAcceptHeader");
283
284 final int stateNumber = acceptStatesArray.length;
285
286 List outerArray = new ArrayList();
287
288 for(int i = 0; i < stateNumber; i++)
289 {
290 DFA dfa = acceptStatesArray[i].dfa;
291 List innerArray = new ArrayList();
292
293 file.write(" // " + acceptStatesArray[i].stateName + System.getProperty("line.separator"));
294 file.write(" {");
295
296 for(int j = 0; j < dfa.states.size(); j++)
297 {
298 DFA.State state = (DFA.State) dfa.states.get(j);
299
300 file.write(state.accept + ", ");
301 innerArray.add(new Integer(state.accept));
302 }
303
304 file.write("}," + System.getProperty("line.separator"));
305
306 outerArray.add(innerArray);
307 }
308
309 out.writeInt(outerArray.size());
310 for(Iterator e = outerArray.iterator(); e.hasNext();)
311 {
312 List innerArray = (List) e.next();
313 out.writeInt(innerArray.size());
314 for(Iterator n = innerArray.iterator(); n.hasNext();)
315 {
316 Integer i = (Integer) n.next();
317 out.writeInt(i.intValue());
318 }
319 }
320 out.close();
321
322 file.write(System.getProperty("line.separator"));
323
324 macros.apply(file, "LexerAcceptTail");
325
326 macros.apply(file, "LexerStateHeader");
327
328 if(ids.stateList.size() > 0)
329 {
330 for(ListIterator i = ids.stateList.listIterator(); i.hasNext();)
331 {
332 String s = (String) i.next();
333
334 macros.apply(file, "LexerStateBody",
335 new String[] {s, "" + i.previousIndex()});
336 }
337 }
338 else
339 {
340 macros.apply(file, "LexerStateBody",
341 new String[] {"INITIAL", "" + 0});
342 }
343
344 macros.apply(file, "LexerStateTail");
345
346 macros.apply(file, "LexerTail");
347 }
348 catch(IOException e)
349 {
350 throw new RuntimeException("An error occured while writing to " +
351 new File(pkgDir, "Lexer.java").getAbsolutePath());
352 }
353
354 try
355 {
356 file.close();
357 }
358 catch(IOException e)
359 {
360 }
361 }
362 }
363