Traductor e intérprete del lenguaje CL 1.23
|
00001 00186 import java.util.List; 00187 import org.antlr.runtime.*; 00188 import org.antlr.runtime.tree.*; 00189 import org.antlr.stringtemplate.*; 00190 import java.io.*; 00191 00268 public class CL { 00269 00273 private static final int DEFAULT_LAST_STEP = 8; 00274 00278 public static void main(String[] args) throws Exception, RecognitionException { 00279 ANTLRStringStream input = new ANTLRStringStream(); 00280 int last_step = DEFAULT_LAST_STEP; 00281 00282 // En primer lugar se determina de donde se lee el 00283 // programa de entrada y en que; paso se detiene el 00284 // traductor/interprete. 00285 if (args.length == 0) { // sin argumentos en args 00286 last_step = DEFAULT_LAST_STEP; 00287 input = new ANTLRInputStream(System.in); 00288 } else if (args.length == 1) { // un solo argumento en args 00289 if (args[0].startsWith("-")) { 00290 last_step = Integer.parseInt(args[0].substring(1, args[0].length())); 00291 input = new ANTLRInputStream(System.in); 00292 } else { 00293 last_step = DEFAULT_LAST_STEP; 00294 input = new ANTLRFileStream(args[0]); 00295 } 00296 } else if (args.length == 2) { // dos argumentos en args 00297 last_step = Integer.parseInt(args[0].substring(1, args[0].length())); 00298 input = new ANTLRFileStream(args[1]); 00299 } else { // numero incorrecto de argumentos en args 00300 System.out.println("Usage: java CL [-<step>] [<file>]"); 00301 System.out.println(" with <step> in 1..11\t(default = " + DEFAULT_LAST_STEP + ")"); 00302 System.exit(1); 00303 } 00304 00305 // Se declara el lexer y otras las variables necesarias 00306 // para crear correctamente el parser, y se le especifica 00307 // como son los arboles que construira. 00308 CLLexer lexer = new CLLexer(input); 00309 CommonTokenStream tokens = new CommonTokenStream(lexer); 00310 CLParser parser = new CLParser(tokens); 00311 00312 parser.setTreeAdaptor(new CL_AST_Adaptor()); 00313 00314 List<RecognitionException> recognitionExceptions; 00315 00316 // Se llama al parser y se obtiene el AST construido. 00317 CLParser.program_return ret = parser.program(); 00318 00319 CL_AST ast = (CL_AST) ret.getTree(); 00320 00321 // Se comprueban los errores lexicos. 00322 recognitionExceptions = lexer.getExceptions(); 00323 if (recognitionExceptions.size() > 0) { 00324 System.out.println("Lexer threw exceptions -- see output"); 00325 System.exit(1); 00326 } 00327 00328 // Se comprueban los errores sintacticos. 00329 recognitionExceptions = parser.getExceptions(); 00330 if (recognitionExceptions.size() > 0) { 00331 System.out.println("Parser threw exceptions -- see output"); 00332 System.exit(1); 00333 } 00334 00335 if (last_step == 1 || last_step == 2) { 00336 System.exit(0); 00337 } 00338 00339 // Se escribe el AST tanto en formato multilinea 00340 // con tabulacion como en formato DOT para que mas tarde 00341 // pueda verse como un grafico. 00342 // // System.out.println(ast.toStringTree()); 00343 if (last_step == 3) { 00344 System.out.print(CL_AST.toIndentedTreeString(ast)); 00345 DOTTreeGenerator gen = new DOTTreeGenerator(); 00346 StringTemplate st = gen.toDOT(ast); 00347 FileWriter outputStream = new FileWriter("ast.dot"); 00348 outputStream.write(st.toString()); 00349 outputStream.close(); 00350 System.exit(0); 00351 } 00352 00353 // Se declaran las variables necesarias para crear 00354 // correctamente el typeCheck especificandole 00355 // la tabla de simbolos que usara (inicialmente vacia). 00356 CommonTreeNodeStream nodes = new CommonTreeNodeStream(ast); 00357 SymTab symtab = new SymTab(); 00358 TypeCheck typeCheck = new TypeCheck(nodes, symtab); 00359 00360 // Se llama al analisis semantico typeCheck. 00361 typeCheck.program(); 00362 00363 // Se comprueban los errores de no reconocimiento del AST. 00364 recognitionExceptions = typeCheck.getExceptions(); 00365 if (recognitionExceptions.size() > 0) { 00366 System.out.println("Tree parser 'TypeCheck' threw exceptions -- see output"); 00367 System.exit(1); 00368 } 00369 00370 if (last_step == 4) { 00371 System.exit(0); 00372 } 00373 00374 // Se vuelve a escribir el AST en formato multilinea con 00375 // tabulacion. Ahora se visualizara tambien su decoracion. 00376 if (last_step == 5) { 00377 System.out.print(CL_AST.toIndentedTreeString(ast)); 00378 System.exit(0); 00379 } 00380 00381 // Se obtienen y, si existen, se escriben los errores semanticos. 00382 SemanticErrors errors = typeCheck.getSemanticErrors(); 00383 00384 if (typeCheck.getNumberOfSemanticErrors() > 0 && last_step == 6) { 00385 System.out.print(errors.toString()); 00386 System.exit(0); 00387 } 00388 00389 if (last_step == 6) { 00390 System.exit(0); 00391 } 00392 00393 // Si existen errores semanticos se detiene la compilacion 00394 // aunque se haya pedido llegar hasta un paso posterior. 00395 if (typeCheck.getNumberOfSemanticErrors() > 0) { 00396 System.out.print(errors.toString()); 00397 System.out.println("Type checking: " + typeCheck.getNumberOfSemanticErrors() + " semantic errors has been found."); 00398 System.exit(0); 00399 } 00400 00401 // Se declaran las variables necesarias para crear 00402 // correctamente el codeGen especificandole 00403 // la tabla de simbolos y la biblioteca 00404 // de templates que usara. Se usa el mismo NodeStream 00405 // que en el typeCheck pero se hace un reset para 00406 // situarse otra vez en la raiz del AST. 00407 00408 // load the group file CodeGen.stg, put in templates var 00409 FileReader groupFileR = new FileReader("CodeGen.stg"); 00410 StringTemplateGroup templates = new StringTemplateGroup(groupFileR); 00411 groupFileR.close(); 00412 00413 nodes.reset(); // NodeStream will be revisited 00414 CodeGen codeGen = new CodeGen(nodes, symtab); 00415 00416 codeGen.setTemplateLib(templates); // where to find templates 00417 00418 // Se llama al generador de codigo codeGen y se obtiene 00419 // el template con el t-codigo generado. 00420 CodeGen.program_return ret2 = codeGen.program(); 00421 00422 StringTemplate output = (StringTemplate) ret2.getTemplate(); 00423 00424 // Se comprueban los errores de no reconocimiento del AST. 00425 recognitionExceptions = codeGen.getExceptions(); 00426 if (recognitionExceptions.size() > 0) { 00427 System.out.println("Tree parser 'CodeGen' threw exceptions -- see output"); 00428 System.exit(1); 00429 } 00430 00431 if (last_step == 7) { 00432 System.exit(0); 00433 } 00434 00435 // Se transforma el template en texto, y se hacen algunos 00436 // cambios para que quede visualmente mejor. 00437 String myTCode = output.toString(); // render full template 00438 String myTCodeWoutBlankLines = myTCode.replaceAll("\n[\n]+","\n").replaceAll("\nsubroutine","\n\nsubroutine"); 00439 00440 // Se escribe el t-codigo generado. 00441 if (last_step == 8) { 00442 // Emit Codegen 00443 // get template from return values struct 00444 System.out.print(myTCodeWoutBlankLines); 00445 System.exit(0); 00446 } 00447 00448 // Comienza el interprete que tiene dos partes 00449 // (1) analisis lexico y sintactico del t-codigo 00450 // (2) analisis semantico del t-codigo 00451 // (3) ejecucion del t-codigo 00452 // Se declaran las variables necesarias para crear 00453 // correctamente el lexer y el parser del t-codigo. 00454 ANTLRStringStream tcodeInput = new ANTLRStringStream(myTCodeWoutBlankLines); 00455 TCodeLexer tcodeLexer = new TCodeLexer(tcodeInput); 00456 CommonTokenStream tcodeTokens = new CommonTokenStream(tcodeLexer); 00457 TCodeParser tcodeParser = new TCodeParser(tcodeTokens); 00458 00459 // Se llama al parser de t-codigo. 00460 tcodeParser.program(); 00461 00462 // Se comprueban los errores lexico/sintacticos del t-codigo. 00463 recognitionExceptions = tcodeParser.getExceptions(); 00464 if (recognitionExceptions.size() > 0) { 00465 System.out.println("Parser 'TCodeParser' threw exceptions -- see output"); 00466 System.exit(1); 00467 } 00468 00469 if (last_step == 9) { 00470 System.exit(0); 00471 } 00472 00473 // Se obtiene la representacion del t-codigo generada 00474 // por el parser. 00475 TCode tcode = tcodeParser.getTCode(); 00476 00477 // Se obtienen y, si existen, se escriben los errores semanticos. 00478 TCodeSemanticErrors tcErrors = tcode.getSemanticErrors(); 00479 00480 if (tcErrors.getNumberOfSemanticErrors() > 0 && last_step == 10) { 00481 System.out.print(tcErrors.toString()); 00482 System.exit(0); 00483 } 00484 00485 if (last_step == 10) { 00486 System.exit(0); 00487 } 00488 00489 // Si existen errores semanticos se detiene la compilacion 00490 // aunque se haya pedido llegar hasta un paso posterior. 00491 if (tcErrors.getNumberOfSemanticErrors() > 0) { 00492 System.out.println("The TCode generated has " + tcErrors.getNumberOfSemanticErrors() + " semantic errors:"); 00493 System.out.print(tcErrors.toString()); 00494 System.exit(0); 00495 } 00496 00497 // A continuacion se ejecuta usando el metodo run() que 00498 // devuelve un string con los resultados, y finalmente 00499 // estos se escriben. 00500 String results = tcode.run(); 00501 System.out.print(results); 00502 } 00503 00504 }