xref: /original-bsd/usr.bin/pascal/src/yyrecover.c (revision 0b685140)
1 /* Copyright (c) 1979 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)yyrecover.c 1.2 03/08/81";
4 
5 #include "whoami.h"
6 #include "0.h"
7 #include "yy.h"
8 
9 /*
10  * Very simplified version of Graham-Rhodes error recovery
11  * method for LALR parsers.  Backward move is embodied in
12  * default reductions of the yacc parser until an error condition
13  * is reached.  Forward move is over a small number of input tokens
14  * and cannot "condense".  The basic corrections are:
15  *
16  *	1) Delete the input token.
17  *
18  *	2) Replace the current input with a legal input.
19  *
20  *	3) Insert a legal token.
21  *
22  * All corrections are weighted, considered only if they allow
23  * at least two shifts, and the cost of a correction increases if
24  * it allows shifting over only a part of the lookahead.
25  *
26  * Another error situation is that which occurs when an identifier "fails"
27  * a reduction because it is not the required "class".
28  * In this case, we also consider replacing this identifier, which has
29  * already been shifted over, with an identifier of the correct class.
30  *
31  * Another correction performed here is unique symbol insertion.
32  * If the current state admits only one input, and no other alternative
33  * correction presents itself, then that symbol will be inserted.
34  * There is a danger in this of looping, and it is handled
35  * by counting true shifts over input (see below).
36  *
37  *
38  * A final class of corrections, considered only when the error
39  * occurred immediately after a shift over a terminal, involves
40  * the three basic corrections above, but with the point of error
41  * considered to be before this terminal was shifted over, effectively
42  * "unreading" this terminal.  This is a feeble attempt at elimination
43  * of the left-right bias and because "if" has a low weight and some
44  * statements are quite simple i.e.
45  *
46  *	cse ch of ...
47  *
48  * we can get a small number of errors.  The major deficiency of
49  * this is that we back up only one token, and that the forward
50  * move is over a small number of tokens, often not enough to really
51  * tell what the input should be, e.g. in
52  *
53  *	a[i] > a[i - 1] ...
54  *
55  * In such cases a bad identifier (misspelled keyword) or omitted
56  * keyword will be change or inserted as "if" as it has the lowest cost.
57  * This is not terribly bad, as "if"s are most common.
58  * This also allows the correction of other errors.
59  *
60  * This recovery depends on the default reductions which delay
61  * noticing the error until the parse reaches a state where the
62  * relevant "alternatives" are visible.  Note that it does not
63  * consider tokens which will cause reductions before being
64  * shifted over.  This requires the grammar to be written in a
65  * certain way for the recovery to work correctly.
66  * In some sense, also, the recovery suffers because we have
67  * LALR(1) tables rather than LR(1) tables, e.g. in
68  *
69  *	if rec.field < rec2,field2 then
70  */
71 
72 /*
73  * Definitions of possible corrective actions
74  */
75 #define	CPANIC		0
76 #define	CDELETE		1
77 #define	CREPLACE	2
78 #define	CINSERT		3
79 #define	CUNIQUE		4
80 #define	CCHIDENT	5
81 
82 /*
83  * Multiplicative cost factors for corrective actions.
84  *
85  * When an error occurs we take YCSIZ - 1 look-ahead tokens.
86  * If a correction being considered will shift over only part of
87  * that look-ahead, it is not completely discarded, but rather
88  * "weighted", its cost being multiplied by a weighting factor.
89  * For a correction to be considered its weighted cost must be less
90  * than CLIMIT.
91  *
92  * Non-weighted costs are considered:
93  *
94  *	LOW	<= 3
95  *	MEDIUM	4,5
96  *	HIGH	>= 6
97  *
98  * CURRENT WEIGHTING STRATEGY: Aug 20, 1977
99  *
100  * For all kinds of corrections we demand shifts over two symbols.
101  * Corrections have high weight even after two symbol
102  * shifts because the costs for deleting and inserting symbols are actually
103  * quite low; we do not want to change weighty symbols
104  * on inconclusive evidence.
105  *
106  * The weights are the same after the third look ahead.
107  * This prevents later, unrelated errors from causing "funny"
108  * biases of the weights toward one type of correction.
109  *
110  * Current look ahead is 5 symbols.
111  */
112 
113 /*** CLIMIT is defined in yy.h for yycosts ***/
114 #define	CPRLIMIT	50
115 #define	CCHIDCOST	3
116 
117 char	insmult[8]	= {INFINITY, INFINITY, INFINITY, 15, 8, 6, 3, 1};
118 char	repmult[7]	= {INFINITY, INFINITY, INFINITY, 8, 6, 3, 1};
119 char	delmult[6]	= {INFINITY, INFINITY, INFINITY, 6, 3, 1};
120 
121 #define	NOCHAR	-1
122 
123 #define	Eprintf	if (errtrace) printf
124 #define	Tprintf	if (testtrace) printf
125 
126 /*
127  * Action arrays of the parser needed here
128  */
129 int	yyact[], yypact[], *yypv;
130 
131 /*
132  * Yytips is the tip of the stack when using
133  * the function loccor to check for local
134  * syntactic correctness. As we don't want
135  * to copy the whole parser stack, but want
136  * to simulate parser moves, we "split"
137  * the parser stack and keep the tip here.
138  */
139 #define	YYTIPSIZ 16
140 int	yytips[YYTIPSIZ], yytipct;
141 int	yytipv[YYTIPSIZ];
142 
143 /*
144  * The array YC saves the lookahead tokens for the
145  * forward moves.
146  * Yccnt is the number of tokens in the YC array.
147  */
148 #define	YCSIZ	6
149 
150 int	yCcnt;
151 struct	yytok YC0[YCSIZ + 1];
152 struct	yytok *YC;
153 
154 /*
155  * YCps gives the top of stack at
156  * the point of error.
157  */
158 
159 bool	yyunique = 1;
160 
161 STATIC	unsigned yyTshifts;
162 
163 /*
164  * Cact is the corrective action we have decided on
165  * so far, ccost its cost, and cchar the associated token.
166  * Cflag tells if the correction is over the previous input token.
167  */
168 int	cact, ccost, cchar, cflag;
169 
170 /*
171  * ACtok holds the token under
172  * consideration when examining
173  * the lookaheads in a state.
174  */
175 struct	yytok ACtok;
176 
177 #define acchar	ACtok.Yychar
178 #define aclval	ACtok.Yylval
179 
180 /*
181  * Make a correction to the current stack which has
182  * top of stack pointer Ps.
183  */
184 yyrecover(Ps0, idfail)
185 	int *Ps0, idfail;
186 {
187 	register int c, i;
188 	int yyrwant, yyrhave;
189 
190 #ifdef PI
191 	Recovery = 1;
192 #endif
193 
194 	YC = &YC0[1];
195 #ifdef DEBUG
196 	if (errtrace) {
197 		setpfx('p');
198 		yerror("Point of error");
199 		printf("States %d %d ...", Ps0[0], Ps0[-1]);
200 		if (idfail)
201 			printf(" [Idfail]");
202 		pchr('\n');
203 		printf("Input %s%s", tokname(&Y , 0)
204 				   , tokname(&Y , 1));
205 	}
206 
207 #endif
208 	/*
209 	 * We first save the current input token
210 	 * and its associated semantic information.
211 	 */
212 	if (yychar < 0)
213 		yychar = yylex();
214 	copy(&YC[0], &Y, sizeof Y);
215 
216 	/*
217 	 * Set the default action and cost
218 	 */
219 	cact = CPANIC, ccost = CLIMIT, cflag = 0;
220 
221 	/*
222 	 * Peek ahead
223 	 */
224 	for (yCcnt = 1; yCcnt < YCSIZ; yCcnt++) {
225 		yychar = yylex();
226 		copy(&YC[yCcnt], &Y, sizeof YC[0]);
227 #ifdef DEBUG
228 		Eprintf(" | %s%s", tokname(&YC[yCcnt] , 0 )
229 				 , tokname(&YC[yCcnt] , 1 ));
230 #endif
231 	}
232 #ifdef DEBUG
233 	Eprintf("\n");
234 #endif
235 
236 	/*
237 	 * If we are here because a reduction failed, try
238 	 * correcting that.
239 	 */
240 	if (idfail) {
241 		/*
242 		 * Save the particulars about
243 		 * the kind of identifier we want/have.
244 		 */
245 		yyrwant = yyidwant;
246 		yyrhave = yyidhave;
247 #ifdef DEBUG
248 		Tprintf("  Try Replace %s identifier with %s identifier cost=%d\n",
249 		    classes[yyidhave], classes[yyidwant], CCHIDCOST);
250 #endif
251 
252 		/*
253 		 * Save the semantics of the ID on the
254 		 * stack, and null them out to free
255 		 * up the reduction in question.
256 		 */
257 		i = yypv[0];
258 		yypv[0] = nullsem(YID);
259 		c = correct(NOCHAR, 0, CCHIDCOST, &repmult[2], Ps0, yypv);
260 		yypv[0] = i;
261 #ifdef DEBUG
262 		if (c < CPRLIMIT || fulltrace)
263 			Eprintf("Cost %2d Replace %s identifier with %s identifier\n", c, classes[yyrhave], classes[yyrwant]);
264 #endif
265 		if (c < ccost)
266 			cact = CCHIDENT, ccost = c, cchar = YID;
267 	}
268 
269 	/*
270 	 * First try correcting the state we are in
271 	 */
272 	trystate(Ps0, yypv, 0, &insmult[1], &delmult[1], &repmult[1]);
273 
274 	/*
275 	 * Now, if we just shifted over a terminal, try
276 	 * correcting it.
277 	 */
278 	if (OY.Yychar != -1 && OY.Yylval != nullsem(OY.Yychar)) {
279 		YC--;
280 		copy(&YC[0], &OY, sizeof YC[0]);
281 		trystate(Ps0 - 1, yypv - 1, 1, insmult, delmult, repmult);
282 		if (cflag == 0)
283 			YC++;
284 		else {
285 			yypv--;
286 #ifdef PXP
287 			yypw--;
288 #endif
289 			Ps0--;
290 			yCcnt++;
291 		}
292 	}
293 
294 	/*
295 	 * Restoring the first look ahead into
296 	 * the scanner token allows the error message
297 	 * routine to print the error message with the text
298 	 * of the correct line.
299 	 */
300 	copy(&Y, &YC[0], sizeof Y);
301 
302 	/*
303 	 * Unique symbol insertion.
304 	 *
305 	 * If there was no reasonable correction found,
306 	 * but only one input to the parser is acceptable
307 	 * we report that, and try it.
308 	 *
309 	 * Special precautions here to prevent looping.
310 	 * The number of true inputs shifted over at the point
311 	 * of the last unique insertion is recorded in the
312 	 * variable yyTshifts.  If this is not less than
313 	 * the current number in yytshifts, we do not insert.
314 	 * Thus, after one unique insertion, no more unique
315 	 * insertions will be made until an input is shifted
316 	 * over.  This guarantees termination.
317 	 */
318 	if (cact == CPANIC && !idfail) {
319 		register int *ap;
320 
321 		ap = &yyact[yypact[*Ps0 + 1]];
322 		if (*ap == -ERROR)
323 			ap += 2;
324 		if (ap[0] <= 0 && ap[2] > 0) {
325 			cchar = -ap[0];
326 			if (cchar == YEOF)
327 				yyexeof();
328 			if (cchar != ERROR && yyTshifts < yytshifts) {
329 				cact = CUNIQUE;
330 #ifdef DEBUG
331 				Eprintf("Unique symbol %s%s\n"
332 					, charname(cchar , 0 )
333 					, charname(cchar , 1 ));
334 #endif
335 				/*
336 				 * Note that the inserted symbol
337 				 * will not be counted as a true input
338 				 * (i.e. the "yytshifts--" below)
339 				 * so that a true shift will be needed
340 				 * to make yytshifts > yyTshifts.
341 				 */
342 				yyTshifts = yytshifts;
343 			}
344 		}
345 	}
346 
347 	/*
348 	 * Set up to perform the correction.
349 	 * Build a token appropriate for replacement
350 	 * or insertion in the yytok structure ACchar
351 	 * having the attributes of the input at the
352 	 * point of error.
353 	 */
354 	copy(&ACtok, &YC[0], sizeof ACtok);
355 	acchar = cchar;
356 	aclval = nullsem(acchar);
357 	if (aclval != NIL)
358 		recovered();
359 	switch (cact) {
360 		/*
361 		 * Panic, just restore the
362 		 * lookahead and return.
363 		 */
364 		case CPANIC:
365 			setpfx('E');
366 			if (idfail) {
367 				copy(&Y, &OY, sizeof Y);
368 				if (yyrhave == NIL) {
369 #ifdef PI
370 					if (yybaduse(yypv[0], yyeline, ISUNDEF) == NIL)
371 #endif
372 						yerror("Undefined identifier");
373 				} else {
374 					yerror("Improper %s identifier", classes[yyrhave]);
375 #ifdef PI
376 					yybaduse(yypv[0], yyeline, NIL);
377 #endif
378 				}
379 				/*
380 				 * Suppress message from panic routine
381 				 */
382 				yyshifts = 1;
383 			}
384 			i = 0;
385 			/* Note that on one path we dont touch yyshifts ! */
386 			break;
387 		/*
388 		 * Delete the input.
389 		 * Mark this as a shift over true input.
390 		 * Restore the lookahead starting at
391 		 * the second token.
392 		 */
393 		case CDELETE:
394 			if (ccost != 0)
395 				yerror("Deleted %s%s", tokname(&YC[0] , 0 )
396 						     , tokname(&YC[0] , 1 ));
397 			yytshifts++;
398 			i = 1;
399 			yyshifts = 0;
400 			break;
401 		/*
402 		 * Replace the input with a new token.
403 		 */
404 		case CREPLACE:
405 			if (acchar == YEOF)
406 				yyexeof();
407 			if (acchar == YEND)
408 				aclval = NIL;
409 			yerror("Replaced %s%s with a %s%s",
410 			    tokname(&YC[0] , 0 ),
411 			    tokname(&YC[0] , 1 ),
412 			    tokname(&ACtok , 0 ),
413 			    tokname(&ACtok , 1 ));
414 			copy(&YC[0], &ACtok, sizeof YC[0]);
415 			i = 0;
416 			yyshifts = 0;
417 			break;
418 		/*
419 		 * Insert a token.
420 		 * Don't count this token as a true input shift.
421 		 * For inserted "end"s pas.y is responsible
422 		 * for the error message later so suppress it.
423 		 * Restore all the lookahead.
424 		 */
425 		case CINSERT:
426 			if (acchar == YEOF)
427 				yyexeof();
428 			if (acchar != YEND)
429 				yerror("Inserted %s%s",
430 					tokname(&ACtok , 0 ),
431 					tokname(&ACtok , 1 ));
432 			yytshifts--;
433 			i = 0;
434 			yyshifts = 0;
435 			break;
436 		/*
437 		 * Make a unique symbol correction.
438 		 * Like an insertion but a different message.
439 		 */
440 		case CUNIQUE:
441 			setpfx('E');
442 			yerror("Expected %s%s",
443 				tokname(&ACtok , 0 ),
444 				tokname(&ACtok , 1 ));
445 			yytshifts--;
446 			i = 0;
447 			if (ccost == 0 || yyunique)
448 				yyshifts = 0;
449 			else
450 				yyshifts = -1;
451 			break;
452 		/*
453 		 * Change an identifier's type
454 		 * to make it work.
455 		 */
456 		case CCHIDENT:
457 			copy(&Y, &OY, sizeof Y);
458 #ifdef PI
459 			i = 1 << yyrwant;
460 #endif
461 			if (yyrhave == NIL) {
462 				yerror("Undefined %s", classes[yyrwant]);
463 #ifdef PI
464 				i |= ISUNDEF;
465 #endif
466 			} else
467 				yerror("Replaced %s id with a %s id", classes[yyrhave], classes[yyrwant]);
468 #ifdef PI
469 			yybaduse(yypv[0], yyeline, i);
470 #endif
471 			yypv[0] = nullsem(YID);
472 			i = 0;
473 			yyshifts = 0;
474 			break;
475 	}
476 
477 	/*
478 	 * Restore the desired portion of the lookahead,
479 	 * and possibly the inserted or unique inserted token.
480 	 */
481 	for (yCcnt--; yCcnt >= i; yCcnt--)
482 		unyylex(&YC[yCcnt]);
483 	if (cact == CINSERT || cact == CUNIQUE)
484 		unyylex(&ACtok);
485 
486 	/*
487 	 * Put the scanner back in sync.
488 	 */
489 	yychar = yylex();
490 
491 	/*
492 	 * We succeeded if we didn't "panic".
493 	 */
494 	Recovery = 0;
495 	Ps = Ps0;
496 	return (cact != CPANIC);
497 }
498 
499 yyexeof()
500 {
501 
502 	yerror("End-of-file expected - QUIT");
503 	pexit(ERRS);
504 }
505 
506 yyunexeof()
507 {
508 
509 	yerror("Unexpected end-of-file - QUIT");
510 	pexit(ERRS);
511 }
512 
513 /*
514  * Try corrections with the state at Ps0.
515  * Flag is 0 if this is the top of stack state,
516  * 1 if it is the state below.
517  */
518 trystate(Ps0, Pv0, flag, insmult, delmult, repmult)
519 	int *Ps0, *Pv0, flag;
520 	char *insmult, *delmult, *repmult;
521 {
522 	/*
523 	 * C is a working cost, ap a pointer into the action
524 	 * table for looking at feasible alternatives.
525 	 */
526 	register int c, *ap;
527 	int i, *actions;
528 
529 #ifdef DEBUG
530 	Eprintf("Trying state %d\n", *Ps0);
531 #endif
532 	/*
533 	 * Try deletion.
534 	 * Correct returns a cost.
535 	 */
536 #ifdef DEBUG
537 	Tprintf("  Try Delete %s%s cost=%d\n",
538 		tokname(&YC[0] , 0 ),
539 		tokname(&YC[0] , 1 ),
540 		delcost(YC[0].Yychar));
541 #endif
542 	c = delcost(YC[0].Yychar);
543 #ifndef DEBUG
544 	if (c < ccost) {
545 #endif
546 		c = correct(NOCHAR, 1, c, delmult, Ps0, Pv0);
547 #ifdef DEBUG
548 		if (c < CPRLIMIT || fulltrace)
549 			Eprintf("Cost %2d Delete %s%s\n", c,
550 				tokname(&YC[0] , 0 ),
551 				tokname(&YC[0] , 1 ));
552 #endif
553 		if (c < ccost)
554 			cact = CDELETE, ccost = c, cflag = flag;
555 #ifndef DEBUG
556 	}
557 #endif
558 
559 	/*
560 	 * Look at the inputs to this state
561 	 * which will cause parse action shift.
562 	 */
563 	aclval = NIL;
564 	ap = &yyact[yypact[*Ps0 + 1]];
565 
566 	/*
567 	 * Skip action on error to
568 	 * detect true unique inputs.
569 	 * Error action is always first.
570 	 */
571 	if (*ap == -ERROR)
572 		ap += 2;
573 
574 	/*
575 	 * Loop through the test actions
576 	 * for this state.
577 	 */
578 	for (actions = ap; *ap <= 0; ap += 2) {
579 		/*
580 		 * Extract the token of this action
581 		 */
582 		acchar = -*ap;
583 
584 		/*
585 		 * Try insertion
586 		 */
587 #ifdef DEBUG
588 		Tprintf("  Try Insert %s%s cost=%d\n"
589 			, charname(acchar , 0 )
590 			, charname(acchar , 1 )
591 			, inscost(acchar));
592 #endif
593 		c = inscost(acchar, YC[0].Yychar);
594 #ifndef DEBUG
595 		if (c < ccost) {
596 #endif
597 			if (c == 0) {
598 				c = correct(acchar, 0, 1, insmult + 1, Ps0, Pv0);
599 #ifdef DEBUG
600 				Eprintf("Cost %2d Freebie %s%s\n", c
601 					, charname(acchar , 0 )
602 					, charname(acchar , 1 ));
603 #endif
604 				if (c < ccost)
605 					cact = CUNIQUE, ccost = 0, cchar = acchar, cflag = flag;
606 			} else {
607 				c = correct(acchar, 0, c, insmult, Ps0, Pv0);
608 #ifdef DEBUG
609 				if (c < CPRLIMIT || fulltrace)
610 					Eprintf("Cost %2d Insert %s%s\n", c
611 						, charname(acchar , 0 )
612 						, charname(acchar , 1 ));
613 #endif
614 				if (c < ccost)
615 					cact = CINSERT, ccost = c, cchar = acchar, cflag = flag;
616 			}
617 #ifndef DEBUG
618 		}
619 #endif
620 
621 		/*
622 		 * Try replacement
623 		 */
624 #ifdef DEBUG
625 		Tprintf("  Try Replace %s%s with %s%s cost=%d\n",
626 		    tokname(&YC[0] , 0 ),
627 		    tokname(&YC[0] , 1 ),
628 		    charname(acchar , 0 ),
629 		    charname(acchar , 1 ),
630 		    repcost(YC[0].Yychar, acchar));
631 #endif
632 		c = repcost(YC[0].Yychar, acchar);
633 #ifndef DEBUG
634 		if (c < ccost) {
635 #endif
636 			c = correct(acchar, 1, repcost(YC[0].Yychar, acchar), repmult, Ps0, Pv0);
637 #ifdef DEBUG
638 			if (c < CPRLIMIT || fulltrace)
639 				Eprintf("Cost %2d Replace %s%s with %s%s\n",
640 					c,
641 					tokname(&YC[0] , 0 ),
642 					tokname(&YC[0] , 1 ),
643 					tokname(&ACtok , 0 ),
644 					tokname(&ACtok , 1 ));
645 #endif
646 			if (c < ccost)
647 				cact = CREPLACE, ccost = c, cchar = acchar, cflag = flag;
648 #ifndef DEBUG
649 		}
650 #endif
651 	}
652 }
653 
654 int	*yCpv;
655 char	yyredfail;
656 
657 /*
658  * The ntok structure is used to build a
659  * scanner structure for tokens inserted
660  * from the argument "fchar" to "correct" below.
661  */
662 static	struct yytok ntok;
663 
664 /*
665  * Compute the cost of a correction
666  * C is the base cost for it.
667  * Fchar is the first input character from
668  * the current state, NOCHAR if none.
669  * The rest of the inputs come from the array
670  * YC, starting at origin and continuing to the
671  * last character there, YC[yCcnt - 1].Yychar.
672  *
673  * The cost returned is INFINITE if this correction
674  * allows no shifts, otherwise is weighted based
675  * on the number of shifts this allows against the
676  * maximum number possible with the available lookahead.
677  */
678 correct(fchar, origin, c, multvec, Ps0, Pv0)
679 	register int fchar, c;
680 	int origin;
681 	char *multvec;
682 	int *Ps0, *Pv0;
683 {
684 	register char *mv;
685 
686 	/*
687 	 * Ps is the top of the parse stack after the most
688 	 * recent local correctness check.  Loccor returns
689 	 * NIL when we cannot shift.
690 	 */
691 	register int *ps;
692 
693 	yyredfail = 0;
694 	/*
695 	 * Initialize the tip parse and semantic stacks.
696 	 */
697 	ps = Ps0;
698 	yytips[0] = *ps;
699 	ps--;
700 	yytipv[0] = Pv0[0];
701 	yCpv = Pv0 - 1;
702 	yytipct = 1;
703 
704 	/*
705 	 * Shift while possible.
706 	 * Adjust cost as necessary.
707 	 */
708 	mv = multvec;
709 	do {
710 		if (fchar != NOCHAR) {
711 			copy(&ntok, &YC[0], sizeof ntok);
712 			ntok.Yychar = fchar, ntok.Yylval = nullsem(fchar);
713 			fchar = NOCHAR;
714 			ps = loccor(ps, &ntok);
715 		} else
716 			ps = loccor(ps, &YC[origin++]);
717 		if (ps == NIL) {
718 			if (yyredfail && mv > multvec)
719 				mv--;
720 			c *= *mv;
721 			break;
722 		}
723 		mv++;
724 	} while (*mv != 1);
725 	return (c);
726 }
727 
728 extern	int yygo[], yypgo[], yyr1[], yyr2[];
729 /*
730  * Local syntactic correctness check.
731  * The arguments to this routine are a
732  * top of stack pointer, ps, and an input
733  * token tok.  Also, implicitly, the contents
734  * of the yytips array which contains the tip
735  * of the stack, and into which the new top
736  * state on the stack will be placed if we shift.
737  *
738  * If we succeed, we return a new top of stack
739  * pointer, else we return NIL.
740  */
741 loccor(ps, ntok)
742 	int *ps;
743 	struct yytok *ntok;
744 {
745 	register int *p, n;
746 	register int nchar;
747 	int i;
748 
749 	if (ps == NIL)
750 		return (NIL);
751 	nchar = ntok->Yychar;
752 	yyeline = ntok->Yyeline;
753 #ifdef DEBUG
754 	Tprintf("    Stack ");
755 	for (i = yytipct - 1; i >= 0; i--)
756 		Tprintf("%d ", yytips[i]);
757 	Tprintf("| %d, Input %s%s\n", *ps
758 		, charname(nchar , 0 )
759 		, charname(nchar , 1 ));
760 #endif
761 	/*
762 	 * As in the yacc parser yyparse,
763 	 * p traces through the action list
764 	 * and "n" is the information associated
765 	 * with the action.
766 	 */
767 newstate:
768 	p = &yyact[ yypact[yytips[yytipct - 1]+1] ];
769 
770 actn:
771 	/*
772 	 * Search the parse actions table
773 	 * for something useful to do.
774 	 * While n is non-positive, it is the
775 	 * arithmetic inverse of the token to be tested.
776 	 * This allows a fast check.
777 	 */
778 	while ((n = *p++) <= 0)
779 		if ((n += nchar) != 0)
780 			p++;
781 	switch (n >> 12) {
782 		/*
783 		 * SHIFT
784 		 */
785 		case 2:
786 			n &= 07777;
787 			yyredfail = 0;
788 			if (nchar == YID)
789 				yyredfail++;
790 			if (yytipct == YYTIPSIZ) {
791 tipover:
792 #ifdef DEBUG
793 				Tprintf("\tTIP OVFLO\n");
794 #endif
795 				return (NIL);
796 			}
797 			yytips[yytipct] = n;
798 			yytipv[yytipct] = ntok->Yylval;
799 			yytipct++;
800 #ifdef DEBUG
801 			Tprintf("\tShift to state %d\n", n);
802 #endif
803 			return (ps);
804 		/*
805 		 * REDUCE
806 		 */
807 		case 3:
808 			n &= 07777;
809 			if (yyEactr(n, yytipv[yytipct - 1]) == 0) {
810 #ifdef DEBUG
811 				Tprintf("\tYyEactr objects: have %s id, want %s id\n", classes[yyidhave], classes[yyidwant]);
812 #endif
813 				return (NIL);
814 			}
815 			yyredfail = 0;
816 			i = yyr2[n];
817 #ifdef DEBUG
818 			Tprintf("\tReduce, length %d,", i);
819 #endif
820 			if (i > yytipct) {
821 				i -= yytipct;
822 				yytipct = 0;
823 				ps -= i;
824 				yCpv -= i;
825 			} else
826 				yytipct -= i;
827 			if (yytipct >= YYTIPSIZ)
828 				goto tipover;
829 			/*
830 			 * Use goto table to find next state
831 			 */
832 			p = &yygo[yypgo[yyr1[n]]];
833 			i = yytipct ? yytips[yytipct - 1] : *ps;
834 			while (*p != i && *p >= 0)
835 				p += 2;
836 #ifdef DEBUG
837 			Tprintf(" new state %d\n", p[1]);
838 #endif
839 			yytips[yytipct] = p[1];
840 			yytipct++;
841 			goto newstate;
842 		/*
843 		 * ACCEPT
844 		 */
845 		case 4:
846 #ifdef DEBUG
847 			Tprintf("\tAccept\n");
848 #endif
849 			return (ps);
850 		/*
851 		 * ERROR
852 		 */
853 		case 1:
854 #ifdef DEBUG
855 			Tprintf("\tError\n");
856 #endif
857 			return (0);
858 	}
859 	panic("loccor");
860 }
861