001         package com.croftsoft.apps.compiler;
002    
003         import java.io.*;
004    
005         import java_cup.runtime.Symbol;
006    
007         /*********************************************************************
008         * A calculator capable of parsing input.
009         *
010         * <P>
011         *
012         * Built using the
013         *
014         * CUP Parser Generator for Java
015         * (<A HREF="http://www.cs.princeton.edu/~appel/modern/java/CUP/">
016         * http://www.cs.princeton.edu/~appel/modern/java/CUP/</A>)
017         *
018         * and
019         *
020         * JLex: A Lexical Analyzer Generator for Java
021         * (<A HREF="http://www.cs.princeton.edu/~appel/modern/java/JLex/">
022         * http://www.cs.princeton.edu/~appel/modern/java/JLex/</A>).
023         *
024         * @version
025         *   1999-03-16
026         * @author
027         *   <A HREF="http://www.alumni.caltech.edu/~croft/">David W. Croft</A>
028         *********************************************************************/
029    
030         public class  Calc
031         //////////////////////////////////////////////////////////////////////
032         //////////////////////////////////////////////////////////////////////
033         {
034    
035         public static final String  INFO
036           = "=============================================\n"
037           + "Calc (C) Copyright 1999 David Wallace Croft\n"
038           + "\n"
039           + "Version 1999-03-16\n"
040           + "Source code available at http://www.orbs.com/\n"
041           + "\n"
042           + "Enter your calculations at the command line.\n"
043           + "Example:  a := 2; b := 3; write ( a + b );\n"
044           + "=============================================\n"
045           + "\n";
046    
047         private static final boolean  DO_DEBUG_PARSE = false;
048    
049         private static final String [ ]  TEST_DATA = {
050    
051             "a := 2;"                        
052           + "write ( a );"                   // 2
053           + "write ( b );"                   // null
054           + "b := 3;"
055           + "write ( b );"                   // 3
056           + "c := a + b;"                    
057           + "write ( c );",                  // 5
058    
059             "a := 2;"
060           + "b := 3;"
061           + "write ( a + b );"               // 5
062           + "write ( a - b );"               // -1
063           + "write ( a * b );"               // 6
064           + "write ( a / b );"               // 0
065           + "write ( a % b );"               // 2
066           + "write ( a ^ b );"               // 8
067           + "write ( a * b ^ a );",          // 18, not 36
068    
069             "bill_123 := 3;"
070           + "write ( bill_123 );",           // 3
071    
072             "write ( a := 1 + 2 );"          // 3
073           + "write ( b := a + 3 );"          // 6
074           + "write ( c := 1 + ( b := 2 ) );" // 3
075           + "write ( b );"                   // 2
076           + "write ( c );",                  // 3
077    
078             "write ( a );"                   // null
079           + "b := 1;"
080           + "write ( b );"                   // 1
081           + "b := a;"
082           + "write ( b );",                  // null
083    
084             "a := 2;"
085           + "b := 3;"
086           + "write ( -1 );"                  // -1
087           + "write ( 1 - -1 );"              // 2
088           + "write ( -a );"                  // -2
089           + "write ( -a + -b );"             // -5
090           + "write ( - ( a - -b ) + 1 );",   // -4
091    
092           // The following test is only partially successful due to error
093           // recovery with parentheses not being handled properly, I suspect.
094    
095             "hello;"                         // syntax error
096           + "write ( 1 );"                   // 1
097           + "write ( 1 + ( 2 + );"           // syntax error
098           + "write ( 2 );"                   // 2
099           + "write ( 1 + ( 2 + 1 );",        // syntax error
100    
101             "a := 2;"
102           + "write ( a + b );"               // null operand, null operand
103           + "b := 3;"
104           + "write ( a + b );"               // 5
105    
106           };
107    
108         //////////////////////////////////////////////////////////////////////
109         //////////////////////////////////////////////////////////////////////
110    
111         public static void  main ( String [ ]  args )
112         //////////////////////////////////////////////////////////////////////
113         {
114           System.out.println ( INFO );
115    
116           if ( args.length < 1 )
117           {
118             parse ( System.in );
119           }
120           else
121           {
122             test ( );
123           }
124         }
125    
126         public static boolean  test ( )
127         //////////////////////////////////////////////////////////////////////
128         {
129           for ( int  i = 0; i < TEST_DATA.length; i++ )
130           {
131             System.out.println ( "--- Test " + i + " --- " );
132             parse ( new StringReader ( TEST_DATA [ i ] ) );
133             System.out.println ( "" );
134           }
135    
136           return true;
137         }
138    
139         public static void  parse ( InputStream  inputStream )
140         //////////////////////////////////////////////////////////////////////
141         {
142           parse ( new CalcScanner ( inputStream ) );
143         }
144    
145         public static void  parse ( Reader  reader )
146         //////////////////////////////////////////////////////////////////////
147         {
148           parse ( new CalcScanner ( reader ) );
149         }
150    
151         public static void  parse ( CalcScanner  calcScanner )
152         //////////////////////////////////////////////////////////////////////
153         {
154           CalcParser  parser = new CalcParser ( calcScanner );
155    
156           Symbol  parseTree = null;
157    
158           try
159           {
160             if ( DO_DEBUG_PARSE )
161             {
162               parseTree = parser.debug_parse ( );
163             }
164             else
165             {
166               parseTree = parser.parse ( );
167             }
168           }
169           catch ( Exception  ex )
170           {
171             ex.printStackTrace ( );
172           }
173    
174           // System.out.println ( parseTree );
175         }
176    
177         //////////////////////////////////////////////////////////////////////
178         //////////////////////////////////////////////////////////////////////
179         }