KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > ro > infoiasi > donald > compiler > parser > CodeWriter


1 package ro.infoiasi.donald.compiler.parser;
2
3 import ro.infoiasi.donald.compiler.cfg.*;
4
5 import java.io.*;
6 import java.util.*;
7
8 public class CodeWriter {
9     public String JavaDoc prefix = "SJCC$";
10
11     public static final int LALR1_PARSER = 0;
12     public static final int LR1_PARSER = 1;
13     public static final int SLR1_PARSER = 2;
14
15     private String JavaDoc packageName;
16     private List imports;
17     private String JavaDoc actionCode;
18     private String JavaDoc parserCode;
19     private String JavaDoc initCode;
20     private String JavaDoc scanCode;
21     private CFG g;
22     private NonTerminals v;
23     private Terminals t;
24     private NonTerminal s;
25     private Productions p;
26     private Production sp;
27
28     private String JavaDoc parserClassName = "Parser";
29     private String JavaDoc symbolClassName = "Token";
30
31     private AbstractLR1Parser lr1Parser;
32
33     public CodeWriter(ParserSpec spec, int parserType,
34             String JavaDoc _parserClassName, String JavaDoc _symbolClassName) {
35         packageName = spec.getPackageName();
36         imports = spec.getImports();
37         actionCode = spec.getActionCode();
38         parserCode = spec.getParserCode();
39         initCode = spec.getInitCode();
40         scanCode = spec.getScanCode();
41         g = spec.getGrammar();
42         v = g.getNonTerminals();
43         t = g.getTerminals();
44         s = g.getStartSymbol();
45         p = g.getProductions();
46
47         switch (parserType) {
48             case LALR1_PARSER:
49                 lr1Parser = new LALR1Parser(spec); break;
50             case LR1_PARSER:
51                 lr1Parser = new LR1Parser(spec); break;
52             case SLR1_PARSER:
53                 lr1Parser = new SLR1Parser(spec); break;
54             default:
55                 throw new RuntimeException JavaDoc("Unknown LR1 parser type");
56         }
57         lr1Parser.precompute();
58         sp = lr1Parser.getStartProduction();
59
60         if (_parserClassName != null) {
61             this.parserClassName = _parserClassName;
62         }
63
64         if (_symbolClassName != null) {
65             this.symbolClassName = _symbolClassName;
66         }
67
68     }
69
70     private String JavaDoc pre(String JavaDoc str) {
71         return prefix + parserClassName + "$" + str;
72     }
73
74     public void generateSymbolClass(PrintWriter out) {
75         generatePackage(out);
76         out.println("public interface "+symbolClassName+" {");
77         Iterator it = g.getTerminals().iterator();
78         while (it.hasNext()) {
79             Terminal a = (Terminal)it.next();
80             out.println("\tint "+a.getName()+" = "+g.getSID(a)+";");
81         }
82         out.println("}");
83     }
84
85     public void generateParser(PrintWriter out) {
86         generatePackage(out);
87         generateImports(out);
88         generateParserClass(out);
89         generateActionClass(out);
90     }
91
92     private void generatePackage(PrintWriter out) {
93         if (packageName != null) {
94             out.println("package "+packageName+";");
95             out.println();
96         }
97     }
98
99     private void generateImports(PrintWriter out) {
100         Iterator it = imports.iterator();
101         while (it.hasNext()) {
102             out.println("import "+it.next()+";");
103         }
104         if (!imports.isEmpty()) {
105             out.println();
106         }
107     }
108
109     private void generateParserClass(PrintWriter out) {
110         out.println();
111         out.println("public class "+parserClassName+
112             " extends SkeletonLRParser {");
113         out.println("\tpublic "+parserClassName+"() {");
114         out.println("\t\tsuper();");
115         out.println("\t}");
116         out.println();
117         out.println("\tpublic "+parserClassName+"(parser.runtime.Lexer lex) {");
118         out.println("\t\tsuper(lex);");
119         out.println("\t}");
120         out.println();
121         generateProductionTable(out);
122         out.println();
123         generateActionTable(out);
124         out.println();
125         generateGotoTable(out);
126         out.println();
127         out.println("\tprotected "+pre("Actions")+" actionObject;");
128         out.println();
129         out.println("\tprotected void initActions() {");
130         out.println("\t\tactionObject = new "+pre("Actions")+"(this);");
131         out.println("\t}");
132         out.println();
133         out.println("\tpublic final parser.runtime.StackSymbol doAction (");
134         out.println("\t\t\tint action, "+
135             "parser.runtime.SkeletonLRParser parser,");
136         out.println("\t\t\tjava.util.Stack stack"+
137             ") throws java.lang.Exception {");
138         out.println("\t\treturn actionObject."+pre("doAction")+
139             "(action, parser, stack);");
140         out.println("\t}");
141         out.println();
142         out.println("\tpublic int getStartState() {");
143         out.println("\t\treturn "+lr1Parser.getStartState()+";");
144         out.println("\t}");
145         out.println();
146         out.println("\tpublic int getStartProduction() {");
147         out.println("\t\treturn "+sp.getIndex()+";");
148         out.println("\t}");
149         out.println();
150         out.println("\tpublic int getEOF() {");
151         out.println("\t\treturn "+t.EOF.getIndex()+";");
152         out.println("\t}");
153         out.println("\tpublic int getTokenOffset() {");
154         out.println("\t\treturn "+v.count()+";");
155         out.println("\t}");
156         if (initCode != null) {
157             out.println();
158             out.println("\tpublic int initCode() throws Exception {");
159             out.println(initCode);
160             out.println("\t}");
161         }
162         if (scanCode != null) {
163             out.println();
164             out.println("\tpublic int scan() throws Exception {");
165             out.println(scanCode);
166             out.println("\t}");
167         }
168         if (parserCode != null) {
169             out.println();
170             out.println(parserCode);
171         }
172         out.println("}");
173     }
174
175
176     private void generateProductionTable(PrintWriter out) {
177         short[][] table = new short[p.count()][2];
178         Iterator it = p.iterator();
179         while (it.hasNext()) {
180             Production prod = (Production)it.next();
181             table[prod.getIndex()][0] = (short)prod.getLHS().getIndex();
182             table[prod.getIndex()][1] = (short)prod.getRHS().size();
183         }
184         out.println("\tpublic short[][] getProductionTable() {");
185         out.print("\t\treturn unpackFromStrings(");
186         generateTableAsString(out, table);
187         out.println(");\n\t}");
188     }
189
190     private void generateActionTable(PrintWriter out) {
191         int n = lr1Parser.getStateNo();
192         short[][] table = new short[n][t.count()];
193         for (int i = 0; i<n; i++) {
194             Iterator it = t.iterator();
195             while (it.hasNext()) {
196                 Terminal a = (Terminal)it.next();
197                 short action;
198                 AbstractLR1Parser.ParseAction pa = lr1Parser.getAction(i, a);
199                 if (pa != null) {
200                     if (pa.isShiftAction()) {
201                         AbstractLR1Parser.ShiftAction sa =
202                             (AbstractLR1Parser.ShiftAction)pa;
203                         action = (short)(sa.getStateIndex().intValue()+1);
204                     } else {
205                         AbstractLR1Parser.ReduceAction ra =
206                             (AbstractLR1Parser.ReduceAction)pa;
207                         action = (short)(-ra.getProduction().getIndex()-1);
208                     }
209                 } else {
210                     action = 0;
211                 }
212                 table[i][a.getIndex()] = action;
213             }
214         }
215         out.println("\tpublic short[][] getActionTable() {");
216         out.print("\t\treturn unpackFromStrings(");
217         generateTableAsString(out, table);
218         out.println(");\n\t}");
219     }
220
221     private void generateGotoTable(PrintWriter out) {
222         int n = lr1Parser.getStateNo();
223         short[][] table = new short[n][v.count()];
224         for (int i = 0; i<n; i++) {
225             Iterator it = v.iterator();
226             while (it.hasNext()) {
227                 NonTerminal x = (NonTerminal)it.next();
228                 table[i][x.getIndex()] = (short)lr1Parser.getGoto(i, x);
229             }
230         }
231         out.println("\tpublic short[][] getGotoTable() {");
232         out.print("\t\treturn unpackFromStrings(");
233         generateTableAsString(out, table);
234         out.println(");\n\t}");
235     }
236
237
238     private void generateActionClass(PrintWriter out) {
239         out.println();
240         out.println("class " + pre("Actions") + " {");
241         if (actionCode != null) {
242             out.println();
243             out.println(actionCode);
244         }
245         out.println("\tprivate final "+parserClassName+" parser;");
246         out.println();
247         out.println("\t"+pre("Actions")+"("+parserClassName+" parser) {");
248         out.println("\t\tthis.parser = parser;");
249         out.println("\t}");
250         out.println("");
251         out.println("\tpublic final parser.runtime.StackSymbol "+
252             pre("doAction")+"(\n\t\t\tint "+pre("action")+
253             ",\n\t\t\tparser.runtime.SkeletonLRParser "+pre("parser")+
254             ",\n\t\t\tjava.util.Stack "+pre("stack")+
255             ") throws java.lang.Exception {");
256         //out.println("\t\tparser.runtime.StackSymbol "+pre("result")+";");
257
out.println();
258         out.println("\t\tswitch ("+pre("action")+") {");
259         Iterator it = p.iterator();
260         while (it.hasNext()) {
261             Production prod = (Production)it.next();
262             out.println("\t\t\tcase "+prod.getIndex()+": // "+prod.toString());
263             out.println("\t\t\t{");
264             String JavaDoc resultType = prod.getLHS().getType();
265             if (resultType == null) {
266                 resultType = "java.lang.Object";
267             }
268             out.println("\t\t\t\t"+resultType+" RESULT = null;");
269             Word w = prod.getRHS();
270             int j = 0;
271             WordIterator wordIt = w.iterator();
272             while (wordIt.hasNext()) {
273                 Symbol sym = (Symbol)wordIt.next();
274                 if (!sym.isTerminal() && sym.getName().indexOf("$ACTION") == 0) {
275                     int off = w.size()-j-1;
276                     out.println("\t\t\t\t// propagate RESULT from "+
277                         sym.getName());
278                     String JavaDoc temp = "((parser.runtime.StackSymbol) "+pre("stack")+
279                         ".elementAt("+pre("stack")+".size()-"+off+")).value";
280                     out.println("\t\t\t\tif ("+temp+" != null) {");
281                     out.println("\t\t\t\t\tRESULT = "+temp+";");
282                     out.println("\t\t\t\t}");
283                 }
284                 j++;
285             }
286             SemanticAction sa = prod.getSemanticAction();
287             if (sa != null && sa.getCode() != null && sa.getCode().length()>0) {
288                 Iterator labelIt = sa.getLabels().iterator();
289                 while (labelIt.hasNext()) {
290                     Label label = (Label)labelIt.next();
291                     int off = sa.getOffset()-label.getPosition();
292                     String JavaDoc temp = "((parser.runtime.StackSymbol)"+pre("stack")+
293                         ".elementAt("+pre("stack")+".size()-"+off+"))";
294                     //out.println("\t\t\t\tint "+label.getName()+
295
// "left = "+temp+".left;");
296
//out.println("\t\t\t\tint "+label.getName()+
297
// "right = "+temp+".right;");
298
String JavaDoc type = label.getSymbol().getType();
299                     if (type == null) {
300                         type = "java.lang.Object";
301                     }
302                     out.println("\t\t\t\t"+type+" "+label.getName()+
303                         " = ("+type+")"+temp+".value;");
304                 }
305                 out.println(sa.getCode());
306             }
307             if (prod == sp) {
308                 out.println("\t\t\t\tparser.doneParsing();");
309             }
310             // ... left and right?
311
out.println("\t\t\t\treturn new parser.runtime.StackSymbol("+
312                 g.getSID(prod.getLHS())+" /*"+
313                 prod.getLHS().getName()+"*/, RESULT);");
314             out.println("\t\t\t}");
315         }
316         out.println("\t\t\tdefault:");
317         out.println("\t\t\t\tthrow new Exception(\"Invalid action number\");");
318         out.println("\t\t}"); // end switch
319
out.println("\t}"); // end doAction
320
out.println("}");
321     }
322
323
324     private void generateTableAsString(PrintWriter out, short[][] sa) {
325         out.println("new String[] {");
326         out.print("\t\t\"");
327         int nchar = 0, nbytes = 0;
328         nbytes += generateEscapedChar(out, (char)(sa.length>>16));
329         nchar = generateNewline(out, nchar, nbytes);
330         nbytes += generateEscapedChar(out, (char)(sa.length&0xFFFF));
331         nchar = generateNewline(out, nchar, nbytes);
332         for (int i = 0; i<sa.length; i++) {
333             nbytes += generateEscapedChar(out, (char)(sa[i].length>>16));
334             nchar = generateNewline(out, nchar, nbytes);
335             nbytes += generateEscapedChar(out, (char)(sa[i].length&0xFFFF));
336             nchar = generateNewline(out, nchar, nbytes);
337             for (int j = 0; j<sa[i].length; j++) {
338                 // contents of string are (value+2) to allow for common -1, 0 cases
339
// (UTF-8 encoding is most efficient for 0<c<0x80)
340
nbytes += generateEscapedChar(out, (char)(2+sa[i][j]));
341                 nchar = generateNewline(out, nchar, nbytes);
342             }
343         }
344         out.print("\" }");
345     }
346
347     private int generateNewline(PrintWriter out, int nchar, int nbytes) {
348         if (nbytes > 65500) {
349             out.println("\", "); out.print("\t\t\"");
350             return 0;
351         } else if (nchar > 11) {
352             out.println("\" +"); out.print("\t\t\"");
353             return 0;
354         } else {
355             return nchar+1;
356         }
357     }
358     
359     private int generateEscapedChar(PrintWriter out, char c) {
360         StringBuffer JavaDoc escape = new StringBuffer JavaDoc();
361         if (c <= 0xFF) {
362             escape.append(Integer.toOctalString(c));
363             while(escape.length() < 3) escape.insert(0, '0');
364         } else {
365             escape.append(Integer.toHexString(c));
366             while(escape.length() < 4) escape.insert(0, '0');
367             escape.insert(0, 'u');
368         }
369         escape.insert(0, '\\');
370         out.print(escape.toString());
371         
372         if (c == 0) {
373             return 2;
374         } else if (c >= 0x01 && c <= 0x7F) {
375             return 1;
376         } else if (c >= 0x80 && c <= 0x7FF) {
377             return 2;
378         } else {
379             return 3;
380         }
381     }
382 }
383
Popular Tags