/*********************************************************************
 * Author: B. Alex Bridges                                           *
 * Login ID: brid0129                                                *
 * Class: CPSC-221, Winter 1999                                      *
 * Project: Programming Assignment 2                                 *
 * Description: This program generates a cross reference for a Java  *
 *              program file.  It uses a closed hash table with      *
 *              double hashing.                                      *
 * Contents: Methods for generating cross reference.                 *
 *********************************************************************/

/* IMPORTS */
import java.io.*;


class Xref
{
  /* CONSTANTS */
  final static boolean b_debug = false;           // CONTROLS EXTRA DEBUG OUTPUT
  final static String str_res = "Reserved.txt";   // FILENAME OF RESERVED WORDS
  final static String str_ops = "Operators.txt";  // FILENAME OF OPERATORS
  final static String str_sep = "Seperators.txt"; // FILENAME OF SEPERATORS
  final static int int_reslim = 59;               // MAX. NUMBER OF RESERVED WORDS
  final static int int_opslim = 37;               // MAX. NUMBER OF OPERATORS
  final static int int_seplim = 9;                // MAX. NUMBER OF SEPERATORS


  /* GLOBAL VARIABLES */
  public static Hash Hash_table;

  /*************************************************************************
   * Method: begin                                                         *
   * Purpose: Controls the generation of cross reference.                  *
   * Input: --PARAMATERS--                                                 *
   *        => 'str_program' = The name of the program.                    *
   * Output: --RETURNS--                                                   *
   *         => NONE                                                       *
   *************************************************************************/
  public static void begin(String str_program)
  {
    /* LOCAL VARIABLES */
    BufferedReader br_file_in;      // FILE INPUT STREAM SETUP
    boolean b_end = false;          // END OF FILE STATUS
    String str_read = new String(); // THE NEXT LINE OF TEXT

    /* FILE INPUT STREAM SETUP FOR SPECIFIED FILE */
    br_file_in = File.open(str_program, false);

    if(br_file_in == null)
      System.exit(-1);

    System.out.println();

    /* INITIALIZE HASH TABLE */
    Hash_table = new Hash();

    /* INPUT CONTROL */
    parser(br_file_in);

    System.out.println();
  } // method begin

