xref: /original-bsd/usr.bin/pascal/src/yypanic.c (revision 5b8e85f8)
1 /* Copyright (c) 1979 Regents of the University of California */
2 
3 static	char sccsid[] = "@(#)yypanic.c 1.3 03/29/82";
4 
5 #include "whoami.h"
6 #include "0.h"
7 #include "yy.h"
8 
9 struct yytok oldpos;
10 /*
11  * The routine yyPerror coordinates the panic when
12  * the correction routines fail. Three types of panics
13  * are possible - those in a declaration part, those
14  * in a statement part, and those in an expression.
15  *
16  * Declaration part panics consider insertion of "begin",
17  * expression part panics will stop on more symbols.
18  * The panics are otherwise the same.
19  *
20  * ERROR MESSAGE SUPPRESSION STRATEGY: August 11, 1977
21  *
22  * If the parser has not made at least 2 moves since the last point of
23  * error then we want to suppress the supplied error message.
24  * Otherwise we print it.
25  * We then skip input up to the next solid symbol.
26  */
27 yyPerror(cp, kind)
28 	char *cp;
29 	register int kind;
30 {
31 	register int ishifts, brlev;
32 
33 	copy(&oldpos, &Y, sizeof oldpos);
34 	brlev = 0;
35 	if (yychar < 0)
36 		yychar = yylex();
37 	for (ishifts = yyshifts; ; yychar = yylex(), yyshifts++)
38 		switch (yychar) {
39 			case YILLCH:
40 				yerror("Illegal character");
41 				if (ishifts == yyshifts)
42 					yyOshifts = 0;
43 				continue;
44 			case YEOF:
45 				if (kind == PDECL) {
46 					/*
47 					 * we have paniced to end of file
48 					 * during declarations. Separately
49 					 * compiled segments can syntactically
50 					 * exit without any error message, so
51 					 * we force one here.
52 					 */
53 					yerror(cp);
54 					continuation();
55 					yyunexeof();
56 				}
57 				goto quiet;
58 			case ';':
59 				if (kind == PPROG)
60 					continue;
61 				if (kind == PDECL)
62 					yychar = yylex();
63 				goto resume;
64 			case YEND:
65 				if (kind == PPROG)
66 					continue;
67 			case YPROCEDURE:
68 			case YFUNCTION:
69 				goto resume;
70 			case YLABEL:
71 			case YTYPE:
72 			case YCONST:
73 			case YVAR:
74 				if (kind == PSTAT) {
75 					yerror("Declaration found when statement expected");
76 					goto quiet;
77 				}
78 			case YBEGIN:
79 				goto resume;
80 			case YFOR:
81 			case YREPEAT:
82 			case YWHILE:
83 			case YGOTO:
84 			case YIF:
85 				if (kind != PDECL)
86 					goto resume;
87 				yerror("Expected keyword begin after declarations, before statements");
88 				unyylex(&Y);
89 				yychar = YBEGIN;
90 				yylval = nullsem(YBEGIN);
91 				goto quiet;
92 			case YTHEN:
93 			case YELSE:
94 			case YDO:
95 				if (kind == PSTAT) {
96 					yychar = yylex();
97 					goto resume;
98 				}
99 				if (kind == PEXPR)
100 					goto resume;
101 				continue;
102 			case ')':
103 			case ']':
104 				if (kind != PEXPR)
105 					continue;
106 				if (brlev == 0)
107 					goto resume;
108 				if (brlev > 0)
109 					brlev--;
110 				continue;
111 			case '(':
112 			case '[':
113 				brlev++;
114 				continue;
115 			case ',':
116 				if (brlev != 0)
117 					continue;
118 			case YOF:
119 			case YTO:
120 			case YDOWNTO:
121 				if (kind == PEXPR)
122 					goto resume;
123 				continue;
124 #ifdef PI
125 			/*
126 			 * A rough approximation for now
127 			 * Should be much more lenient on suppressing
128 			 * warnings.
129 			 */
130 			case YID:
131 				syneflg = TRUE;
132 				continue;
133 #endif
134 		}
135 resume:
136 	if (yyOshifts >= 2) {
137 		if (yychar != -1)
138 			unyylex(&Y);
139 		copy(&Y, &oldpos, sizeof Y);
140 		yerror(cp);
141 		yychar = yylex();
142 	}
143 quiet:
144 	if (yyshifts - ishifts > 2 && opt('r')) {
145 		setpfx('r');
146 		yerror("Parsing resumes");
147 	}
148 	/*
149 	 * If we paniced in the statement part,
150 	 * and didn't stop at a ';', then we insert
151 	 * a ';' to prevent the recovery from immediately
152 	 * inserting one and complaining about it.
153 	 */
154 	if (kind == PSTAT && yychar != ';') {
155 		unyylex(&Y);
156 		yyshifts--;
157 		yytshifts--;
158 		yychar = ';';
159 		yylval = nullsem(';');
160 	}
161 }
162