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