Home | History | Annotate | Download | only in runtime
      1 
      2 package java_cup.runtime;
      3 
      4 import java.util.Stack;
      5 
      6 /** This class implements a skeleton table driven LR parser.  In general,
      7  *  LR parsers are a form of bottom up shift-reduce parsers.  Shift-reduce
      8  *  parsers act by shifting input onto a parse stack until the symbols
      9  *  matching the right hand side of a production appear on the top of the
     10  *  stack.  Once this occurs, a reduce is performed.  This involves removing
     11  *  the symbols corresponding to the right hand side of the production
     12  *  (the so called "handle") and replacing them with the non-terminal from
     13  *  the left hand side of the production.  <p>
     14  *
     15  *  To control the decision of whether to shift or reduce at any given point,
     16  *  the parser uses a state machine (the "viable prefix recognition machine"
     17  *  built by the parser generator).  The current state of the machine is placed
     18  *  on top of the parse stack (stored as part of a symbol object representing
     19  *  a terminal or non terminal).  The parse action table is consulted
     20  *  (using the current state and the current lookahead token as indexes) to
     21  *  determine whether to shift or to reduce.  When the parser shifts, it
     22  *  changes to a new state by pushing a new symbol (containing a new state)
     23  *  onto the stack.  When the parser reduces, it pops the handle (right hand
     24  *  side of a production) off the stack.  This leaves the parser in the state
     25  *  it was in before any of those symbols were matched.  Next the reduce-goto
     26  *  table is consulted (using the new state and current lookahead token as
     27  *  indexes) to determine a new state to go to.  The parser then shifts to
     28  *  this goto state by pushing the left hand side symbol of the production
     29  *  (also containing the new state) onto the stack.<p>
     30  *
     31  *  This class actually provides four LR parsers.  The methods parse() and
     32  *  debug_parse() provide two versions of the main parser (the only difference
     33  *  being that debug_parse() emits debugging trace messages as it parses).
     34  *  In addition to these main parsers, the error recovery mechanism uses two
     35  *  more.  One of these is used to simulate "parsing ahead" in the input
     36  *  without carrying out actions (to verify that a potential error recovery
     37  *  has worked), and the other is used to parse through buffered "parse ahead"
     38  *  input in order to execute all actions and re-synchronize the actual parser
     39  *  configuration.<p>
     40  *
     41  *  This is an abstract class which is normally filled out by a subclass
     42  *  generated by the JavaCup parser generator.  In addition to supplying
     43  *  the actual parse tables, generated code also supplies methods which
     44  *  invoke various pieces of user supplied code, provide access to certain
     45  *  special symbols (e.g., EOF and error), etc.  Specifically, the following
     46  *  abstract methods are normally supplied by generated code:
     47  *  <dl compact>
     48  *  <dt> short[][] production_table()
     49  *  <dd> Provides a reference to the production table (indicating the index of
     50  *       the left hand side non terminal and the length of the right hand side
     51  *       for each production in the grammar).
     52  *  <dt> short[][] action_table()
     53  *  <dd> Provides a reference to the parse action table.
     54  *  <dt> short[][] reduce_table()
     55  *  <dd> Provides a reference to the reduce-goto table.
     56  *  <dt> int start_state()
     57  *  <dd> Indicates the index of the start state.
     58  *  <dt> int start_production()
     59  *  <dd> Indicates the index of the starting production.
     60  *  <dt> int EOF_sym()
     61  *  <dd> Indicates the index of the EOF symbol.
     62  *  <dt> int error_sym()
     63  *  <dd> Indicates the index of the error symbol.
     64  *  <dt> symbol do_action()
     65  *  <dd> Executes a piece of user supplied action code.  This always comes at
     66  *       the point of a reduce in the parse, so this code also allocates and
     67  *       fills in the left hand side non terminal symbol object that is to be
     68  *       pushed onto the stack for the reduce.
     69  *  <dt> void init_actions()
     70  *  <dd> Code to initialize a special object that encapsulates user supplied
     71  *       actions (this object is used by do_action() to actually carry out the
     72  *       actions).
     73  *  <dt> token scan()
     74  *  <dd> Used to get the next input token from the scanner.
     75  *  </dl>
     76  *
     77  *  In addition to these routines that <i>must</i> be supplied by the
     78  *  generated subclass there are also a series of routines that <i>may</i>
     79  *  be supplied.  These include:
     80  *  <dl>
     81  *  <dt> int error_sync_size()
     82  *  <dd> This determines how many tokens past the point of an error
     83  *       must be parsed without error in order to consider a recovery to
     84  *       be valid.  This defaults to 3.  Values less than 2 are not
     85  *       recommended.
     86  *  <dt> void report_error(String message, Object info)
     87  *  <dd> This method is called to report an error.  The default implementation
     88  *       simply prints a message to System.err and ignores its second parameter.
     89  *       This method is often replaced in order to provide a more sophisticated
     90  *       error reporting mechanism.
     91  *  <dt> void report_fatal_error(String message, Object info)
     92  *  <dd> This method is called when a fatal error that cannot be recovered from
     93  *       is encountered.  In the default implementation, it calls
     94  *       report_error() to emit a message, then throws an exception.
     95  *  <dt> void syntax_error(token cur_token)
     96  *  <dd> This method is called as soon as syntax error is detected (but
     97  *       before recovery is attempted).  In the default implementation it
     98  *       invokes: report_error("Syntax error", null);
     99  *  <dt> void unrecovered_syntax_error(token cur_token)
    100  *  <dd> This method is called if syntax error recovery fails.  In the default
    101  *       implementation it invokes:<br>
    102  *         report_fatal_error("Couldn't repair and continue parse", null);
    103  *  </dl>
    104  *
    105  * @see     java_cup.runtime.symbol
    106  * @see     java_cup.runtime.token
    107  * @see     java_cup.runtime.virtual_parse_stack
    108  * @version last updated: 11/25/95
    109  * @author  Scott Hudson
    110  */
    111 
    112 public abstract class lr_parser {
    113 
    114   /*-----------------------------------------------------------*/
    115   /*--- Constructor(s) ----------------------------------------*/
    116   /*-----------------------------------------------------------*/
    117 
    118   /** Simple constructor. */
    119   public lr_parser()
    120     {
    121       /* nothing to do here */
    122     }
    123 
    124   /*-----------------------------------------------------------*/
    125   /*--- (Access to) Static (Class) Variables ------------------*/
    126   /*-----------------------------------------------------------*/
    127 
    128   /** The default number of tokens after an error we much match to consider
    129    *  it recovered from.
    130    */
    131   protected final static int _error_sync_size = 3;
    132 
    133   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    134 
    135   /** The number of tokens after an error we much match to consider it
    136    *  recovered from.
    137    */
    138   protected int error_sync_size() {return _error_sync_size; }
    139 
    140   /*-----------------------------------------------------------*/
    141   /*--- (Access to) Instance Variables ------------------------*/
    142   /*-----------------------------------------------------------*/
    143 
    144   /** Table of production information (supplied by generated subclass).
    145    *  This table contains one entry per production and is indexed by
    146    *  the negative-encoded values (reduce actions) in the action_table.
    147    *  Each entry has two parts, the index of the non-terminal on the
    148    *  left hand side of the production, and the number of symbols
    149    *  on the right hand side.
    150    */
    151   public abstract short[][] production_table();
    152 
    153   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    154 
    155   /** The action table (supplied by generated subclass).  This table is
    156    *  indexed by state and terminal number indicating what action is to
    157    *  be taken when the parser is in the given state (i.e., the given state
    158    *  is on top of the stack) and the given terminal is next on the input.
    159    *  States are indexed using the first dimension, however, the entries for
    160    *  a given state are compacted and stored in adjacent index, value pairs
    161    *  which are searched for rather than accessed directly (see get_action()).
    162    *  The actions stored in the table will be either shifts, reduces, or
    163    *  errors.  Shifts are encoded as positive values (one greater than the
    164    *  state shifted to).  Reduces are encoded as negative values (one less
    165    *  than the production reduced by).  Error entries are denoted by zero.
    166    *
    167    * @see java_cup.runtime.lr_parser#get_action
    168    */
    169   public abstract short[][] action_table();
    170 
    171   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    172 
    173   /** The reduce-goto table (supplied by generated subclass).  This
    174    *  table is indexed by state and non-terminal number and contains
    175    *  state numbers.  States are indexed using the first dimension, however,
    176    *  the entries for a given state are compacted and stored in adjacent
    177    *  index, value pairs which are searched for rather than accessed
    178    *  directly (see get_reduce()).  When a reduce occurs, the handle
    179    *  (corresponding to the RHS of the matched production) is popped off
    180    *  the stack.  The new top of stack indicates a state.  This table is
    181    *  then indexed by that state and the LHS of the reducing production to
    182    *  indicate where to "shift" to.
    183    *
    184    * @see java_cup.runtime.lr_parser#get_reduce
    185    */
    186   public abstract short[][] reduce_table();
    187 
    188   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    189 
    190   /** The index of the start state (supplied by generated subclass). */
    191   public abstract int start_state();
    192 
    193   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    194 
    195   /** The index of the start production (supplied by generated subclass). */
    196   public abstract int start_production();
    197 
    198   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    199 
    200   /** The index of the end of file terminal symbol (supplied by generated
    201    *  subclass).
    202    */
    203   public abstract int EOF_sym();
    204 
    205   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    206 
    207   /** The index of the special error symbol (supplied by generated subclass). */
    208   public abstract int error_sym();
    209 
    210   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    211 
    212   /** Internal flag to indicate when parser should quit. */
    213   protected boolean _done_parsing = false;
    214 
    215   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    216 
    217   /** This method is called to indicate that the parser should quit.  This is
    218    *  normally called by an accept action, but can be used to cancel parsing
    219    *  early in other circumstances if desired.
    220    */
    221   public void done_parsing()
    222     {
    223       _done_parsing = true;
    224     }
    225 
    226   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    227   /* Global parse state shared by parse(), error recovery, and
    228    * debugging routines */
    229   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    230 
    231   /** Indication of the index for top of stack (for use by actions). */
    232   protected int tos;
    233 
    234   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    235 
    236   /** The current lookahead token. */
    237   protected token cur_token;
    238 
    239   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    240 
    241   /** The parse stack itself. */
    242   protected Stack stack = new Stack();
    243 
    244   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    245 
    246   /** Direct reference to the production table. */
    247   protected short[][] production_tab;
    248 
    249   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    250 
    251   /** Direct reference to the action table. */
    252   protected short[][] action_tab;
    253 
    254   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    255 
    256   /** Direct reference to the reduce-goto table. */
    257   protected short[][] reduce_tab;
    258 
    259   /*-----------------------------------------------------------*/
    260   /*--- General Methods ---------------------------------------*/
    261   /*-----------------------------------------------------------*/
    262 
    263   /** Perform a bit of user supplied action code (supplied by generated
    264    *  subclass).  Actions are indexed by an internal action number assigned
    265    *  at parser generation time.
    266    *
    267    * @param act_num   the internal index of the action to be performed.
    268    * @param parser    the parser object we are acting for.
    269    * @param stack     the parse stack of that object.
    270    * @param top       the index of the top element of the parse stack.
    271    */
    272   public abstract symbol do_action(
    273     int       act_num,
    274     lr_parser parser,
    275     Stack     stack,
    276     int       top)
    277     throws java.lang.Exception;
    278 
    279   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    280 
    281   /** User code for initialization inside the parser.  Typically this
    282    *  initializes the scanner.  This is called before the parser requests
    283    *  the first token.  Here this is just a placeholder for subclasses that
    284    *  might need this and we perform no action.   This method is normally
    285    *  overridden by the generated code using this contents of the "init with"
    286    *  clause as its body.
    287    */
    288   public void user_init() throws java.lang.Exception { }
    289 
    290   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    291 
    292   /** Initialize the action object.  This is called before the parser does
    293    *  any parse actions. This is filled in by generated code to create
    294    *  an object that encapsulates all action code.
    295    */
    296   protected abstract void init_actions() throws java.lang.Exception;
    297 
    298   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    299 
    300   /** Get the next token from the input (supplied by generated subclass).
    301    *  Once end of file has been reached, all subsequent calls to scan
    302    *  should return an EOF token (which is symbol number 0).  This method
    303    *  is supplied by the generator using using the code declared in the
    304    *  "scan with" clause.
    305    */
    306   public abstract token scan() throws java.lang.Exception;
    307 
    308   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    309 
    310   /** Report a fatal error.  This method takes a  message string and an
    311    *  additional object (to be used by specializations implemented in
    312    *  subclasses).  Here in the base class a very simple implementation
    313    *  is provided which reports the error then throws an exception.
    314    *
    315    * @param message an error message.
    316    * @param info    an extra object reserved for use by specialized subclasses.
    317    */
    318   public void report_fatal_error(
    319     String   message,
    320     Object   info)
    321     throws java.lang.Exception
    322     {
    323       /* stop parsing (not really necessary since we throw an exception, but) */
    324       done_parsing();
    325 
    326       /* use the normal error message reporting to put out the message */
    327       report_error(message, info);
    328 
    329       /* throw an exception */
    330       throw new Exception("Can't recover from previous error(s)");
    331     }
    332 
    333   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    334 
    335   /** Report a non fatal error (or warning).  This method takes a message
    336    *  string and an additional object (to be used by specializations
    337    *  implemented in subclasses).  Here in the base class a very simple
    338    *  implementation is provided which simply prints the message to
    339    *  System.err.
    340    *
    341    * @param message an error message.
    342    * @param info    an extra object reserved for use by specialized subclasses.
    343    */
    344   public void report_error(String message, Object info)
    345     {
    346       System.err.println(message);
    347     }
    348 
    349   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    350 
    351   /** This method is called when a syntax error has been detected and recovery
    352    *  is about to be invoked.  Here in the base class we just emit a
    353    *  "Syntax error" error message.
    354    *
    355    * @param cur_token the current lookahead token.
    356    */
    357   public void syntax_error(token cur_token)
    358     {
    359       report_error("Syntax error", null);
    360     }
    361 
    362   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    363 
    364   /** This method is called if it is determined that syntax error recovery
    365    *  has been unsuccessful.  Here in the base class we report a fatal error.
    366    *
    367    * @param cur_token the current lookahead token.
    368    */
    369   public void unrecovered_syntax_error(token cur_token)
    370     throws java.lang.Exception
    371     {
    372       report_fatal_error("Couldn't repair and continue parse", null);
    373     }
    374 
    375   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    376 
    377   /** Fetch an action from the action table.  The table is broken up into
    378    *  rows, one per state (rows are indexed directly by state number).
    379    *  Within each row, a list of index, value pairs are given (as sequential
    380    *  entries in the table), and the list is terminated by a default entry
    381    *  (denoted with a symbol index of -1).  To find the proper entry in a row
    382    *  we do a linear or binary search (depending on the size of the row).
    383    *
    384    * @param state the state index of the action being accessed.
    385    * @param sym   the symbol index of the action being accessed.
    386    */
    387   protected final short get_action(int state, int sym)
    388     {
    389       short tag;
    390       int first, last, probe;
    391       short[] row = action_tab[state];
    392 
    393       /* linear search if we are < 10 entries */
    394       if (row.length < 20)
    395         for (probe = 0; probe < row.length; probe++)
    396       {
    397         /* is this entry labeled with our symbol or the default? */
    398         tag = row[probe++];
    399         if (tag == sym || tag == -1)
    400           {
    401             /* return the next entry */
    402             return row[probe];
    403           }
    404       }
    405       /* otherwise binary search */
    406       else
    407     {
    408       first = 0;
    409       last = (row.length-1)/2 - 1;  /* leave out trailing default entry */
    410       while (first <= last)
    411         {
    412           probe = (first+last)/2;
    413           if (sym == row[probe*2])
    414         return row[probe*2+1];
    415           else if (sym > row[probe*2])
    416         first = probe+1;
    417           else
    418             last = probe-1;
    419         }
    420 
    421       /* not found, use the default at the end */
    422       return row[row.length-1];
    423     }
    424 
    425       /* shouldn't happened, but if we run off the end we return the
    426      default (error == 0) */
    427       return 0;
    428     }
    429 
    430   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    431 
    432   /** Fetch a state from the reduce-goto table.  The table is broken up into
    433    *  rows, one per state (rows are indexed directly by state number).
    434    *  Within each row, a list of index, value pairs are given (as sequential
    435    *  entries in the table), and the list is terminated by a default entry
    436    *  (denoted with a symbol index of -1).  To find the proper entry in a row
    437    *  we do a linear search.
    438    *
    439    * @param state the state index of the entry being accessed.
    440    * @param sym   the symbol index of the entry being accessed.
    441    */
    442   protected final short get_reduce(int state, int sym)
    443     {
    444       short tag;
    445       short[] row = reduce_tab[state];
    446 
    447       /* if we have a null row we go with the default */
    448       if (row == null)
    449         return -1;
    450 
    451       for (int probe = 0; probe < row.length; probe++)
    452     {
    453       /* is this entry labeled with our symbol or the default? */
    454       tag = row[probe++];
    455       if (tag == sym || tag == -1)
    456         {
    457           /* return the next entry */
    458           return row[probe];
    459         }
    460     }
    461       /* if we run off the end we return the default (error == -1) */
    462       return -1;
    463     }
    464 
    465   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    466 
    467   /** This method provides the main parsing routine.  It returns only when
    468    *  done_parsing() has been called (typically because the parser has
    469    *  accepted, or a fatal error has been reported).  See the header
    470    *  documentation for the class regarding how shift/reduce parsers operate
    471    *  and how the various tables are used.
    472    */
    473   public void parse() throws java.lang.Exception
    474     {
    475       /* the current action code */
    476       int act;
    477 
    478       /* the symbol/stack element returned by a reduce */
    479       symbol lhs_sym;
    480 
    481       /* information about production being reduced with */
    482       short handle_size, lhs_sym_num;
    483 
    484       /* set up direct reference to tables to drive the parser */
    485 
    486       production_tab = production_table();
    487       action_tab     = action_table();
    488       reduce_tab     = reduce_table();
    489 
    490       /* initialize the action encapsulation object */
    491       init_actions();
    492 
    493       /* do user initialization */
    494       user_init();
    495 
    496       /* get the first token */
    497       cur_token = scan();
    498 
    499       /* push dummy symbol with start state to get us underway */
    500       stack.push(new symbol(0, start_state()));
    501       tos = 0;
    502 
    503       /* continue until we are told to stop */
    504       for (_done_parsing = false; !_done_parsing; )
    505     {
    506       /* current state is always on the top of the stack */
    507 
    508       /* look up action out of the current state with the current input */
    509       act = get_action(((symbol)stack.peek()).parse_state, cur_token.sym);
    510 
    511       /* decode the action -- > 0 encodes shift */
    512       if (act > 0)
    513         {
    514           /* shift to the encoded state by pushing it on the stack */
    515           cur_token.parse_state = act-1;
    516           stack.push(cur_token);
    517           tos++;
    518 
    519           /* advance to the next token */
    520           cur_token = scan();
    521         }
    522       /* if its less than zero, then it encodes a reduce action */
    523       else if (act < 0)
    524         {
    525           /* perform the action for the reduce */
    526           lhs_sym = do_action((-act)-1, this, stack, tos);
    527 
    528           /* look up information about the production */
    529           lhs_sym_num = production_tab[(-act)-1][0];
    530           handle_size = production_tab[(-act)-1][1];
    531 
    532           /* pop the handle off the stack */
    533           for (int i = 0; i < handle_size; i++)
    534         {
    535           stack.pop();
    536           tos--;
    537         }
    538 
    539           /* look up the state to go to from the one popped back to */
    540           act = get_reduce(((symbol)stack.peek()).parse_state, lhs_sym_num);
    541 
    542           /* shift to that state */
    543           lhs_sym.parse_state = act;
    544           stack.push(lhs_sym);
    545           tos++;
    546         }
    547       /* finally if the entry is zero, we have an error */
    548       else if (act == 0)
    549         {
    550           /* call user syntax error reporting routine */
    551           syntax_error(cur_token);
    552 
    553           /* try to error recover */
    554           if (!error_recovery(false))
    555         {
    556           /* if that fails give up with a fatal syntax error */
    557           unrecovered_syntax_error(cur_token);
    558 
    559           /* just in case that wasn't fatal enough, end parse */
    560           done_parsing();
    561         }
    562         }
    563     }
    564     }
    565 
    566   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    567 
    568   /** Write a debugging message to System.err for the debugging version
    569    *  of the parser.
    570    *
    571    * @param mess the text of the debugging message.
    572    */
    573   public void debug_message(String mess)
    574     {
    575       System.err.println(mess);
    576     }
    577 
    578   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    579 
    580   /** Dump the parse stack for debugging purposes. */
    581   public void dump_stack()
    582     {
    583       if (stack == null)
    584     {
    585       debug_message("# Stack dump requested, but stack is null");
    586       return;
    587     }
    588 
    589       debug_message("============ Parse Stack Dump ============");
    590 
    591       /* dump the stack */
    592       for (int i=0; i<stack.size(); i++)
    593     {
    594       debug_message("Symbol: " + ((symbol)stack.elementAt(i)).sym +
    595             " State: " + ((symbol)stack.elementAt(i)).parse_state);
    596     }
    597       debug_message("==========================================");
    598     }
    599 
    600   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    601 
    602   /** Do debug output for a reduce.
    603    *
    604    * @param prod_num  the production we are reducing with.
    605    * @param nt_num    the index of the LHS non terminal.
    606    * @param rhs_size  the size of the RHS.
    607    */
    608   public void debug_reduce(int prod_num, int nt_num, int rhs_size)
    609     {
    610       debug_message("# Reduce with prod #" + prod_num + " [NT=" + nt_num +
    611                 ", " + "SZ=" + rhs_size + "]");
    612     }
    613 
    614   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    615 
    616   /** Do debug output for shift.
    617    *
    618    * @param shift_tkn the token being shifted onto the stack.
    619    */
    620   public void debug_shift(token shift_tkn)
    621     {
    622       debug_message("# Shift under term #" + shift_tkn.sym +
    623             " to state #" + shift_tkn.parse_state);
    624     }
    625 
    626   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    627 
    628   /** Perform a parse with debugging output.  This does exactly the
    629    *  same things as parse(), except that it calls debug_shift() and
    630    *  debug_reduce() when shift and reduce moves are taken by the parser
    631    *  and produces various other debugging messages.
    632    */
    633   public void debug_parse()
    634     throws java.lang.Exception
    635     {
    636       /* the current action code */
    637       int act;
    638 
    639       /* the symbol/stack element returned by a reduce */
    640       symbol lhs_sym;
    641 
    642       /* information about production being reduced with */
    643       short handle_size, lhs_sym_num;
    644 
    645       /* set up direct reference to tables to drive the parser */
    646       production_tab = production_table();
    647       action_tab     = action_table();
    648       reduce_tab     = reduce_table();
    649 
    650       debug_message("# Initializing parser");
    651 
    652       /* initialize the action encapsulation object */
    653       init_actions();
    654 
    655       /* do user initialization */
    656       user_init();
    657 
    658       /* the current token */
    659       cur_token = scan();
    660 
    661       debug_message("# Current token is #" + cur_token.sym);
    662 
    663       /* push dummy symbol with start state to get us underway */
    664       stack.push(new symbol(0, start_state()));
    665       tos = 0;
    666 
    667       /* continue until we are told to stop */
    668       for (_done_parsing = false; !_done_parsing; )
    669     {
    670       /* current state is always on the top of the stack */
    671 
    672       /* look up action out of the current state with the current input */
    673       act = get_action(((symbol)stack.peek()).parse_state, cur_token.sym);
    674 
    675       /* decode the action -- > 0 encodes shift */
    676       if (act > 0)
    677         {
    678           /* shift to the encoded state by pushing it on the stack */
    679           cur_token.parse_state = act-1;
    680           debug_shift(cur_token);
    681           stack.push(cur_token);
    682           tos++;
    683 
    684           /* advance to the next token */
    685           cur_token = scan();
    686               debug_message("# Current token is #" + cur_token.sym);
    687         }
    688       /* if its less than zero, then it encodes a reduce action */
    689       else if (act < 0)
    690         {
    691           /* perform the action for the reduce */
    692           lhs_sym = do_action((-act)-1, this, stack, tos);
    693 
    694           /* look up information about the production */
    695           lhs_sym_num = production_tab[(-act)-1][0];
    696           handle_size = production_tab[(-act)-1][1];
    697 
    698           debug_reduce((-act)-1, lhs_sym_num, handle_size);
    699 
    700           /* pop the handle off the stack */
    701           for (int i = 0; i < handle_size; i++)
    702         {
    703           stack.pop();
    704           tos--;
    705         }
    706 
    707           /* look up the state to go to from the one popped back to */
    708           act = get_reduce(((symbol)stack.peek()).parse_state, lhs_sym_num);
    709 
    710           /* shift to that state */
    711           lhs_sym.parse_state = act;
    712           stack.push(lhs_sym);
    713           tos++;
    714 
    715           debug_message("# Goto state #" + act);
    716         }
    717       /* finally if the entry is zero, we have an error */
    718       else if (act == 0)
    719         {
    720           /* call user syntax error reporting routine */
    721           syntax_error(cur_token);
    722 
    723           /* try to error recover */
    724           if (!error_recovery(true))
    725         {
    726           /* if that fails give up with a fatal syntax error */
    727           unrecovered_syntax_error(cur_token);
    728 
    729           /* just in case that wasn't fatal enough, end parse */
    730           done_parsing();
    731         }
    732         }
    733     }
    734     }
    735 
    736   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    737   /* Error recovery code */
    738   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    739 
    740   /** Attempt to recover from a syntax error.  This returns false if recovery
    741    *  fails, true if it succeeds.  Recovery happens in 4 steps.  First we
    742    *  pop the parse stack down to a point at which we have a shift out
    743    *  of the top-most state on the error symbol.  This represents the
    744    *  initial error recovery configuration.  If no such configuration is
    745    *  found, then we fail.  Next a small number of "lookahead" or "parse
    746    *  ahead" tokens are read into a buffer.  The size of this buffer is
    747    *  determined by error_sync_size() and determines how many tokens beyond
    748    *  the error must be matched to consider the recovery a success.  Next,
    749    *  we begin to discard tokens in attempt to get past the point of error
    750    *  to a point where we can continue parsing.  After each token, we attempt
    751    *  to "parse ahead" though the buffered lookahead tokens.  The "parse ahead"
    752    *  process simulates that actual parse, but does not modify the real
    753    *  parser's configuration, nor execute any actions. If we can  parse all
    754    *  the stored tokens without error, then the recovery is considered a
    755    *  success.  Once a successful recovery point is determined, we do an
    756    *  actual parse over the stored input -- modifying the real parse
    757    *  configuration and executing all actions.  Finally, we return the the
    758    *  normal parser to continue with the overall parse.
    759    *
    760    * @param debug should we produce debugging messages as we parse.
    761    */
    762   protected boolean error_recovery(boolean debug)
    763     throws java.lang.Exception
    764     {
    765       if (debug) debug_message("# Attempting error recovery");
    766 
    767       /* first pop the stack back into a state that can shift on error and
    768      do that shift (if that fails, we fail) */
    769       if (!find_recovery_config(debug))
    770     {
    771       if (debug) debug_message("# Error recovery fails");
    772       return false;
    773     }
    774 
    775       /* read ahead to create lookahead we can parse multiple times */
    776       read_lookahead();
    777 
    778       /* repeatedly try to parse forward until we make it the required dist */
    779       for (;;)
    780     {
    781       /* try to parse forward, if it makes it, bail out of loop */
    782       if (debug) debug_message("# Trying to parse ahead");
    783       if (try_parse_ahead(debug))
    784         {
    785           break;
    786         }
    787 
    788       /* if we are now at EOF, we have failed */
    789       if (lookahead[0].sym == EOF_sym())
    790         {
    791           if (debug) debug_message("# Error recovery fails at EOF");
    792           return false;
    793         }
    794 
    795       /* otherwise, we consume another token and try again */
    796       if (debug)
    797       debug_message("# Consuming token #" + cur_err_token().sym);
    798       restart_lookahead();
    799     }
    800 
    801       /* we have consumed to a point where we can parse forward */
    802       if (debug) debug_message("# Parse-ahead ok, going back to normal parse");
    803 
    804       /* do the real parse (including actions) across the lookahead */
    805       parse_lookahead(debug);
    806 
    807       /* we have success */
    808       return true;
    809     }
    810 
    811   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    812 
    813   /** Determine if we can shift under the special error symbol out of the
    814    *  state currently on the top of the (real) parse stack.
    815    */
    816   protected boolean shift_under_error()
    817     {
    818       /* is there a shift under error symbol */
    819       return get_action(((symbol)stack.peek()).parse_state, error_sym()) > 0;
    820     }
    821 
    822   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    823 
    824   /** Put the (real) parse stack into error recovery configuration by
    825    *  popping the stack down to a state that can shift on the special
    826    *  error symbol, then doing the shift.  If no suitable state exists on
    827    *  the stack we return false
    828    *
    829    * @param debug should we produce debugging messages as we parse.
    830    */
    831   protected boolean find_recovery_config(boolean debug)
    832     {
    833       token error_token;
    834       int act;
    835 
    836       if (debug) debug_message("# Finding recovery state on stack");
    837 
    838       /* pop down until we can shift under error token */
    839       while (!shift_under_error())
    840     {
    841       /* pop the stack */
    842       if (debug)
    843         debug_message("# Pop stack by one, state was # " +
    844                       ((symbol)stack.peek()).parse_state);
    845           stack.pop();
    846       tos--;
    847 
    848       /* if we have hit bottom, we fail */
    849       if (stack.empty())
    850         {
    851           if (debug) debug_message("# No recovery state found on stack");
    852           return false;
    853         }
    854     }
    855 
    856       /* state on top of the stack can shift under error, find the shift */
    857       act = get_action(((symbol)stack.peek()).parse_state, error_sym());
    858       if (debug)
    859     {
    860       debug_message("# Recover state found (#" +
    861             ((symbol)stack.peek()).parse_state + ")");
    862       debug_message("# Shifting on error to state #" + (act-1));
    863     }
    864 
    865       /* build and shift a special error token */
    866       error_token = new token(error_sym());
    867       error_token.parse_state = act-1;
    868       stack.push(error_token);
    869       tos++;
    870 
    871       return true;
    872     }
    873 
    874   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    875 
    876   /** Lookahead tokens used for attempting error recovery "parse aheads". */
    877   protected token lookahead[];
    878 
    879   /** Position in lookahead input buffer used for "parse ahead". */
    880   protected int lookahead_pos;
    881 
    882   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    883 
    884   /** Read from input to establish our buffer of "parse ahead" lookahead
    885    *  symbols.
    886    */
    887   protected void read_lookahead() throws java.lang.Exception
    888     {
    889       /* create the lookahead array */
    890       lookahead = new token[error_sync_size()];
    891 
    892       /* fill in the array */
    893       for (int i = 0; i < error_sync_size(); i++)
    894     {
    895       lookahead[i] = cur_token;
    896       cur_token = scan();
    897     }
    898 
    899       /* start at the beginning */
    900       lookahead_pos = 0;
    901     }
    902 
    903   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    904 
    905   /** Return the current lookahead in our error "parse ahead" buffer. */
    906   protected token cur_err_token() { return lookahead[lookahead_pos]; }
    907 
    908   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    909 
    910   /** Advance to next "parse ahead" input symbol. Return true if we have
    911    *  input to advance to, false otherwise.
    912    */
    913   protected boolean advance_lookahead()
    914     {
    915       /* advance the input location */
    916       lookahead_pos++;
    917 
    918       /* return true if we didn't go off the end */
    919       return lookahead_pos < error_sync_size();
    920     }
    921 
    922   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    923 
    924   /** Reset the parse ahead input to one token past where we started error
    925    *  recovery (this consumes one new token from the real input).
    926    */
    927   protected void restart_lookahead() throws java.lang.Exception
    928     {
    929       /* move all the existing input over */
    930       for (int i = 1; i < error_sync_size(); i++)
    931     lookahead[i-1] = lookahead[i];
    932 
    933       /* read a new token into the last spot */
    934       cur_token = scan();
    935       lookahead[error_sync_size()-1] = cur_token;
    936 
    937       /* reset our internal position marker */
    938       lookahead_pos = 0;
    939     }
    940 
    941   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    942 
    943   /** Do a simulated parse forward (a "parse ahead") from the current
    944    *  stack configuration using stored lookahead input and a virtual parse
    945    *  stack.  Return true if we make it all the way through the stored
    946    *  lookahead input without error. This basically simulates the action of
    947    *  parse() using only our saved "parse ahead" input, and not executing any
    948    *  actions.
    949    *
    950    * @param debug should we produce debugging messages as we parse.
    951    */
    952   protected boolean try_parse_ahead(boolean debug)
    953     throws java.lang.Exception
    954     {
    955       int act;
    956       short lhs, rhs_size;
    957 
    958       /* create a virtual stack from the real parse stack */
    959       virtual_parse_stack vstack = new virtual_parse_stack(stack);
    960 
    961       /* parse until we fail or get past the lookahead input */
    962       for (;;)
    963     {
    964       /* look up the action from the current state (on top of stack) */
    965       act = get_action(vstack.top(), cur_err_token().sym);
    966 
    967       /* if its an error, we fail */
    968       if (act == 0) return false;
    969 
    970       /* > 0 encodes a shift */
    971       if (act > 0)
    972         {
    973           /* push the new state on the stack */
    974           vstack.push(act-1);
    975 
    976           if (debug) debug_message("# Parse-ahead shifts token #" +
    977                cur_err_token().sym + " into state #" + (act-1));
    978 
    979           /* advance simulated input, if we run off the end, we are done */
    980           if (!advance_lookahead()) return true;
    981         }
    982       /* < 0 encodes a reduce */
    983       else
    984         {
    985           /* if this is a reduce with the start production we are done */
    986           if ((-act)-1 == start_production())
    987         {
    988           if (debug) debug_message("# Parse-ahead accepts");
    989           return true;
    990         }
    991 
    992           /* get the lhs symbol and the rhs size */
    993           lhs = production_tab[(-act)-1][0];
    994           rhs_size = production_tab[(-act)-1][1];
    995 
    996           /* pop handle off the stack */
    997           for (int i = 0; i < rhs_size; i++)
    998         vstack.pop();
    999 
   1000           if (debug)
   1001         debug_message("# Parse-ahead reduces: handle size = " +
   1002               rhs_size + " lhs = #" + lhs + " from state #" + vstack.top());
   1003 
   1004           /* look up goto and push it onto the stack */
   1005           vstack.push(get_reduce(vstack.top(), lhs));
   1006           if (debug)
   1007         debug_message("# Goto state #" + vstack.top());
   1008         }
   1009     }
   1010     }
   1011 
   1012   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
   1013 
   1014   /** Parse forward using stored lookahead symbols.  In this case we have
   1015    *  already verified that parsing will make it through the stored lookahead
   1016    *  symbols and we are now getting back to the point at which we can hand
   1017    *  control back to the normal parser.  Consequently, this version of the
   1018    *  parser performs all actions and modifies the real parse configuration.
   1019    *  This returns once we have consumed all the stored input or we accept.
   1020    *
   1021    * @param debug should we produce debugging messages as we parse.
   1022    */
   1023   protected void parse_lookahead(boolean debug)
   1024     throws java.lang.Exception
   1025     {
   1026       /* the current action code */
   1027       int act;
   1028 
   1029       /* the symbol/stack element returned by a reduce */
   1030       symbol lhs_sym;
   1031 
   1032       /* information about production being reduced with */
   1033       short handle_size, lhs_sym_num;
   1034 
   1035       /* restart the saved input at the beginning */
   1036       lookahead_pos = 0;
   1037 
   1038       if (debug)
   1039     {
   1040       debug_message("# Reparsing saved input with actions");
   1041       debug_message("# Current token is #" + cur_err_token().sym);
   1042       debug_message("# Current state is #" +
   1043             ((symbol)stack.peek()).parse_state);
   1044     }
   1045 
   1046       /* continue until we accept or have read all lookahead input */
   1047       while(!_done_parsing)
   1048     {
   1049       /* current state is always on the top of the stack */
   1050 
   1051       /* look up action out of the current state with the current input */
   1052       act =
   1053         get_action(((symbol)stack.peek()).parse_state, cur_err_token().sym);
   1054 
   1055       /* decode the action -- > 0 encodes shift */
   1056       if (act > 0)
   1057         {
   1058           /* shift to the encoded state by pushing it on the stack */
   1059           cur_err_token().parse_state = act-1;
   1060           if (debug) debug_shift(cur_err_token());
   1061           stack.push(cur_err_token());
   1062           tos++;
   1063 
   1064           /* advance to the next token, if there is none, we are done */
   1065           if (!advance_lookahead())
   1066         {
   1067           if (debug) debug_message("# Completed reparse");
   1068 
   1069           /* scan next token so we can continue parse */
   1070           cur_token = scan();
   1071 
   1072           /* go back to normal parser */
   1073           return;
   1074         }
   1075 
   1076           if (debug)
   1077         debug_message("# Current token is #" + cur_err_token().sym);
   1078         }
   1079       /* if its less than zero, then it encodes a reduce action */
   1080       else if (act < 0)
   1081         {
   1082           /* perform the action for the reduce */
   1083           lhs_sym = do_action((-act)-1, this, stack, tos);
   1084 
   1085           /* look up information about the production */
   1086           lhs_sym_num = production_tab[(-act)-1][0];
   1087           handle_size = production_tab[(-act)-1][1];
   1088 
   1089           if (debug) debug_reduce((-act)-1, lhs_sym_num, handle_size);
   1090 
   1091           /* pop the handle off the stack */
   1092           for (int i = 0; i < handle_size; i++)
   1093         {
   1094           stack.pop();
   1095           tos--;
   1096         }
   1097 
   1098           /* look up the state to go to from the one popped back to */
   1099           act = get_reduce(((symbol)stack.peek()).parse_state, lhs_sym_num);
   1100 
   1101           /* shift to that state */
   1102           lhs_sym.parse_state = act;
   1103           stack.push(lhs_sym);
   1104           tos++;
   1105 
   1106           if (debug) debug_message("# Goto state #" + act);
   1107 
   1108         }
   1109       /* finally if the entry is zero, we have an error
   1110          (shouldn't happen here, but...)*/
   1111       else if (act == 0)
   1112         {
   1113           report_fatal_error("Syntax error", null);
   1114           return;
   1115         }
   1116     }
   1117     }
   1118 
   1119   /*-----------------------------------------------------------*/
   1120 
   1121 };
   1122