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         }