import java.util.StringTokenizer;
import java.io.*;

class SymbolTable {
  // This class uses a private DefsTree as its basic data structure.  It
  // reads a filename and looks up the definitions from that file and puts
  // all the data in its private DefsTree using the BST insert which you
  // implemented.  I have done the method that does the IO for you but you
  // have to code the other methods.  Methods like insert perform some
  // basic tests (like is the DefsTree empty) and deal with boundary cases
  // but in the end they will invoke the DefsTree method.  This class
  // allows one to have a real symbol table object even if there are no
  // bindings (i.e. the private DefsTree is null).

  private DefsTree table;

  // Constructors 
  public SymbolTable(){table = null;};
  public SymbolTable(DefsTree t){table = t;};

  // Class Methods
  public static SymbolTable getdefs(String fname){
    //This function reads the definitions from the file named by the
    //argument and constructs a Symbol Table containing the variable-value
    //bindings. 
    FileInputStream inputData;
    int val; char var;
    int blank = (int) ' ';
    SymbolTable result = new SymbolTable();

    try {
    inputData = new FileInputStream(fname);
    BufferedInputStream bis = new BufferedInputStream(inputData);
    DataInputStream dis = new DataInputStream(bis);
    String currentDef = null;
    StringTokenizer defST = null;
    //StringTokenizer rawdefs = new StringTokenizer (filein.readLine(), " ,");
    while ((currentDef = dis.readLine()) != null){
      defST = new StringTokenizer(currentDef, " ");
      //var = rawdefs.nextToken().charAt(0);
      //val = Integer.parseInt(rawdefs.nextToken());
      var = defST.nextToken().charAt(0);
      val = Integer.parseInt(defST.nextToken());
      result.insert(var,val);}
    } catch(IOException exception){
      System.out.println("Input problem. Terminating.");
      System.exit(0);}
    return result;}//end method getdefs

  // Instance Methods

  public void insert(char name, int val){
    // Insert is used to insert values into the symbol table.
    //It takes a name and a value.  The modification is made in-place and
    //nothing is returned.  
      Binding bar = new Binding(name, val);
      //If we don't have a tree yet, make a new one. Otherwise, use the
      //DefsTree insert:
      if (table == null) table = new DefsTree(bar);
      else table.insert(bar);

  }// end method insert

  public int lookup(char name){
      //use the DefsTree lookup, unless there is no tree, in which case return 0
      if (table == null) return 0;
      else return table.lookup(name);
  }// end method lookup

  void showdefs(){
    //The function showdefs is used to display the bindings stored in the
    //symbol table.  

    if (table == null) System.out.println("The table is empty");
    else table.inorder();};

  public static void main(String[] args){
    SymbolTable S = getdefs(args[0]);
    System.out.println("showdefs() output:");
    S.showdefs();
  }
}// end SymbolTable
