001: package java_cup;
002:
003: import java.util.Enumeration;
004:
005: /** This class represents the complete "action" table of the parser.
006: * It has one row for each state in the parse machine, and a column for
007: * each terminal symbol. Each entry in the table represents a shift,
008: * reduce, or an error.
009: *
010: * @see java_cup.parse_action
011: * @see java_cup.parse_action_row
012: * @version last updated: 11/25/95
013: * @author Scott Hudson
014: */
015: public class parse_action_table {
016:
017: /*-----------------------------------------------------------*/
018: /*--- Constructor(s) ----------------------------------------*/
019: /*-----------------------------------------------------------*/
020:
021: /** Simple constructor. All terminals, non-terminals, and productions must
022: * already have been entered, and the viable prefix recognizer should
023: * have been constructed before this is called.
024: */
025: public parse_action_table() {
026: /* determine how many states we are working with */
027: _num_states = lalr_state.number();
028:
029: /* allocate the array and fill it in with empty rows */
030: under_state = new parse_action_row[_num_states];
031: for (int i = 0; i < _num_states; i++)
032: under_state[i] = new parse_action_row();
033: }
034:
035: /*-----------------------------------------------------------*/
036: /*--- (Access to) Instance Variables ------------------------*/
037: /*-----------------------------------------------------------*/
038:
039: /** How many rows/states are in the machine/table. */
040: protected int _num_states;
041:
042: /** How many rows/states are in the machine/table. */
043: public int num_states() {
044: return _num_states;
045: }
046:
047: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
048:
049: /** Actual array of rows, one per state. */
050: public parse_action_row[] under_state;
051:
052: /*-----------------------------------------------------------*/
053: /*--- General Methods ---------------------------------------*/
054: /*-----------------------------------------------------------*/
055:
056: /** Check the table to ensure that all productions have been reduced.
057: * Issue a warning message (to System.err) for each production that
058: * is never reduced.
059: */
060: public void check_reductions() throws internal_error {
061: parse_action act;
062: production prod;
063:
064: /* tabulate reductions -- look at every table entry */
065: for (int row = 0; row < num_states(); row++) {
066: for (int col = 0; col < parse_action_row.size(); col++) {
067: /* look at the action entry to see if its a reduce */
068: act = under_state[row].under_term[col];
069: if (act != null && act.kind() == parse_action.REDUCE) {
070: /* tell production that we used it */
071: ((reduce_action) act).reduce_with()
072: .note_reduction_use();
073: }
074: }
075: }
076:
077: /* now go across every production and make sure we hit it */
078: for (Enumeration p = production.all(); p.hasMoreElements();) {
079: prod = (production) p.nextElement();
080:
081: /* if we didn't hit it give a warning */
082: if (prod.num_reductions() == 0) {
083: /* count it *
084: emit.not_reduced++;
085:
086: /* give a warning if they haven't been turned off */
087: if (!emit.nowarn) {
088:
089: ErrorManager.getManager().emit_warning(
090: "*** Production \""
091: + prod.to_simple_string()
092: + "\" never reduced");
093: }
094: }
095: }
096: }
097:
098: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*
099:
100: /** Convert to a string. */
101: public String toString() {
102: String result;
103: int cnt;
104:
105: result = "-------- ACTION_TABLE --------\n";
106: for (int row = 0; row < num_states(); row++) {
107: result += "From state #" + row + "\n";
108: cnt = 0;
109: for (int col = 0; col < parse_action_row.size(); col++) {
110: /* if the action is not an error print it */
111: if (under_state[row].under_term[col].kind() != parse_action.ERROR) {
112: result += " [term " + col + ":"
113: + under_state[row].under_term[col] + "]";
114:
115: /* end the line after the 2nd one */
116: cnt++;
117: if (cnt == 2) {
118: result += "\n";
119: cnt = 0;
120: }
121: }
122: }
123: /* finish the line if we haven't just done that */
124: if (cnt != 0)
125: result += "\n";
126: }
127: result += "------------------------------";
128:
129: return result;
130: }
131:
132: /*-----------------------------------------------------------*/
133:
134: }
|