001 package com.croftsoft.apps.compiler.mini.code; 002 003 import java.io.PrintStream; 004 import java.util.*; 005 006 import com.croftsoft.apps.compiler.mini.node.*; 007 import com.croftsoft.apps.compiler.mini.parse.MiniSymbols; 008 009 /********************************************************************* 010 * Generates Java source code from MiniNode objects. 011 * 012 * @see 013 * com.croftsoft.apps.compiler.mini.node.MiniNodeCodeVisitor 014 * 015 * @author 016 * <A HREF="http://www.alumni.caltech.edu/~croft/">David W. Croft</A> 017 * @version 018 * 1999-04-27 019 *********************************************************************/ 020 021 public class JavaSourceMiniNodeCodeVisitor 022 implements MiniNodeCodeVisitor, MiniSymbols 023 ////////////////////////////////////////////////////////////////////// 024 ////////////////////////////////////////////////////////////////////// 025 { 026 027 protected PrintStream out; 028 protected String className; 029 030 protected int depth; 031 protected int nextTemp; 032 033 protected String margin = " "; 034 protected String demarkLine 035 = "///////////////////////////////////" 036 + "///////////////////////////////////"; 037 038 ////////////////////////////////////////////////////////////////////// 039 ////////////////////////////////////////////////////////////////////// 040 041 public JavaSourceMiniNodeCodeVisitor ( 042 PrintStream out, 043 String className ) 044 ////////////////////////////////////////////////////////////////////// 045 { 046 this.out = out; 047 this.className = className; 048 } 049 050 ////////////////////////////////////////////////////////////////////// 051 ////////////////////////////////////////////////////////////////////// 052 053 public int nextTemp ( ) 054 ////////////////////////////////////////////////////////////////////// 055 { 056 return nextTemp++; 057 } 058 059 ////////////////////////////////////////////////////////////////////// 060 ////////////////////////////////////////////////////////////////////// 061 062 protected void indent ( ) 063 ////////////////////////////////////////////////////////////////////// 064 { 065 out.print ( pad ( ) ); 066 } 067 068 protected String pad ( ) 069 ////////////////////////////////////////////////////////////////////// 070 { 071 String s = margin; 072 073 for ( int i = 0; i < depth; i++ ) s += " "; 074 075 return s; 076 } 077 078 protected void generate ( 079 String prefix, List miniNodeList, String postfix, 080 String delimiter ) 081 ////////////////////////////////////////////////////////////////////// 082 { 083 if ( miniNodeList == null ) return; 084 085 Iterator i = miniNodeList.iterator ( ); 086 087 while ( i.hasNext ( ) ) 088 { 089 if ( prefix != null ) 090 { 091 out.print ( prefix ); 092 } 093 094 ( ( MiniNode ) i.next ( ) ).generate ( this ); 095 096 if ( postfix != null ) out.print ( postfix ); 097 098 if ( delimiter != null ) 099 { 100 if ( i.hasNext ( ) ) out.print ( delimiter ); 101 } 102 } 103 } 104 105 protected void generate ( List miniNodeList ) 106 ////////////////////////////////////////////////////////////////////// 107 { 108 generate ( null, miniNodeList, null, null ); 109 } 110 111 ////////////////////////////////////////////////////////////////////// 112 ////////////////////////////////////////////////////////////////////// 113 114 public void generateAssignmentStatement ( MiniNode miniNode ) 115 ////////////////////////////////////////////////////////////////////// 116 { 117 AssignmentStatementMiniNode assignmentStatementMiniNode 118 = ( AssignmentStatementMiniNode ) miniNode; 119 120 indent ( ); 121 122 assignmentStatementMiniNode.getNameMiniNode ( ).generate ( this ); 123 124 out.print ( " = " ); 125 126 assignmentStatementMiniNode.getExpressionMiniNode ( ).generate ( 127 this ); 128 129 out.println ( ";" ); 130 } 131 132 public void generateBlock ( MiniNode miniNode ) 133 ////////////////////////////////////////////////////////////////////// 134 { 135 BlockMiniNode blockMiniNode = ( BlockMiniNode ) miniNode; 136 137 DeclarationSequenceMiniNode declarationSequenceMiniNode 138 = blockMiniNode.getDeclarationSequenceMiniNode ( ); 139 140 if ( declarationSequenceMiniNode != null ) 141 { 142 declarationSequenceMiniNode.generate ( this ); 143 out.println ( "" ); 144 } 145 146 StatementSequenceMiniNode statementSequenceMiniNode 147 = blockMiniNode.getStatementSequenceMiniNode ( ); 148 149 if ( statementSequenceMiniNode != null ) 150 { 151 statementSequenceMiniNode.generate ( this ); 152 } 153 } 154 155 public void generateComparison ( MiniNode miniNode ) 156 ////////////////////////////////////////////////////////////////////// 157 { 158 ComparisonMiniNode comparisonMiniNode 159 = ( ComparisonMiniNode ) miniNode; 160 161 comparisonMiniNode.getLeftExpressionMiniNode ( ).generate ( this ); 162 163 out.print ( " " ); 164 165 comparisonMiniNode.getRelationMiniNode ( ).generate ( this ); 166 167 out.print ( " " ); 168 169 comparisonMiniNode.getRightExpressionMiniNode ( ).generate ( this ); 170 } 171 172 public void generateConditionalStatement ( MiniNode miniNode ) 173 ////////////////////////////////////////////////////////////////////// 174 { 175 ConditionalStatementMiniNode conditionalStatementMiniNode 176 = ( ConditionalStatementMiniNode ) miniNode; 177 178 indent ( ); 179 180 out.print ( "if ( " ); 181 182 conditionalStatementMiniNode.getComparisonMiniNode ( ).generate ( 183 this ); 184 185 out.println ( " )" ); 186 187 indent ( ); 188 189 out.println ( "{" ); 190 191 depth++; 192 193 conditionalStatementMiniNode.getThenStatementSequenceMiniNode ( 194 ).generate ( this ); 195 196 depth--; 197 198 indent ( ); 199 200 out.println ( "}" ); 201 202 StatementSequenceMiniNode elseStatementSequenceMiniNode 203 = conditionalStatementMiniNode.getElseStatementSequenceMiniNode ( 204 ); 205 206 if ( elseStatementSequenceMiniNode != null ) 207 { 208 indent ( ); 209 210 out.println ( "else" ); 211 212 indent ( ); 213 214 out.println ( "{" ); 215 216 depth++; 217 218 elseStatementSequenceMiniNode.generate ( this ); 219 220 depth--; 221 222 indent ( ); 223 224 out.println ( "}" ); 225 } 226 } 227 228 public void generateConstant ( MiniNode miniNode ) 229 ////////////////////////////////////////////////////////////////////// 230 { 231 ConstantMiniNode constantMiniNode 232 = ( ConstantMiniNode ) miniNode; 233 234 out.print ( constantMiniNode.getI ( ) ); 235 } 236 237 public void generateDeclarationSequence ( MiniNode miniNode ) 238 ////////////////////////////////////////////////////////////////////// 239 { 240 DeclarationSequenceMiniNode declarationSequenceMiniNode 241 = ( DeclarationSequenceMiniNode ) miniNode; 242 243 generate ( pad ( ), 244 declarationSequenceMiniNode.getDeclarationMiniNodeList ( ), 245 null, null ); 246 } 247 248 public void generateDefiniteLoopStatement ( MiniNode miniNode ) 249 ////////////////////////////////////////////////////////////////////// 250 { 251 DefiniteLoopStatementMiniNode definiteLoopStatementMiniNode 252 = ( DefiniteLoopStatementMiniNode ) miniNode; 253 254 indent ( ); 255 256 // Underscores are not used in the Mini language so it is safe to 257 // use them to create new variables without fear of namespace 258 // conflicts. 259 260 String countStr = "count_" + nextTemp ( ); 261 String indexStr = "index_" + nextTemp ( ); 262 263 out.print ( "int " + countStr + " = " ); 264 265 definiteLoopStatementMiniNode.getExpressionMiniNode ( ).generate ( 266 this ); 267 268 out.println ( ";" ); 269 270 indent ( ); 271 272 out.println ( "for ( int " + indexStr + " = 0; " 273 + indexStr + " < " + countStr + "; " + indexStr + "++ )" ); 274 275 indent ( ); 276 277 out.println ( "{" ); 278 279 depth++; 280 281 definiteLoopStatementMiniNode.getStatementSequenceMiniNode ( 282 ).generate ( this ); 283 284 depth--; 285 286 indent ( ); 287 288 out.println ( "}" ); 289 } 290 291 public void generateExpression ( MiniNode miniNode ) 292 ////////////////////////////////////////////////////////////////////// 293 { 294 ExpressionMiniNode expressionMiniNode 295 = ( ExpressionMiniNode ) miniNode; 296 297 MiniNode expression = expressionMiniNode.getExpressionMiniNode ( ); 298 299 if ( expression != null ) 300 { 301 expression.generate ( this ); 302 303 out.print ( " " ); 304 305 expressionMiniNode.getOperatorMiniNode ( ).generate ( this ); 306 307 out.print ( " " ); 308 } 309 310 expressionMiniNode.getTermMiniNode ( ).generate ( this ); 311 } 312 313 public void generateExpressionElement ( MiniNode miniNode ) 314 ////////////////////////////////////////////////////////////////////// 315 { 316 ExpressionElementMiniNode expressionElementMiniNode 317 = ( ExpressionElementMiniNode ) miniNode; 318 319 out.print ( "( " ); 320 321 expressionElementMiniNode.getExpressionMiniNode ( ).generate ( 322 this ); 323 324 out.print ( " )" ); 325 } 326 327 public void generateExpressionSequence ( MiniNode miniNode ) 328 ////////////////////////////////////////////////////////////////////// 329 { 330 ExpressionSequenceMiniNode expressionSequenceMiniNode 331 = ( ExpressionSequenceMiniNode ) miniNode; 332 333 generate ( null, 334 expressionSequenceMiniNode.getExpressionMiniNodeList ( ), 335 null, ", " ); 336 } 337 338 public void generateIndefiniteLoopStatement ( MiniNode miniNode ) 339 ////////////////////////////////////////////////////////////////////// 340 { 341 IndefiniteLoopStatementMiniNode indefiniteLoopStatementMiniNode 342 = ( IndefiniteLoopStatementMiniNode ) miniNode; 343 344 indent ( ); 345 346 out.print ( "while ( " ); 347 348 indefiniteLoopStatementMiniNode.getComparisonMiniNode ( ).generate ( 349 this ); 350 351 out.println ( " )" ); 352 353 indent ( ); 354 355 out.println ( "{" ); 356 357 depth++; 358 359 indefiniteLoopStatementMiniNode.getStatementSequenceMiniNode ( 360 ).generate ( this ); 361 362 depth--; 363 364 indent ( ); 365 366 out.println ( "}" ); 367 } 368 369 public void generateInputStatement ( MiniNode miniNode ) 370 ////////////////////////////////////////////////////////////////////// 371 { 372 InputStatementMiniNode inputStatementMiniNode 373 = ( InputStatementMiniNode ) miniNode; 374 375 NameSequenceMiniNode nameSequenceMiniNode 376 = inputStatementMiniNode.getNameSequenceMiniNode ( ); 377 378 out.println ( pad ( ) + "try" ); 379 out.println ( pad ( ) + "{" ); 380 381 generate ( pad ( ) + " ", 382 nameSequenceMiniNode.getNameMiniNodeList ( ), 383 " = Integer.parseInt ( new java.io.BufferedReader (" 384 + System.getProperty ( "line.separator" ) 385 + pad ( ) + " " 386 + "new java.io.InputStreamReader ( System.in ) ).readLine ( ) );" 387 + System.getProperty ( "line.separator" ), 388 null ); 389 390 out.println ( pad ( ) + "}" ); 391 out.println ( pad ( ) + "catch ( java.io.IOException ex )" ); 392 out.println ( pad ( ) + "{" ); 393 out.println ( pad ( ) 394 + " throw new RuntimeException ( \"input error\" );" ); 395 out.println ( pad ( ) + "}" ); 396 } 397 398 public void generateIntegerDeclaration ( MiniNode miniNode ) 399 ////////////////////////////////////////////////////////////////////// 400 { 401 IntegerDeclarationMiniNode integerDeclarationMiniNode 402 = ( IntegerDeclarationMiniNode ) miniNode; 403 404 out.print ( "int " ); 405 406 integerDeclarationMiniNode.getNameSequenceMiniNode ( ).generate ( 407 this ); 408 409 out.println ( ";" ); 410 } 411 412 public void generateName ( MiniNode miniNode ) 413 ////////////////////////////////////////////////////////////////////// 414 { 415 NameMiniNode nameMiniNode = ( NameMiniNode ) miniNode; 416 417 out.print ( nameMiniNode.getName ( ) ); 418 } 419 420 public void generateNameSequence ( MiniNode miniNode ) 421 ////////////////////////////////////////////////////////////////////// 422 { 423 NameSequenceMiniNode nameSequenceMiniNode 424 = ( NameSequenceMiniNode ) miniNode; 425 426 generate ( null, nameSequenceMiniNode.getNameMiniNodeList ( ), 427 null, ", " ); 428 } 429 430 public void generateOperator ( MiniNode miniNode ) 431 ////////////////////////////////////////////////////////////////////// 432 { 433 OperatorMiniNode operatorMiniNode = ( OperatorMiniNode ) miniNode; 434 435 String s = null; 436 437 switch ( operatorMiniNode.getOperator ( ) ) 438 { 439 case MiniSymbols.DIVIDE: s = "/"; break; 440 case MiniSymbols.MINUS : s = "-"; break; 441 case MiniSymbols.PLUS : s = "+"; break; 442 case MiniSymbols.TIMES : s = "*"; break; 443 444 default: 445 throw new RuntimeException ( "unknown operator" ); 446 } 447 448 out.print ( s ); 449 } 450 451 public void generateOutputStatement ( MiniNode miniNode ) 452 ////////////////////////////////////////////////////////////////////// 453 { 454 OutputStatementMiniNode outputStatementMiniNode 455 = ( OutputStatementMiniNode ) miniNode; 456 457 ExpressionSequenceMiniNode expressionSequenceMiniNode 458 = outputStatementMiniNode.getExpressionSequenceMiniNode ( ); 459 460 generate ( pad ( ) + "System.out.println ( ", 461 expressionSequenceMiniNode.getExpressionMiniNodeList ( ), 462 " );" + System.getProperty ( "line.separator" ), 463 null ); 464 } 465 466 public void generateParameterSequence ( MiniNode miniNode ) 467 ////////////////////////////////////////////////////////////////////// 468 { 469 ParameterSequenceMiniNode parameterSequenceMiniNode 470 = ( ParameterSequenceMiniNode ) miniNode; 471 472 NameSequenceMiniNode nameSequenceMiniNode 473 = parameterSequenceMiniNode.getNameSequenceMiniNode ( ); 474 475 List nameMiniNodeList 476 = nameSequenceMiniNode.getNameMiniNodeList ( ); 477 478 generate ( "int ", nameMiniNodeList, null, ", " ); 479 } 480 481 public void generateProcedureCallStatement ( MiniNode miniNode ) 482 ////////////////////////////////////////////////////////////////////// 483 { 484 ProcedureCallStatementMiniNode procedureCallStatementMiniNode 485 = ( ProcedureCallStatementMiniNode ) miniNode; 486 487 NameMiniNode nameMiniNode 488 = procedureCallStatementMiniNode.getNameMiniNode ( ); 489 490 indent ( ); 491 492 if ( procedureCallStatementMiniNode.callsNested ( 493 ).booleanValue ( ) ) 494 { 495 out.print ( "new " ); 496 497 nameMiniNode.generate ( this ); 498 499 out.print ( " ( ).procedure (" ); 500 501 } 502 else 503 { 504 nameMiniNode.generate ( this ); 505 out.print ( " (" ); 506 } 507 508 ExpressionSequenceMiniNode expressionSequenceMiniNode 509 = procedureCallStatementMiniNode.getExpressionSequenceMiniNode ( 510 ); 511 512 if ( expressionSequenceMiniNode != null ) 513 { 514 out.print ( " " ); 515 516 expressionSequenceMiniNode.generate ( this ); 517 } 518 519 out.println ( " );" ); 520 } 521 522 public void generateProcedureDeclaration ( MiniNode miniNode ) 523 ////////////////////////////////////////////////////////////////////// 524 { 525 ProcedureDeclarationMiniNode procedureDeclarationMiniNode 526 = ( ProcedureDeclarationMiniNode ) miniNode; 527 528 NameMiniNode nameMiniNode 529 = procedureDeclarationMiniNode.getNameMiniNode ( ); 530 531 BlockMiniNode blockMiniNode 532 = procedureDeclarationMiniNode.getBlockMiniNode ( ); 533 534 DeclarationSequenceMiniNode declarationSequenceMiniNode 535 = blockMiniNode.getDeclarationSequenceMiniNode ( ); 536 537 boolean hasNestedProcedures = false; 538 539 if ( declarationSequenceMiniNode != null ) 540 { 541 List declarationMiniNodeList 542 = declarationSequenceMiniNode.getDeclarationMiniNodeList ( ); 543 544 Iterator i = declarationMiniNodeList.iterator ( ); 545 while ( i.hasNext ( ) ) 546 { 547 if ( i.next ( ) instanceof ProcedureDeclarationMiniNode ) 548 { 549 hasNestedProcedures = true; 550 break; 551 } 552 } 553 } 554 555 out.println ( "" ); 556 557 if ( !hasNestedProcedures ) 558 { 559 out.print ( margin + "public void " ); 560 nameMiniNode.generate ( this ); 561 out.print ( " (" ); 562 563 ParameterSequenceMiniNode parameterSequenceMiniNode 564 = procedureDeclarationMiniNode.getParameterSequenceMiniNode ( ); 565 566 if ( parameterSequenceMiniNode != null ) 567 { 568 out.print ( " " ); 569 parameterSequenceMiniNode.generate ( this ); 570 } 571 572 out.println ( " )" ); 573 574 out.println ( margin + demarkLine ); 575 576 out.println ( margin + "{" ); 577 578 depth++; 579 580 blockMiniNode.generate ( this ); 581 582 depth--; 583 584 out.println ( margin + "}" ); 585 586 out.println ( "" ); 587 } 588 else 589 { 590 out.print ( margin + "public class " ); 591 nameMiniNode.generate ( this ); 592 out.println ( "" ); 593 594 out.println ( margin + demarkLine ); 595 out.print ( margin + "// Start of inner class " ); 596 nameMiniNode.generate ( this ); 597 out.println ( "" ); 598 out.println ( margin + demarkLine ); 599 out.println ( margin + "{" ); 600 601 if ( declarationSequenceMiniNode != null ) 602 { 603 out.println ( "" ); 604 declarationSequenceMiniNode.generate ( this ); 605 } 606 607 out.println ( "" ); 608 609 out.print ( margin + "public void procedure (" ); 610 611 ParameterSequenceMiniNode parameterSequenceMiniNode 612 = procedureDeclarationMiniNode.getParameterSequenceMiniNode ( ); 613 614 if ( parameterSequenceMiniNode != null ) 615 { 616 out.print ( " " ); 617 parameterSequenceMiniNode.generate ( this ); 618 } 619 620 out.println ( " )" ); 621 622 out.println ( margin + demarkLine ); 623 624 out.println ( margin + "{" ); 625 626 depth++; 627 628 blockMiniNode.getStatementSequenceMiniNode ( ).generate ( this ); 629 630 depth--; 631 632 out.println ( margin + "}" ); 633 634 out.println ( "" ); 635 636 out.println ( margin + demarkLine ); 637 out.print ( margin + "// End of inner class " ); 638 nameMiniNode.generate ( this ); 639 out.println ( "" ); 640 out.println ( margin + demarkLine ); 641 out.println ( margin + "}" ); 642 out.println ( "" ); 643 } 644 } 645 646 public void generateProgram ( MiniNode miniNode ) 647 ////////////////////////////////////////////////////////////////////// 648 { 649 ProgramMiniNode programMiniNode = ( ProgramMiniNode ) miniNode; 650 651 out.println ( margin + "public class " + className ); 652 out.println ( margin + demarkLine ); 653 out.println ( margin + "// Start of " + className ); 654 out.println ( margin + demarkLine ); 655 out.println ( margin + "{" ); 656 657 BlockMiniNode blockMiniNode = programMiniNode.getBlockMiniNode ( ); 658 659 DeclarationSequenceMiniNode declarationSequenceMiniNode 660 = blockMiniNode.getDeclarationSequenceMiniNode ( ); 661 662 if ( declarationSequenceMiniNode != null ) 663 { 664 out.println ( "" ); 665 declarationSequenceMiniNode.generate ( this ); 666 } 667 668 out.println ( "" ); 669 out.println ( margin + "public void procedure ( )" ); 670 671 out.println ( margin + demarkLine ); 672 673 out.println ( margin + "{" ); 674 675 depth++; 676 677 blockMiniNode.getStatementSequenceMiniNode ( ).generate ( this ); 678 679 depth--; 680 681 out.println ( margin + "}" ); 682 683 out.println ( "" ); 684 out.println ( 685 margin + "public static void main ( String [ ] args )" ); 686 out.println ( margin + demarkLine ); 687 out.println ( margin + "{" ); 688 out.println ( 689 margin + " new " + className + " ( ).procedure ( );" ); 690 out.println ( margin + "}" ); 691 out.println ( "" ); 692 693 out.println ( margin + demarkLine ); 694 out.println ( margin + "// End of " + className ); 695 out.println ( margin + demarkLine ); 696 out.println ( margin + "}" ); 697 } 698 699 public void generateRelation ( MiniNode miniNode ) 700 ////////////////////////////////////////////////////////////////////// 701 { 702 RelationMiniNode relationMiniNode = ( RelationMiniNode ) miniNode; 703 704 String s = null; 705 706 switch ( relationMiniNode.getRelation ( ) ) 707 { 708 case MiniSymbols.EQ: s = "=="; break; 709 case MiniSymbols.LE: s = "<="; break; 710 case MiniSymbols.LT: s = "<" ; break; 711 case MiniSymbols.GT: s = ">" ; break; 712 case MiniSymbols.GE: s = ">="; break; 713 case MiniSymbols.NE: s = "!="; break; 714 715 default: 716 throw new RuntimeException ( "unknown relation" ); 717 } 718 719 out.print ( s ); 720 } 721 722 public void generateStatementSequence ( MiniNode miniNode ) 723 ////////////////////////////////////////////////////////////////////// 724 { 725 StatementSequenceMiniNode statementSequenceMiniNode 726 = ( StatementSequenceMiniNode ) miniNode; 727 728 generate ( null, 729 statementSequenceMiniNode.getStatementMiniNodeList ( ), 730 null, System.getProperty ( "line.separator" ) ); 731 } 732 733 public void generateTerm ( MiniNode miniNode ) 734 ////////////////////////////////////////////////////////////////////// 735 { 736 TermMiniNode termMiniNode = ( TermMiniNode ) miniNode; 737 738 MiniNode term = termMiniNode.getTermMiniNode ( ); 739 740 if ( term != null ) 741 { 742 term.generate ( this ); 743 744 out.print ( " " ); 745 746 termMiniNode.getOperatorMiniNode ( ).generate ( this ); 747 748 out.print ( " " ); 749 } 750 751 termMiniNode.getElementMiniNode ( ).generate ( this ); 752 } 753 754 ////////////////////////////////////////////////////////////////////// 755 ////////////////////////////////////////////////////////////////////// 756 }