
package java_cup;

/**
 * This class represents the complete "action" table of the parser. It has one
 * row for each state in the parse machine, and a column for each terminal
 * symbol. Each entry in the table represents a shift, reduce, or an error.
 *
 * @see java_cup.parse_action
 * @see java_cup.parse_action_row
 * @version last updated: 11/25/95
 * @author Scott Hudson
 */
public class parse_action_table {

  /*-----------------------------------------------------------*/
  /*--- Constructor(s) ----------------------------------------*/
  /*-----------------------------------------------------------*/

  /**
   * Simple constructor. All terminals, non-terminals, and productions must
   * already have been entered, and the viable prefix recognizer should have been
   * constructed before this is called.
   */
  public parse_action_table() {
    /* determine how many states we are working with */
    _num_states = lalr_state.number();

    /* allocate the array and fill it in with empty rows */
    under_state = new parse_action_row[_num_states];
    for (int i = 0; i < _num_states; i++)
      under_state[i] = new parse_action_row();
  }

  /*-----------------------------------------------------------*/
  /*--- (Access to) Instance Variables ------------------------*/
  /*-----------------------------------------------------------*/

  /** How many rows/states are in the machine/table. */
  protected int _num_states;

  /** How many rows/states are in the machine/table. */
  public int num_states() {
    return _num_states;
  }

  /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

  /** Actual array of rows, one per state. */
  public parse_action_row[] under_state;

  /*-----------------------------------------------------------*/
  /*--- General Methods ---------------------------------------*/
  /*-----------------------------------------------------------*/

  /**
   * Check the table to ensure that all productions have been reduced. Issue a
   * warning message (to System.err) for each production that is never reduced.
   */
  public void check_reductions() throws internal_error {
    parse_action act;

    /* tabulate reductions -- look at every table entry */
    for (int row = 0; row < num_states(); row++) {
      for (int col = 0; col < parse_action_row.size(); col++) {
        /* look at the action entry to see if its a reduce */
        act = under_state[row].under_term[col];
        if (act != null && act.kind() == parse_action.REDUCE) {
          /* tell production that we used it */
          ((reduce_action) act).reduce_with().note_reduction_use();
        }
      }
    }

    /* now go across every production and make sure we hit it */
    for (var prod : production.all()){
      /* if we didn't hit it give a warning */
      if (prod.num_reductions() == 0) {
        /*
         * count it * emit.not_reduced++;
         * 
         * /* give a warning if they haven't been turned off
         */
        if (!emit.nowarn) {

          ErrorManager.getManager().emit_warning("*** Production \"" + prod.to_simple_string() + "\" never reduced");
        }
      }
    }
  }

  /*
   * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*
   * 
   * /** Convert to a string.
   */
  @Override
  public String toString() {
    String result;
    int cnt;

    result = "-------- ACTION_TABLE --------\n";
    for (int row = 0; row < num_states(); row++) {
      result += "From state #" + row + "\n";
      cnt = 0;
      for (int col = 0; col < parse_action_row.size(); col++) {
        /* if the action is not an error print it */
        if (under_state[row].under_term[col].kind() != parse_action.ERROR) {
          result += " [term " + col + ":" + under_state[row].under_term[col] + "]";

          /* end the line after the 2nd one */
          cnt++;
          if (cnt == 2) {
            result += "\n";
            cnt = 0;
          }
        }
      }
      /* finish the line if we haven't just done that */
      if (cnt != 0)
        result += "\n";
    }
    result += "------------------------------";

    return result;
  }

  /*-----------------------------------------------------------*/

}
