rajan@rti.UUCP (Sundar Varadarajan) (08/03/87)
Hi,
There seem to be two problems with the way yacc handles errors.
(1) If, in a state the action on error is to shift, but the default action
is to reduce, then yacc will reduce, rather than shift, on error. (See
"Introduction to Compiler Construction with UNIX" by Axel T. Schreiner
and H. George Friedman Jr. Chapter 4, page 71 for a full explanation).
(2) If, in a state the action on error is to reduce by a rule but the
default action is to reduce by another rule, then yacc will reduce by
the latter rather than by the former(on error).
The fixes for the two problems are as follows. If in a state there is a
shift on the special terminal "error", then make the default action the error
action. That is, yacc recognizes the input as being in error by default. For
the second problem, if there is a reduce on error, then make that the default
action.
This is done by modifying the code in y3.c in the yacc source as fol-
lows.
288c296
< if( temp1[chfind(2,"error")] > 0 ) lastred = 0;
---
> if( temp1[1] > 0 ) lastred = 0;
290,293d297
< /* for error recovery, arrange that, if there is a reduce on the */
< /* error recovery token, `error', the default be that reduction */
< if( temp1[chfind(2,"error")] < 0 ) lastred = -temp1[chfind(2,"error")];
<
(This is extracted by "diff newy3.c y3.c". Furthermore, the line numbers are
likely to be slightly off).
Another yacc bug. Yacc sometimes gets confused with the type (of the
value on the value stack) of a terminal. If you have more than 64 different
types attached to non-terminals and if you declare the type of the non-
terminals before the type of the terminals (with the "%type <...>" and
"%token <...>" declarations), yacc will get confused about the type of the
terminals. Always declare the type of the terminals first and then the non-
terminals.
Sundar