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