| |
| package java_cup; |
| |
| import java.util.Enumeration; |
| |
| /** 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; |
| production prod; |
| |
| /* tabulate reductions -- look at every table entry */ |
| for (int row = 0; row < num_states(); row++) |
| { |
| for (int col = 0; col < under_state[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 (Enumeration p = production.all(); p.hasMoreElements(); ) |
| { |
| prod = (production)p.nextElement(); |
| |
| /* 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) |
| { |
| System.err.println("*** Production \"" + |
| prod.to_simple_string() + "\" never reduced"); |
| lexer.warning_count++; |
| } |
| } |
| } |
| } |
| |
| /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .* |
| |
| /** Convert to a string. */ |
| 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 < under_state[row].size(); col++) |
| { |
| /* if the action is not an error print it */ |
| if (under_state[row].under_term[col].kind() != parse_action.ERROR) |
| { |
| result += col + ":" + under_state[row].under_term[col] + " "; |
| |
| /* end the line after the 3rd one */ |
| cnt++; |
| if (cnt == 3) |
| { |
| result += "\n"; |
| cnt = 0; |
| } |
| } |
| } |
| /* finish the line if we haven't just done that */ |
| if (cnt != 0) result += "\n"; |
| } |
| result += "------------------------------"; |
| |
| return result; |
| } |
| |
| /*-----------------------------------------------------------*/ |
| |
| }; |
| |