CSc 109 Test 1  Wednesday  24 April 2002
=============== SUGGESTED ANSWERS ==================
1. (25 pts)  Given the syntax diagrams below (where [] stands for a box and ()
stands for a circle), write the declarations and definitions for the class
Parse such that the program in main() displays "Success" if and only if a line
of text entered from the console satisfies the diagram for A.  I have started
the answer. You can assume that the members I have declared have been defined.
Your program should assume that no blanks or tabs are allowed.

    A                                      B
    ----> (a) --->[B]---------------->     ----------->(c)-->[B]-->(c)-----
                       ^         |               |                         |
                       |         |               |----(d)----------------->|
                      [B]<--(z)<-                |                         |
                                                 |----(e)----->[A]----------->
  int main()
  {Parse p;
   p.par();
   cout<<"Success\n";
  }
  class Parse
  {public:
     Parse();
   private:
     static void errCheck(bool b,char *mess);//if b display message and exit()
     char ch;
   //  ..... your private and public declarations are below
<<<<<<<<<<<<<<
#include <fstream.h>
#include <stdlib.h>                                                 |----(e)----->[A]-----------

  class Parse
  {public:
     Parse();
   private:
     static void errCheck(bool b,char *mess);//if b display message and exit()
     char ch;
   public:
     void par();
   private:
     void A();
     void B();
};

 int main()
  {Parse p;
   p.par();
   cout<<"Success\n";
   cin.get();
   cin.get();
  }

  void Parse::par()
  {cin.get(ch);
   A();
   cout<<"\nch == "<<ch<<endl;
   errCheck(ch!='\n',"eoln expected");
  }

  void Parse::A()
  {errCheck(ch!='a',"'a' expected");
   cin.get(ch);
   B();
   while(ch=='z')
   {cin.get(ch);
    B();
   }
  }

  void Parse::B()
  {switch(ch)
    { case 'c': cin.get(ch); B(); errCheck(ch!='c',"'c' expected");
                cin.get(ch); break;
      case 'd': cin.get(ch); break;
      case 'e': cin.get(ch); A(); break;
      default: errCheck(true,"'c', 'd', or 'e' expected");
    }
  }

  Parse::Parse(){}
  void Parse::errCheck(bool b,char *mess)
  {if(b)
    {cout<<mess<<endl;
     cin.get();
     cin.get();
     exit(1);
    }
  }

2.  (25 pts) Write the template for a class Safe which does not allow access
to a value unless it has been previously defined.  The code below should
compile and produce the output indicated.  You only need write the methods
needed to make the code function properly.
Safe<int> a,b(3);
Safe<double> d(23.4);
cout<<b<<"  "<<d<<endl;
cout<<a<<endl;
/* <OUTPUT>
   3 23.4
   Undefined Value
  */
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#include <fstream.h>
template <class T>
class Safe
{public:
  Safe();
  Safe(const T&t);
  template <class V>
  friend ostream & operator<<(ostream &out,const Safe<V> & s);
 private:
   bool set;
   T value;
};

template <class T>
Safe<T>::Safe()
{set=false;}

template <class T>
Safe<T>::Safe(const T&t)
{set=true;
 value=t;
}

template <class T>
ostream & operator<<(ostream &out,const Safe<T> & s)
{if(!s.set)
   out<<"Undefined Value";
 else
   out<<s.value;
 return out;
}

int main()
{
Safe<int> a,b(3);
Safe<double> c,d(23.4);
 cout<<b<<"  "<<d<<endl;
cout<<a<<endl;    //error, should exit
cin.get();
}

3.  (25 pts) Below the Stack Machine mnemonics is a Modest Language Program.
   Translate it into an equivalent Stack Machine Program which will output
   8 if the value read into x is neither 2 nor 9 and will output 7 if x is
   either 2 or 9.
   HALT=0,ADD=1,SUB=-1,MUL=2,DIV=-2,READ=3,WRITE=-3,PUSH=4,POP=-4,PUSHI=5,
   JMP=-5,JMPL=6,JMPG=-6,JMPE=7,JMPNE=-7

   ints x
   read x
   bools d
   d=x!=2 and x!=9
   if d goto 100
   write 7
   stop
   100 write 8
   stop
   end
<<<<<<<<<<<<<<<<<<<<<<<<<<<<
3000 read x
-4200  store x way above program
4200   get x
5002
-1000   x-2 will be 0 (false) if x==2
4200   get x
5011   store 9
-1000   x-9  will be 0 (false) if x==9
2000     x!=2 & x!=9
-7015   skip to 13
5007
-3000   write 7
0
5010    location 13
-3000
0
E


4.  (25 pts) I made a mistake in specifying the syntax of the Modest language
and had to remove the part that allowed the user to parenthesize boolean
expressions.  Since then I found an easy way to use commas to parentheisze
boolean expressions.  I simply added the following path to the syntax diagram
for boolFactor:     --->(,)--->[boolExp]--->(,)--->    (Here the parentheses
are replaced by pairs of commas (,) )
Thus, the user could write    b = ,false or true, and false  which would
produce a different result than  b = false or true and false.  Now we need to
write a program to compile Modest programs with such expressions.  That turns
out to be quite simple. We can create a subclass of FullParser which overloads
boolFactor(), where the overloaded boolFactor() checks for a comma. If it finds
a comma it deals with it.  Otherwise it passes the token back to the FullParser
version of boolFactor.  Call the subclass UParser.  In the main program we
need only change the declaration of the parser from FullParser p; to
UParser p;  Below I list my declaration of FullParser.  First, indicate what
changes need to be made to the declaration for class FullParser.  Second,
provide the declaration and definitions (code) for class UParser.
class FullParser: public Parser
{public:
  FullParser(istream &in=cin,ostream &out=cout,ostream & fcode=cout);
 private:
  void boolExp();
  void intExp();
  void intTerm();
  void boolTerm();
  void boolFactor();
  void intFactor();
  void genLogicCode(int op);
};
<<<<<<<<<<<<<<<<<<<<<<<<<<
// in class FullParser change "private:" to "protected:"
//                     prefixe  void boolFactor(); with "virtual "
class UParser:public FullParser
{public:
   UParser(istream & in=cin,ostream & out=cout,ostream &codeout=cout);
   void boolFactor();
};

UParser::UParser(istream & in,ostream &out,ostream &codeout)
  :FullParser(in,out,codeout){}

void UParser::boolFactor()
{if(token==Tokenize::COMMA)
  {token=tok->next();
   boolExp();
   errCheck(token!=Tokenize::COMMA,"comma");
   token=tok->next();
  }
 else
   FullParser::boolFactor();
}
