|
|
1.1 root 1: /* Copyright (c) 1979 Regents of the University of California */
2:
3: static char sccsid[] = "@(#)yyrecover.c 1.1 8/27/80";
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.