xref: /original-bsd/usr.bin/pascal/src/yyrecover.c (revision b64b0d54)
1 /* Copyright (c) 1979 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)yyrecover.c 1.3 02/05/83";
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 #ifdef PXP
203 		putchar('\n');
204 #else
205 		pchr('\n');
206 #endif
207 		printf("Input %s%s", tokname(&Y , 0)
208 				   , tokname(&Y , 1));
209 	}
210 
211 #endif
212 	/*
213 	 * We first save the current input token
214 	 * and its associated semantic information.
215 	 */
216 	if (yychar < 0)
217 		yychar = yylex();
218 	copy(&YC[0], &Y, sizeof Y);
219 
220 	/*
221 	 * Set the default action and cost
222 	 */
223 	cact = CPANIC, ccost = CLIMIT, cflag = 0;
224 
225 	/*
226 	 * Peek ahead
227 	 */
228 	for (yCcnt = 1; yCcnt < YCSIZ; yCcnt++) {
229 		yychar = yylex();
230 		copy(&YC[yCcnt], &Y, sizeof YC[0]);
231 #ifdef DEBUG
232 		Eprintf(" | %s%s", tokname(&YC[yCcnt] , 0 )
233 				 , tokname(&YC[yCcnt] , 1 ));
234 #endif
235 	}
236 #ifdef DEBUG
237 	Eprintf("\n");
238 #endif
239 
240 	/*
241 	 * If we are here because a reduction failed, try
242 	 * correcting that.
243 	 */
244 	if (idfail) {
245 		/*
246 		 * Save the particulars about
247 		 * the kind of identifier we want/have.
248 		 */
249 		yyrwant = yyidwant;
250 		yyrhave = yyidhave;
251 #ifdef DEBUG
252 		Tprintf("  Try Replace %s identifier with %s identifier cost=%d\n",
253 		    classes[yyidhave], classes[yyidwant], CCHIDCOST);
254 #endif
255 
256 		/*
257 		 * Save the semantics of the ID on the
258 		 * stack, and null them out to free
259 		 * up the reduction in question.
260 		 */
261 		i = yypv[0];
262 		yypv[0] = nullsem(YID);
263 		c = correct(NOCHAR, 0, CCHIDCOST, &repmult[2], Ps0, yypv);
264 		yypv[0] = i;
265 #ifdef DEBUG
266 		if (c < CPRLIMIT || fulltrace)
267 			Eprintf("Cost %2d Replace %s identifier with %s identifier\n", c, classes[yyrhave], classes[yyrwant]);
268 #endif
269 		if (c < ccost)
270 			cact = CCHIDENT, ccost = c, cchar = YID;
271 	}
272 
273 	/*
274 	 * First try correcting the state we are in
275 	 */
276 	trystate(Ps0, yypv, 0, &insmult[1], &delmult[1], &repmult[1]);
277 
278 	/*
279 	 * Now, if we just shifted over a terminal, try
280 	 * correcting it.
281 	 */
282 	if (OY.Yychar != -1 && OY.Yylval != nullsem(OY.Yychar)) {
283 		YC--;
284 		copy(&YC[0], &OY, sizeof YC[0]);
285 		trystate(Ps0 - 1, yypv - 1, 1, insmult, delmult, repmult);
286 		if (cflag == 0)
287 			YC++;
288 		else {
289 			yypv--;
290 #ifdef PXP
291 			yypw--;
292 #endif
293 			Ps0--;
294 			yCcnt++;
295 		}
296 	}
297 
298 	/*
299 	 * Restoring the first look ahead into
300 	 * the scanner token allows the error message
301 	 * routine to print the error message with the text
302 	 * of the correct line.
303 	 */
304 	copy(&Y, &YC[0], sizeof Y);
305 
306 	/*
307 	 * Unique symbol insertion.
308 	 *
309 	 * If there was no reasonable correction found,
310 	 * but only one input to the parser is acceptable
311 	 * we report that, and try it.
312 	 *
313 	 * Special precautions here to prevent looping.
314 	 * The number of true inputs shifted over at the point
315 	 * of the last unique insertion is recorded in the
316 	 * variable yyTshifts.  If this is not less than
317 	 * the current number in yytshifts, we do not insert.
318 	 * Thus, after one unique insertion, no more unique
319 	 * insertions will be made until an input is shifted
320 	 * over.  This guarantees termination.
321 	 */
322 	if (cact == CPANIC && !idfail) {
323 		register int *ap;
324 
325 		ap = &yyact[yypact[*Ps0 + 1]];
326 		if (*ap == -ERROR)
327 			ap += 2;
328 		if (ap[0] <= 0 && ap[2] > 0) {
329 			cchar = -ap[0];
330 			if (cchar == YEOF)
331 				yyexeof();
332 			if (cchar != ERROR && yyTshifts < yytshifts) {
333 				cact = CUNIQUE;
334 #ifdef DEBUG
335 				Eprintf("Unique symbol %s%s\n"
336 					, charname(cchar , 0 )
337 					, charname(cchar , 1 ));
338 #endif
339 				/*
340 				 * Note that the inserted symbol
341 				 * will not be counted as a true input
342 				 * (i.e. the "yytshifts--" below)
343 				 * so that a true shift will be needed
344 				 * to make yytshifts > yyTshifts.
345 				 */
346 				yyTshifts = yytshifts;
347 			}
348 		}
349 	}
350 
351 	/*
352 	 * Set up to perform the correction.
353 	 * Build a token appropriate for replacement
354 	 * or insertion in the yytok structure ACchar
355 	 * having the attributes of the input at the
356 	 * point of error.
357 	 */
358 	copy(&ACtok, &YC[0], sizeof ACtok);
359 	acchar = cchar;
360 	aclval = nullsem(acchar);
361 	if (aclval != NIL)
362 		recovered();
363 	switch (cact) {
364 		/*
365 		 * Panic, just restore the
366 		 * lookahead and return.
367 		 */
368 		case CPANIC:
369 			setpfx('E');
370 			if (idfail) {
371 				copy(&Y, &OY, sizeof Y);
372 				if (yyrhave == NIL) {
373 #ifdef PI
374 					if (yybaduse(yypv[0], yyeline, ISUNDEF) == NIL)
375 #endif
376 						yerror("Undefined identifier");
377 				} else {
378 					yerror("Improper %s identifier", classes[yyrhave]);
379 #ifdef PI
380 					yybaduse(yypv[0], yyeline, NIL);
381 #endif
382 				}
383 				/*
384 				 * Suppress message from panic routine
385 				 */
386 				yyshifts = 1;
387 			}
388 			i = 0;
389 			/* Note that on one path we dont touch yyshifts ! */
390 			break;
391 		/*
392 		 * Delete the input.
393 		 * Mark this as a shift over true input.
394 		 * Restore the lookahead starting at
395 		 * the second token.
396 		 */
397 		case CDELETE:
398 			if (ccost != 0)
399 				yerror("Deleted %s%s", tokname(&YC[0] , 0 )
400 						     , tokname(&YC[0] , 1 ));
401 			yytshifts++;
402 			i = 1;
403 			yyshifts = 0;
404 			break;
405 		/*
406 		 * Replace the input with a new token.
407 		 */
408 		case CREPLACE:
409 			if (acchar == YEOF)
410 				yyexeof();
411 			if (acchar == YEND)
412 				aclval = NIL;
413 			yerror("Replaced %s%s with a %s%s",
414 			    tokname(&YC[0] , 0 ),
415 			    tokname(&YC[0] , 1 ),
416 			    tokname(&ACtok , 0 ),
417 			    tokname(&ACtok , 1 ));
418 			copy(&YC[0], &ACtok, sizeof YC[0]);
419 			i = 0;
420 			yyshifts = 0;
421 			break;
422 		/*
423 		 * Insert a token.
424 		 * Don't count this token as a true input shift.
425 		 * For inserted "end"s pas.y is responsible
426 		 * for the error message later so suppress it.
427 		 * Restore all the lookahead.
428 		 */
429 		case CINSERT:
430 			if (acchar == YEOF)
431 				yyexeof();
432 			if (acchar != YEND)
433 				yerror("Inserted %s%s",
434 					tokname(&ACtok , 0 ),
435 					tokname(&ACtok , 1 ));
436 			yytshifts--;
437 			i = 0;
438 			yyshifts = 0;
439 			break;
440 		/*
441 		 * Make a unique symbol correction.
442 		 * Like an insertion but a different message.
443 		 */
444 		case CUNIQUE:
445 			setpfx('E');
446 			yerror("Expected %s%s",
447 				tokname(&ACtok , 0 ),
448 				tokname(&ACtok , 1 ));
449 			yytshifts--;
450 			i = 0;
451 			if (ccost == 0 || yyunique)
452 				yyshifts = 0;
453 			else
454 				yyshifts = -1;
455 			break;
456 		/*
457 		 * Change an identifier's type
458 		 * to make it work.
459 		 */
460 		case CCHIDENT:
461 			copy(&Y, &OY, sizeof Y);
462 #ifdef PI
463 			i = 1 << yyrwant;
464 #endif
465 			if (yyrhave == NIL) {
466 				yerror("Undefined %s", classes[yyrwant]);
467 #ifdef PI
468 				i |= ISUNDEF;
469 #endif
470 			} else
471 				yerror("Replaced %s id with a %s id", classes[yyrhave], classes[yyrwant]);
472 #ifdef PI
473 			yybaduse(yypv[0], yyeline, i);
474 #endif
475 			yypv[0] = nullsem(YID);
476 			i = 0;
477 			yyshifts = 0;
478 			break;
479 	}
480 
481 	/*
482 	 * Restore the desired portion of the lookahead,
483 	 * and possibly the inserted or unique inserted token.
484 	 */
485 	for (yCcnt--; yCcnt >= i; yCcnt--)
486 		unyylex(&YC[yCcnt]);
487 	if (cact == CINSERT || cact == CUNIQUE)
488 		unyylex(&ACtok);
489 
490 	/*
491 	 * Put the scanner back in sync.
492 	 */
493 	yychar = yylex();
494 
495 	/*
496 	 * We succeeded if we didn't "panic".
497 	 */
498 	Recovery = 0;
499 	Ps = Ps0;
500 	return (cact != CPANIC);
501 }
502 
503 yyexeof()
504 {
505 
506 	yerror("End-of-file expected - QUIT");
507 	pexit(ERRS);
508 }
509 
510 yyunexeof()
511 {
512 
513 	yerror("Unexpected end-of-file - QUIT");
514 	pexit(ERRS);
515 }
516 
517 /*
518  * Try corrections with the state at Ps0.
519  * Flag is 0 if this is the top of stack state,
520  * 1 if it is the state below.
521  */
522 trystate(Ps0, Pv0, flag, insmult, delmult, repmult)
523 	int *Ps0, *Pv0, flag;
524 	char *insmult, *delmult, *repmult;
525 {
526 	/*
527 	 * C is a working cost, ap a pointer into the action
528 	 * table for looking at feasible alternatives.
529 	 */
530 	register int c, *ap;
531 	int i, *actions;
532 
533 #ifdef DEBUG
534 	Eprintf("Trying state %d\n", *Ps0);
535 #endif
536 	/*
537 	 * Try deletion.
538 	 * Correct returns a cost.
539 	 */
540 #ifdef DEBUG
541 	Tprintf("  Try Delete %s%s cost=%d\n",
542 		tokname(&YC[0] , 0 ),
543 		tokname(&YC[0] , 1 ),
544 		delcost(YC[0].Yychar));
545 #endif
546 	c = delcost(YC[0].Yychar);
547 #ifndef DEBUG
548 	if (c < ccost) {
549 #endif
550 		c = correct(NOCHAR, 1, c, delmult, Ps0, Pv0);
551 #ifdef DEBUG
552 		if (c < CPRLIMIT || fulltrace)
553 			Eprintf("Cost %2d Delete %s%s\n", c,
554 				tokname(&YC[0] , 0 ),
555 				tokname(&YC[0] , 1 ));
556 #endif
557 		if (c < ccost)
558 			cact = CDELETE, ccost = c, cflag = flag;
559 #ifndef DEBUG
560 	}
561 #endif
562 
563 	/*
564 	 * Look at the inputs to this state
565 	 * which will cause parse action shift.
566 	 */
567 	aclval = NIL;
568 	ap = &yyact[yypact[*Ps0 + 1]];
569 
570 	/*
571 	 * Skip action on error to
572 	 * detect true unique inputs.
573 	 * Error action is always first.
574 	 */
575 	if (*ap == -ERROR)
576 		ap += 2;
577 
578 	/*
579 	 * Loop through the test actions
580 	 * for this state.
581 	 */
582 	for (actions = ap; *ap <= 0; ap += 2) {
583 		/*
584 		 * Extract the token of this action
585 		 */
586 		acchar = -*ap;
587 
588 		/*
589 		 * Try insertion
590 		 */
591 #ifdef DEBUG
592 		Tprintf("  Try Insert %s%s cost=%d\n"
593 			, charname(acchar , 0 )
594 			, charname(acchar , 1 )
595 			, inscost(acchar));
596 #endif
597 		c = inscost(acchar, YC[0].Yychar);
598 #ifndef DEBUG
599 		if (c < ccost) {
600 #endif
601 			if (c == 0) {
602 				c = correct(acchar, 0, 1, insmult + 1, Ps0, Pv0);
603 #ifdef DEBUG
604 				Eprintf("Cost %2d Freebie %s%s\n", c
605 					, charname(acchar , 0 )
606 					, charname(acchar , 1 ));
607 #endif
608 				if (c < ccost)
609 					cact = CUNIQUE, ccost = 0, cchar = acchar, cflag = flag;
610 			} else {
611 				c = correct(acchar, 0, c, insmult, Ps0, Pv0);
612 #ifdef DEBUG
613 				if (c < CPRLIMIT || fulltrace)
614 					Eprintf("Cost %2d Insert %s%s\n", c
615 						, charname(acchar , 0 )
616 						, charname(acchar , 1 ));
617 #endif
618 				if (c < ccost)
619 					cact = CINSERT, ccost = c, cchar = acchar, cflag = flag;
620 			}
621 #ifndef DEBUG
622 		}
623 #endif
624 
625 		/*
626 		 * Try replacement
627 		 */
628 #ifdef DEBUG
629 		Tprintf("  Try Replace %s%s with %s%s cost=%d\n",
630 		    tokname(&YC[0] , 0 ),
631 		    tokname(&YC[0] , 1 ),
632 		    charname(acchar , 0 ),
633 		    charname(acchar , 1 ),
634 		    repcost(YC[0].Yychar, acchar));
635 #endif
636 		c = repcost(YC[0].Yychar, acchar);
637 #ifndef DEBUG
638 		if (c < ccost) {
639 #endif
640 			c = correct(acchar, 1, repcost(YC[0].Yychar, acchar), repmult, Ps0, Pv0);
641 #ifdef DEBUG
642 			if (c < CPRLIMIT || fulltrace)
643 				Eprintf("Cost %2d Replace %s%s with %s%s\n",
644 					c,
645 					tokname(&YC[0] , 0 ),
646 					tokname(&YC[0] , 1 ),
647 					tokname(&ACtok , 0 ),
648 					tokname(&ACtok , 1 ));
649 #endif
650 			if (c < ccost)
651 				cact = CREPLACE, ccost = c, cchar = acchar, cflag = flag;
652 #ifndef DEBUG
653 		}
654 #endif
655 	}
656 }
657 
658 int	*yCpv;
659 char	yyredfail;
660 
661 /*
662  * The ntok structure is used to build a
663  * scanner structure for tokens inserted
664  * from the argument "fchar" to "correct" below.
665  */
666 static	struct yytok ntok;
667 
668 /*
669  * Compute the cost of a correction
670  * C is the base cost for it.
671  * Fchar is the first input character from
672  * the current state, NOCHAR if none.
673  * The rest of the inputs come from the array
674  * YC, starting at origin and continuing to the
675  * last character there, YC[yCcnt - 1].Yychar.
676  *
677  * The cost returned is INFINITE if this correction
678  * allows no shifts, otherwise is weighted based
679  * on the number of shifts this allows against the
680  * maximum number possible with the available lookahead.
681  */
682 correct(fchar, origin, c, multvec, Ps0, Pv0)
683 	register int fchar, c;
684 	int origin;
685 	char *multvec;
686 	int *Ps0, *Pv0;
687 {
688 	register char *mv;
689 
690 	/*
691 	 * Ps is the top of the parse stack after the most
692 	 * recent local correctness check.  Loccor returns
693 	 * NIL when we cannot shift.
694 	 */
695 	register int *ps;
696 
697 	yyredfail = 0;
698 	/*
699 	 * Initialize the tip parse and semantic stacks.
700 	 */
701 	ps = Ps0;
702 	yytips[0] = *ps;
703 	ps--;
704 	yytipv[0] = Pv0[0];
705 	yCpv = Pv0 - 1;
706 	yytipct = 1;
707 
708 	/*
709 	 * Shift while possible.
710 	 * Adjust cost as necessary.
711 	 */
712 	mv = multvec;
713 	do {
714 		if (fchar != NOCHAR) {
715 			copy(&ntok, &YC[0], sizeof ntok);
716 			ntok.Yychar = fchar, ntok.Yylval = nullsem(fchar);
717 			fchar = NOCHAR;
718 			ps = loccor(ps, &ntok);
719 		} else
720 			ps = loccor(ps, &YC[origin++]);
721 		if (ps == NIL) {
722 			if (yyredfail && mv > multvec)
723 				mv--;
724 			c *= *mv;
725 			break;
726 		}
727 		mv++;
728 	} while (*mv != 1);
729 	return (c);
730 }
731 
732 extern	int yygo[], yypgo[], yyr1[], yyr2[];
733 /*
734  * Local syntactic correctness check.
735  * The arguments to this routine are a
736  * top of stack pointer, ps, and an input
737  * token tok.  Also, implicitly, the contents
738  * of the yytips array which contains the tip
739  * of the stack, and into which the new top
740  * state on the stack will be placed if we shift.
741  *
742  * If we succeed, we return a new top of stack
743  * pointer, else we return NIL.
744  */
745 loccor(ps, ntok)
746 	int *ps;
747 	struct yytok *ntok;
748 {
749 	register int *p, n;
750 	register int nchar;
751 	int i;
752 
753 	if (ps == NIL)
754 		return (NIL);
755 	nchar = ntok->Yychar;
756 	yyeline = ntok->Yyeline;
757 #ifdef DEBUG
758 	Tprintf("    Stack ");
759 	for (i = yytipct - 1; i >= 0; i--)
760 		Tprintf("%d ", yytips[i]);
761 	Tprintf("| %d, Input %s%s\n", *ps
762 		, charname(nchar , 0 )
763 		, charname(nchar , 1 ));
764 #endif
765 	/*
766 	 * As in the yacc parser yyparse,
767 	 * p traces through the action list
768 	 * and "n" is the information associated
769 	 * with the action.
770 	 */
771 newstate:
772 	p = &yyact[ yypact[yytips[yytipct - 1]+1] ];
773 
774 actn:
775 	/*
776 	 * Search the parse actions table
777 	 * for something useful to do.
778 	 * While n is non-positive, it is the
779 	 * arithmetic inverse of the token to be tested.
780 	 * This allows a fast check.
781 	 */
782 	while ((n = *p++) <= 0)
783 		if ((n += nchar) != 0)
784 			p++;
785 	switch (n >> 12) {
786 		/*
787 		 * SHIFT
788 		 */
789 		case 2:
790 			n &= 07777;
791 			yyredfail = 0;
792 			if (nchar == YID)
793 				yyredfail++;
794 			if (yytipct == YYTIPSIZ) {
795 tipover:
796 #ifdef DEBUG
797 				Tprintf("\tTIP OVFLO\n");
798 #endif
799 				return (NIL);
800 			}
801 			yytips[yytipct] = n;
802 			yytipv[yytipct] = ntok->Yylval;
803 			yytipct++;
804 #ifdef DEBUG
805 			Tprintf("\tShift to state %d\n", n);
806 #endif
807 			return (ps);
808 		/*
809 		 * REDUCE
810 		 */
811 		case 3:
812 			n &= 07777;
813 			if (yyEactr(n, yytipv[yytipct - 1]) == 0) {
814 #ifdef DEBUG
815 				Tprintf("\tYyEactr objects: have %s id, want %s id\n", classes[yyidhave], classes[yyidwant]);
816 #endif
817 				return (NIL);
818 			}
819 			yyredfail = 0;
820 			i = yyr2[n];
821 #ifdef DEBUG
822 			Tprintf("\tReduce, length %d,", i);
823 #endif
824 			if (i > yytipct) {
825 				i -= yytipct;
826 				yytipct = 0;
827 				ps -= i;
828 				yCpv -= i;
829 			} else
830 				yytipct -= i;
831 			if (yytipct >= YYTIPSIZ)
832 				goto tipover;
833 			/*
834 			 * Use goto table to find next state
835 			 */
836 			p = &yygo[yypgo[yyr1[n]]];
837 			i = yytipct ? yytips[yytipct - 1] : *ps;
838 			while (*p != i && *p >= 0)
839 				p += 2;
840 #ifdef DEBUG
841 			Tprintf(" new state %d\n", p[1]);
842 #endif
843 			yytips[yytipct] = p[1];
844 			yytipct++;
845 			goto newstate;
846 		/*
847 		 * ACCEPT
848 		 */
849 		case 4:
850 #ifdef DEBUG
851 			Tprintf("\tAccept\n");
852 #endif
853 			return (ps);
854 		/*
855 		 * ERROR
856 		 */
857 		case 1:
858 #ifdef DEBUG
859 			Tprintf("\tError\n");
860 #endif
861 			return (0);
862 	}
863 	panic("loccor");
864 }
865