CSE 109 Test 1  Friday 20 October 2009
======================================================================
              SUGGESTED ANSWERS
======================================================================
1.  Below are the syntax diagrams for Exp, and below the diagrams is the
main program that purports to parse strings of characters that satisfy
the syntax of Exp. Write the code for exp() (and for any functions it calls).
You should assume that classes Lex and Word behave as discussed in lecture
an in the programming assignments.  In the diagrams I use parentheses, (),
to indicate circles (or ovals) and square brackets, [], to indicate boxes.
  Exp
  ---------------------------------------------------------------------->
        ^                         |   ^                        |
        |                         |   |                        |
        +---('/')<--[A]<--('[')<--+   +--(']')<--[A]<--('/')<--+
  A
  -------+----('+')--[A]---('+')-----[A]-----------------------------+
         |                                                           |
         +---[NUMBER]------------------------------------------------+---->
         |                                                           |
         +---('-')----[Exp]------------------------------------------+
//Recall Lex constants LBRACK, PLUS, MINUS, DIVIDE, NUMBER
#include "/proj/csc109/p5/lex.h"
#include "/proj/csc109/p5/word.h"
#include "/proj/csc109/p5/check.h"
void check(bool b, char *mess){
  check(b,mess,__LINE__,__FILE__);
}
int main(){
  Word w;
  Lex x;
  int tok;
  w.setDelimiters("\n");
  cout<<"Enter a string to parse- ";
  cin>>w;
  x.setString(w);
  tok=x.next();
  exp(x,tok);  //if an error occurs, diagnose it and exit program
  cout<<"The string is syntactically correct\n";
}
===========================================================================
void a(Lex&v,int &tok);

void exp(Lex&v,int &tok){
  while(tok==Lex::LBRACK){
    tok=v.next();
    a(v,tok);
    check(tok==Lex::DIVIDE," '/' expected");
    tok=v.next();
  }
  while(tok==Lex::DIVIDE){
    tok=v.next();
    a(v,tok);
    check(tok==Lex::RBRACK," ']' expected");
    tok=v.next();
  }
}

void a(Lex&v,int &tok){
  switch(tok){
  case Lex::PLUS: tok=v.next();
    a(v,tok);
    check(tok==Lex::PLUS,"'+' expected");
    tok=v.next();
    a(v,tok);
    break;
  case Lex::NUMBER: tok=v.next(); break;
  case Lex::MINUS: tok=v.next();
    exp(v,tok);
    break;
  default: check(false,"'+', '-', or number expected");
  }
}
===========================================================================
2.  Write a program that takes the strings entered on the command line and
for each string states whether there is a file with that name in the directory
in which the program was called. For example, if the executable file for the
program is in a.out, the command
  a.out 1 data p2.cc
would produce output something like
  The file 'a.out' exists
  The file '1' exists
  The file 'data' does not exist
  The file 'p2.cc' does not exist
===========================================================================
#include <fstream>
#include <iostream>
using namespace std;

int main(int ct, char **arg){
  ifstream f;
  for(int j=0; j<ct; j++){
    cerr<<"First file\n";
    f.open(arg[j]);
    if(f.good())
      cout<<"File '"<<arg[j]<<"' exists\n";
    else
      cout<<"File '"<<arg[j]<<"' does not exist\n";
    f.clear();
    f.close();
  }

}
===========================================================================

3.  Assume you have the function check(), and the classes Word and Lex, as
discussed in lecture. Write a function allNums() that reads in a line of text
from the keyboard and returns true if and only if the line consists solely of
NUMBERS (i.e., unsigned ints), as defined by the syntax diagrams for CALC.
===========================================================================
#include "/proj/csc109/p5/lex.h"
#include "/proj/csc109/p5/word.h"
#include "/proj/csc109/p5/check.h"

bool allNums(){
  Lex lex;
  Word w;
  int tok;
  w.setDelimiters("\n");
  cin>>w;
  for(int j=0;j<w.length();j++)
    if(w[j]=='$')
      return false;
  w.add('$');
  lex.setString(w);
  tok=lex.next();
  while(tok==Lex::NUMBER)
    tok=lex.next();
  return tok==Lex::DOLLAR;
}
===========================================================================
4. Assume you are developing a templated class to represent the ADT for a set.
Recall that a set stores single copies of various elements, no matter how many
times the given element is added to the set.  Further, assume you are
developing the template piecemeal and it is only necessary that your template,
as developed so far, have enough functionality for the code below to compile.
Write that template.
   int main(){
    Set<Word> t;  //construct a set that can hold a maximum of 100 elements
                  //of type Word
    ((t+=Word("one"))+="two")+="two";
    cout<<t<<endl;  //OUTPUT: {one, two}
   }

===========================================================================
#include <iostream>
using namespace std;
#include "/proj/csc109/p5/word.h"

template <class X>
class Set{
private:
  X t[100];
  int ct;
public:
  Set();
  Set & operator +=(const X &x);
  template <class Y>
  friend ostream & operator<<(ostream &out,const Set<Y> &s);
};

template <class X>
Set<X>::Set():ct(0){}

template <class X>
Set<X> & Set<X>::operator+=(const X &x){
  if(ct>=100)
    return *this;
  for(int j=0;j<ct;j++)
    if(t[j]==x)
      return *this;
  t[ct]=x;
  ct++;
  return *this;
}

template <class X>
ostream & operator<<(ostream &out,const Set<X> &s){
  out<<"{";
  for(int j=0; j<s.ct;j++){
    if(j>0)
      out<<", ";
    out<<s.t[j];
  }
  return out<<"}";
}
===========================================================================

