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