Pristine Ack-5.5
[Ack-5.5.git] / util / LLgen / lib / rec
1 /* 
2  * Some grammar independent code.
3  * This file is copied into Lpars.c.
4  */
5
6 #ifndef lint
7 static char *rcsid = "$Id: rec,v 2.24 1998/11/10 14:26:06 ceriel Exp $";
8 #endif
9
10 unsigned int    LLtcnt[LL_NTERMINALS];
11 unsigned int    LLscnt[LL_NSETS];
12 int             LLcsymb, LLsymb;
13 static int      LLlevel;
14
15 #if LL_NON_CORR
16 int             LLstartsymb;
17 static int      fake_eof = 0;
18 #endif
19
20 #if LL_ANSI_C
21 #define LL_VOIDCST (void)
22 void    LLmessage(int);
23 #else
24 #define LL_VOIDCST
25 #endif
26 #ifdef LL_USERHOOK
27 #if LL_ANSI_C
28 static int      LLdoskip(int);
29 static int      LLuserhook(int, int*);
30 #else
31 static int      LLdoskip();
32 static int      LLuserhook();
33 #endif
34 #endif
35
36 #ifndef LL_FASTER
37 #if LL_ANSI_C
38 void LLscan(int t)
39 #else
40 LLscan(t)
41         int     t;
42 #endif
43 {
44         /*
45          * Check if the next symbol is equal to the parameter
46          */
47
48 #if LL_NON_CORR
49         /* See if the error recovery has eaten an eof */
50         if (fake_eof) {
51                 LLsymb = EOFILE;
52                 fake_eof = 0;
53         }
54         else {
55                 LLsymb = LL_LEXI();
56         }
57
58         if (LLsymb == t) {
59 #else
60         if ((LLsymb = LL_LEXI()) == t) {
61 #endif
62
63 #if LL_NON_CORR
64                 /* Check if a previous parser has 'crashed', in that
65                  * case continue with non-correcting parser 
66                  */
67                 if (err_seen && !nc_done) {
68                         LLnc_recover();
69                         nc_done = 1;
70                         /* Remember that the error recovery has eaten an eof */
71                         fake_eof = 1;
72                         if (t != LLsymb) {
73                                 LLerror(t);
74                         }
75                         else
76                                 return;
77                 }
78 #endif
79                 return;
80         }
81         /*
82          * If we come here, an error has been detected
83          */
84         LLerror(t);
85 }
86 #endif
87
88 #if LL_ANSI_C
89 void LLread(void) {
90 #else
91 LLread() {
92 #endif
93
94 #if LL_NON_CORR
95         /* Again, check if another parser has crashed,
96          * in that case intercept and go to the
97          * non-correcting parser
98          */
99
100         if (err_seen && !nc_done) {
101                 LLnc_recover();
102                 nc_done = 1;
103                 /* Pretend we read end of file */
104                 LLsymb = EOFILE;
105                 LLcsymb = LLindex[EOFILE];
106                 fake_eof = 0;
107                 return;
108         }
109
110         if (fake_eof) {
111                 LLsymb = EOFILE;
112                 LLcsymb = LLindex[EOFILE];
113                 fake_eof = 0;
114                 return;
115         }
116 #endif
117
118         for (;;) {
119                 if ((LLcsymb = LLindex[(LLsymb = LL_LEXI())]) >= 0) return;
120                 LLmessage(0);
121         }
122         /* NOTREACHED */
123 }
124
125 #if LL_ANSI_C
126 void LLerror(int t)
127 #else
128 LLerror(t)
129         int     t;
130 #endif
131 {
132         register int i;
133
134         if (t == EOFILE && LLsymb <= 0) return;
135 #ifdef LL_NEWMESS
136         if (t == EOFILE) {
137 #ifdef LL_USERHOOK
138                 static int lst[] = { EOFILE, 0 };
139                 LL_VOIDCST LLuserhook(EOFILE, lst);
140 #endif /* LL_USERHOOK */
141                 if (LLsymb != EOFILE && LLsymb > 0) {
142                         LLmessage(-1);
143                         while ((LLsymb = LL_LEXI()) > 0 && LLsymb != EOFILE) 
144                                 /* nothing */ ;
145                 }
146                 return;
147         }
148 #endif
149
150 #if LL_NON_CORR
151         if ((!nc_done) && (LLsymb > 0) && (LLsymb != EOFILE)) {
152                 LLmessage(0);
153                 LLnc_recover();
154                 nc_done = 1;
155                 LLsymb = EOFILE;
156         }
157 #endif
158         
159         if ((LLcsymb = LLindex[LLsymb]) < 0) {
160                 LLmessage(0);
161                 LLread();
162         }
163         i = LLindex[t];
164         LLtcnt[i]++;
165 #ifdef LL_USERHOOK
166         LL_VOIDCST LLdoskip(t);
167 #else
168         LL_VOIDCST LLskip();
169 #endif
170         LLtcnt[i]--;
171         if (LLsymb != t) {
172 #if LL_NON_CORR
173                 /* A little kludge here; when using non-correcting recovery
174                  * it can happen that a program is correct but incomplete. 
175                  * Here, we test this, and make sure the appropriate 
176                  * message is generated 
177                  */
178                 if (! nc_done) {
179                         int oldLLsymb;
180                         oldLLsymb = LLsymb;
181                         LLsymb = EOFILE;
182                         LLmessage(0);
183                         nc_done = 1;    
184                 /* Not really, but to prevent more than 1 error message */
185                         LLsymb = oldLLsymb;
186                 }
187 #endif
188                 LLmessage(t);
189         }
190 }
191
192 #if LL_ANSI_C
193 void LLsafeerror(int t)
194 #else
195 LLsafeerror(t)
196         int     t;
197 #endif
198 {
199         if (t == EOFILE && LLsymb <= 0) return;
200 #ifdef LL_NEWMESS
201         if (t == EOFILE) {
202 #ifdef LL_USERHOOK
203                 static int lst[] = { EOFILE, 0 };
204                 LL_VOIDCST LLuserhook(EOFILE, lst);
205 #endif /* LL_USERHOOK */
206                 if (LLsymb != EOFILE && LLsymb > 0) {
207                         LLmessage(-1);
208                         while ((LLsymb = LL_LEXI()) > 0 && LLsymb != EOFILE) 
209                                 /* nothing */ ;
210                 }
211                 return;
212         }
213 #endif
214 #if LL_NON_CORR
215         if ((!nc_done) && (LLsymb > 0) && (LLsymb != EOFILE)) {
216                 LLmessage(0);
217                 LLnc_recover();
218                 nc_done = 1;
219                 LLsymb = EOFILE;
220         }
221         /* A little kludge here; when using non-correcting recovery
222          * it can happen that a program is correct but incomplete.
223          * Here, we test this, and make sure the appropriate
224          * message is generated
225          */
226         if (! nc_done) {
227                 int oldLLsymb;
228                 oldLLsymb = LLsymb;
229                 LLsymb = EOFILE;
230                 LLmessage(0);
231                 nc_done = 1;
232         /* Not really, but to prevent more than 1 error message */
233                 LLsymb = oldLLsymb;
234         }
235 #endif
236         LLmessage(t);
237 }
238
239 #ifndef LLNOFIRSTS
240 #if LL_ANSI_C
241 int LLfirst(int x, int d) {
242 #else
243 int LLfirst(x, d) {
244 #endif
245         register int i;
246
247         return (i = LLindex[x]) >= 0 &&
248                 (LLsets[d + (i >> 3)] & (1 << (i & 07)));
249 }
250 #endif
251
252 #if LL_ANSI_C
253 int LLnext(int n)
254 #else
255 int LLnext(n)
256         int     n;
257 #endif
258 {
259         /*      returns: 0 if the current symbol is'nt skipped, and it
260                          is'nt a member of "n",
261                          1 if we have a new symbol, but it is'nt a member,
262                          2 if the current symbol is a member,
263                          and 3 if we have a new symbol and it is a member.
264                 So, the low order bit indicates wether we have a new symbol,
265                 and the next bit indicates wether it is a member of "n".
266         */
267
268         int retval = 0;
269
270         if (LLskip()) retval = 1;
271         if (n <= 0 && LLsets[(LLcsymb >> 3) - n] & (1 << (LLcsymb & 07))) {
272                 retval |= 2;
273         }
274         else if (n > 0 && LLcsymb == LLindex[n]) retval |= 2;
275         return retval;
276 }
277
278 #if LL_ANSI_C
279 int LLskip(void) {
280 #else
281 int LLskip() {
282 #endif
283         /*      returns 0 if the current symbol is'nt skipped, and
284                 1 if it is, t.i., we have a new symbol
285         */
286 #ifdef LL_USERHOOK
287         return LLdoskip(0);
288 }
289
290 #if LL_ANSI_C
291 extern void LL_USERHOOK(int, int *);
292 static int LLuserhook(int e, int *list)
293 #else
294 static int LLuserhook(e, list)
295         int e;
296         int *list;
297 #endif
298 {
299         int old = LLsymb;
300         LL_USERHOOK(e, list);
301         LLread();
302         return LLsymb != old;
303 }
304
305 #if LL_ANSI_C
306 static void LLmklist(register int *list)
307 #else
308 static LLmklist(list)
309         register int *list;
310 #endif
311 {
312         char Xset[LL_SSIZE];
313         register char *p;
314         register int i;
315
316         for (p = &Xset[0]; p < &Xset[LL_SSIZE]; ) *p++ = 0;
317         for (i = 0; i < LL_NTERMINALS; i++) {
318                 if (LLtcnt[i] != 0) Xset[i >> 3] |= (1 << (i & 07));
319         }
320         for (i = LL_NSETS - 1; i >= 0; i--) if (LLscnt[i] != 0) {
321                 register char *q = &LLsets[LL_SSIZE * i];
322
323                 p = &Xset[0];
324                 while (p < &Xset[LL_SSIZE]) *p++ |= *q++;
325         }
326         for (i = 0; i < LL_NTERMINALS; i++) {
327                 if (Xset[i >> 3] & (1 << (i & 07))) {
328                         *list++ = LLtok[i];
329                 }
330         }
331         *list = 0;
332 }
333
334 #if LL_ANSI_C
335 static int LLdoskip(int e)
336 #else
337 static int LLdoskip(e)
338         int     e;
339 #endif
340 {
341         int LLx;
342         int list[LL_NTERMINALS+1];
343 #endif /* LL_USERHOOK */
344         register int i;
345         int retval;
346         int LLi, LLb;
347
348         retval = 0;
349 #ifdef LL_USERHOOK
350         LLmklist(list);
351         LLx = LLuserhook(e, list);
352         if (LLx) retval = 1;
353 #endif /* LL_USERHOOK */
354         for (;;) {
355                 if (LLtcnt[LLcsymb] != 0) {
356 #ifdef LL_USERHOOK
357                         if (!e || !LLx || LLcsymb == LLindex[e])
358 #endif
359                         return retval;
360                 }
361                 LLi = LLcsymb >> 3;
362                 LLb = 1 << (LLcsymb & 07);
363                 for (i = LL_NSETS - 1; i >= 0; i--) {
364                         if (LLscnt[i] != 0) {
365                                 if (LLsets[LL_SSIZE*i+LLi] & LLb) {
366 #ifdef LL_USERHOOK
367                                         if (!e || !LLx || LLcsymb == LLindex[e])
368 #endif
369                                         return retval;
370                                 }
371                         }
372                 }
373 #ifdef LL_USERHOOK
374                 if (LLx) {
375                         LLx = LLuserhook(e, list);
376                         continue;
377                 }
378 #endif /* LL_USERHOOK */
379 #if LL_NON_CORR
380                 if ((!nc_done) && (LLsymb > 0)) {
381                         LLmessage(0);
382                         LLnc_recover();
383                         nc_done = 1;
384                         fake_eof = 1;
385                 }
386                 else {
387                         LLmessage(0);
388                 }
389 #else
390                 LLmessage(0);
391 #endif
392                 retval = 1;
393                 LLread();
394         }
395         /* NOTREACHED */
396 }
397
398 #if LL_ANSI_C
399 void LLnewlevel(unsigned int *LLsinfo) {
400 #else
401 LLnewlevel(LLsinfo) unsigned int *LLsinfo; {
402 #endif
403         register int i;
404
405         if (LLlevel++) {
406                 LLsinfo[LL_NSETS+LL_NTERMINALS] = (unsigned) LLsymb;
407                 LLsinfo[LL_NSETS+LL_NTERMINALS+1] = (unsigned) LLcsymb;
408                 for (i = LL_NTERMINALS - 1; i >= 0; i--) {
409                         LLsinfo[i] = LLtcnt[i];
410                         LLtcnt[i] = 0;
411                 }
412                 for (i = LL_NSETS - 1; i >= 0; i--) {
413                         LLsinfo[LL_NTERMINALS+i] = LLscnt[i];
414                         LLscnt[i] = 0;
415                 }
416         }
417         LLtincr(0);
418 }
419
420 #if LL_ANSI_C
421 void LLoldlevel(unsigned int *LLsinfo) {
422 #else
423 LLoldlevel(LLsinfo) unsigned int *LLsinfo; {
424 #endif
425         register int i;
426
427         LLtdecr(0);
428 #ifdef LL_DEBUG
429         for (i = 0; i < LL_NTERMINALS; i++) LL_assert(LLtcnt[i] == 0);
430         for (i = 0; i < LL_NSETS; i++) LL_assert(LLscnt[i] == 0);
431 #endif
432         if (--LLlevel) {
433                 for (i = LL_NSETS - 1; i >= 0; i--) {
434                         LLscnt[i] = LLsinfo[LL_NTERMINALS+i];
435                 }
436                 for (i = LL_NTERMINALS - 1; i >= 0; i--) {
437                         LLtcnt[i] = LLsinfo[i];
438                 }
439                 LLsymb = (int) LLsinfo[LL_NSETS+LL_NTERMINALS];
440                 LLcsymb = (int) LLsinfo[LL_NSETS+LL_NTERMINALS+1];
441         }
442 }