  /*************************************************************************
   * Method: parser                                                        *
   * Purpose: Parses the stream of input.                                  *
   * Input: --PARAMATERS--                                                 *
   *        => 'br_file_in' = The stream of input.                         *
   * Output: --RETURNS--                                                   *
   *         => NONE                                                       *
   *************************************************************************/
  public static void parser(BufferedReader br_file_in)
  {
    /* LOCAL VARIABLES */
    BufferedReader br_res;                      // BUFFERED READER FOR RESERVED WORDS
    BufferedReader br_ops;                      // BUFFERED READER FOR OPERATIONS
    BufferedReader br_sep;                      // BUFFERED READER FOR SEPERATORS
    String[] strA_res = new String[int_reslim]; // SET OF RESERVED WORDS
    String[] strA_ops = new String[int_opslim]; // SET OF OPERATORS
    char[] charA_sep = new char[int_seplim];    // SET OF SEPERATORS
    int i;                                      // ARRAY INDEX
    int int_res;                                // NUMBER OF RESERVED WORDS
    int int_ops;                                // NUMBER OF OPERATIONS
    int int_sep;                                // NUMBER OF SEPERATORS
    StreamTokenizer stmT_parser;                // STREAM TOKENIZER
    boolean b_end = false;                      // END OF FILE STATUS
    int int_token;                              // NUMERIC VALUE FOR NEXT TOKEN
    String str_token = new String();            // STRING OF CURRENT TOKEN
    String str_value = new String();            // STRING OF CURRENT VALUE
    int int_line;                               // LINE NUMBER OF CURRENT TOKEN
    boolean b_match = false;                    // STATUS OF MATCH IN ABOVE MENTIONED SETS

    try
    {
      /* LOAD RESERVED WORDS */
      br_res = File.open(str_res, false);
      i = 0;
      while( br_res.ready() )
        strA_res[i++] = br_res.readLine();;
      int_res = i;

      if(b_debug)
      {
        System.out.println("--RESERVED WORDS--");
        for(i = 0; i < int_res; i++)
          System.out.print(strA_res[i]+", ");
        System.out.println("\n");
      } // if

      /* LOAD OPERATORS */
      br_ops = File.open(str_ops, false);
      i = 0;
      while( br_ops.ready() )
        strA_ops[i++] = br_ops.readLine();;
      int_ops = i;

      if(b_debug)
      {
        System.out.println("--OPERATORS--");
        for(i = 0; i < int_ops; i++)
          System.out.print(strA_ops[i]+", ");
        System.out.println("\n");
      } // if

      /* LOAD SEPERATORS */
      br_sep = File.open(str_sep, false);
      i = 0;
      while( br_sep.ready() )
        charA_sep[i++] = br_sep.readLine().charAt(0);
      int_sep = i;

      if(b_debug)
      {
        System.out.println("--SEPERATORS--");
        for(i = 0; i < int_sep; i++)
          System.out.print(charA_sep[i]+", ");
        System.out.println("\n");
      } // if

      /* CREATION AND SETUP OF TOKENIZER */
      stmT_parser = new StreamTokenizer(br_file_in);
      stmT_parser.slashSlashComments(true);   // SINGLE-LINE COMMENTS
      stmT_parser.slashStarComments(true);    // MULTI-LINE COMMENTS
      stmT_parser.quoteChar('"');             // STRING CONSTANTS = 34
      stmT_parser.whitespaceChars('.', '.');  // PERIOD = 46

      /* INPUT => TOKENS */
      b_end = false;
      while(!b_end)
      {
        int_token = stmT_parser.nextToken();

        str_token = stmT_parser.toString();
        int_line = stmT_parser.lineno();

        /* TOKEN TYPE */
        switch(stmT_parser.ttype)
        {
          /* EOF */
          case java.io.StreamTokenizer.TT_EOF:
            b_end = true;
            break;
          /* NUMBER */
          case java.io.StreamTokenizer.TT_NUMBER:
            str_value = String.valueOf(stmT_parser.nval);

            System.out.println("Inserting "+str_token+".");

            Hash_table.insert(str_value, int_line);

            break;
          /* WORD */
          case java.io.StreamTokenizer.TT_WORD:
            str_value = stmT_parser.sval;

            // => CHECK IF RESERVED WORD
            b_match = false;
            for(i = 0; i < int_res; i++)
              if( str_value.equals(strA_res[i]) )
              {
                b_match = true;
                break;
              } // if

            if(!b_match)
              System.out.println("Inserting "+str_token+".");
            else if(b_match)
              System.out.println("Skipping "+str_token+".");

             if(!b_match)
              Hash_table.insert(str_value, int_line);

            break;
          /* OTHER */
          default:
            str_value = String.valueOf( str_token.charAt(7) ); // Extract x from "Token['x'], line n"

            // => CHECK IF OPERATOR
            b_match = false;
            for(i = 0; i < int_ops; i++)
              if( str_value.equals(strA_ops[i]) )
              {
                b_match = true;
                break;
              } // if

            if(b_match)
              System.out.println("Skipping "+str_token+".");

            if(b_match)
              break;

            // => CHECK IF SEPERATOR
            b_match = false;
            for(i = 0; i < int_sep; i++)
              if( str_value.equals( String.valueOf(charA_sep[i]) ) )
              {
                b_match = true;
                break;
              } // if

            if(b_match)
              System.out.println("Skipping "+str_token+".");

            if(b_match)
              break;

            if(b_debug)
              System.out.println("ERROR: "+str_token+" was unrecognizable.");
            break;
        } // switch
      } // while
    } // try
    /* EXCEPTION HANDLING */
    catch(IOException exception)
    {
      System.out.println(" FATAL EXCEPTION: File input problem.");
      System.exit(-1);
    } // catch
 } // method parser
} // class Xref
