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 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 packageName; 16 private List imports; 17 private String actionCode; 18 private String parserCode; 19 private String initCode; 20 private String 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 parserClassName = "Parser"; 29 private String symbolClassName = "Token"; 30 31 private AbstractLR1Parser lr1Parser; 32 33 public CodeWriter(ParserSpec spec, int parserType, 34 String _parserClassName, String _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 ("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 pre(String 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(); 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 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 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 temp = "((parser.runtime.StackSymbol)"+pre("stack")+ 293 ".elementAt("+pre("stack")+".size()-"+off+"))"; 294 String 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 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}"); out.println("\t}"); 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 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 escape = new StringBuffer (); 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 |