Pristine Ack-5.5
[Ack-5.5.git] / util / LLgen / src / tokens.c.dist
1 /* LLgen generated code from source tokens.g */
2 #include "Lpars.h"
3 #define LL_LEXI scanner
4 #define LLNOFIRSTS
5 #if __STDC__ || __cplusplus
6 #define LL_ANSI_C 1
7 #endif
8 #define LL_LEXI scanner
9 /* $Id: incl,v 2.13 1997/02/21 15:44:09 ceriel Exp $ */
10 #ifdef LL_DEBUG
11 #include <assert.h>
12 #include <stdio.h>
13 #define LL_assert(x)    assert(x)
14 #else
15 #define LL_assert(x)    /* nothing */
16 #endif
17
18 extern int LLsymb;
19
20 #define LL_SAFE(x)      /* Nothing */
21 #define LL_SSCANDONE(x) if (LLsymb != x) LLsafeerror(x)
22 #define LL_SCANDONE(x)  if (LLsymb != x) LLerror(x)
23 #define LL_NOSCANDONE(x) LLscan(x)
24 #ifdef LL_FASTER
25 #define LLscan(x)       if ((LLsymb = LL_LEXI()) != x) LLerror(x)
26 #endif
27
28 extern unsigned int LLscnt[];
29 extern unsigned int LLtcnt[];
30 extern int LLcsymb;
31
32 #if LL_NON_CORR
33 extern int LLstartsymb;
34 #endif
35
36 #define LLsdecr(d)      {LL_assert(LLscnt[d] > 0); LLscnt[d]--;}
37 #define LLtdecr(d)      {LL_assert(LLtcnt[d] > 0); LLtcnt[d]--;}
38 #define LLsincr(d)      LLscnt[d]++
39 #define LLtincr(d)      LLtcnt[d]++
40
41 #if LL_ANSI_C
42 extern int LL_LEXI(void);
43 extern void LLread(void);
44 extern int LLskip(void);
45 extern int LLnext(int);
46 extern void LLerror(int);
47 extern void LLsafeerror(int);
48 extern void LLnewlevel(unsigned int *);
49 extern void LLoldlevel(unsigned int *);
50 #ifndef LL_FASTER
51 extern void LLscan(int);
52 #endif
53 #ifndef LLNOFIRSTS
54 extern int LLfirst(int, int);
55 #endif
56 #if LL_NON_CORR
57 extern void LLnc_recover(void);
58 #endif
59 #else /* not LL_ANSI_C */
60 extern LLread();
61 extern int LLskip();
62 extern int LLnext();
63 extern LLerror();
64 extern LLsafeerror();
65 extern LLnewlevel();
66 extern LLoldlevel();
67 #ifndef LL_FASTER
68 extern LLscan();
69 #endif
70 #ifndef LLNOFIRSTS
71 extern int LLfirst();
72 #endif
73 #if LL_NON_CORR
74 extern LLnc_recover();
75 #endif
76 #endif /* not LL_ANSI_C */
77
78 # line 20 "tokens.g"
79
80 # include "types.h"
81 # include "io.h"
82 # include "extern.h"
83 # include "assert.h"
84 # include "cclass.h"
85
86 # ifndef NORCSID
87 static string   rcsidc = "$Id: tokens.g,v 2.17 1997/02/21 15:44:44 ceriel Exp $";
88 # endif
89
90 /* Here are defined : */
91 extern int      scanner();
92 extern          LLmessage();
93 extern int      input();
94 extern          unput();
95 extern          skipcomment();
96 # ifdef LINE_DIRECTIVE
97 STATIC          linedirective();
98 # endif
99 STATIC string   cpy();
100 STATIC string   vallookup();
101 STATIC          copyact();
102
103 static int      nparams;
104 # line 75 "tokens.g"
105
106
107 /*
108  * Structure for a keyword
109  */
110
111 typedef struct keyword {
112         string  w_word;
113         int     w_value;
114 } t_keyw, *p_keyw;
115
116 /*
117  * The list of keywords, the most often used keywords come first.
118  * Linear search is used, as there are not many keywords
119  */
120
121 static t_keyw resword[] = {
122         { "token",      C_TOKEN         },
123         { "avoid",      C_AVOID         },
124         { "prefer",     C_PREFER        },
125         { "persistent", C_PERSISTENT    },
126         { "default",    C_DEFAULT       },
127         { "if",         C_IF            },
128         { "while",      C_WHILE         },
129         { "first",      C_FIRST         },
130         { "start",      C_START         },
131         { "lexical",    C_LEXICAL       },
132         { "onerror",    C_ONERROR       },
133         { "prefix",     C_PREFIX        },
134 #ifdef NON_CORRECTING
135         { "substart",   C_SUBSTART      },
136         { "erroneous",  C_ERRONEOUS     },
137         { "illegal",    C_ILLEGAL       },
138 #endif
139         { 0,            0               }
140 };
141
142 static t_token  savedtok;       /* to save lextoken in case of an insertion */
143 # ifdef LINE_DIRECTIVE
144 static  int     nostartline;    /* = 0 if at the start of a line */
145 # endif
146
147 STATIC
148 copyact(ch1,ch2,flag,level) char ch1,ch2; {
149         /*
150          * Copy an action to file f. Opening bracket is ch1, closing bracket
151          * is ch2.
152          * If flag & 1, copy opening and closing parameters too.
153          * If flag & 2, don't allow ','.
154          */
155         static int      text_seen = 0;
156         register        FILE *f;
157         register        ch;             /* Current char */
158         register        match;          /* used to read strings */
159         int             saved = linecount;
160                                         /* save linecount */
161         int             sav_strip = strip_grammar;
162
163         f = fact;
164         if (ch1 == '{' || flag != 1) strip_grammar = 0;
165         if (!level) {
166                 text_seen = 0;
167                 nparams = 0;                    /* count comma's */
168                 putc('\0',f);
169                 fprintf(f,"# line %d \"%s\"\n", linecount,f_input);
170         }
171         if (level || (flag & 1)) putc(ch1,f);
172         for (;;) {
173                 ch = input();
174                 if (ch == ch2) {
175                         if (!level) {
176                                 if (text_seen) nparams++;
177                         }
178                         if (level || (flag & 1)) putc(ch,f);
179                         if (strip_grammar != sav_strip) {
180                                 if (ch1 == '{' || flag != 1) putchar(ch);
181                         }
182                         strip_grammar = sav_strip;
183                         return;
184                 }
185                 switch(ch) {
186                   case ')':
187                   case '}':
188                   case ']':
189                         error(linecount,"Parentheses mismatch");
190                         break;
191                   case '(':
192                         text_seen = 1;
193                         copyact('(',')',flag,level+1);
194                         continue;
195                   case '{':
196                         text_seen = 1;
197                         copyact('{','}',flag,level+1);
198                         continue;
199                   case '[':
200                         text_seen = 1;
201                         copyact('[',']',flag,level+1);
202                         continue;
203                   case '/':
204                         ch = input();
205                         unput(ch);
206                         if (ch == '*') {
207                                 putc('/', f);
208                                 skipcomment(1);
209                                 continue;
210                         }
211                         ch = '/';
212                         text_seen = 1;
213                         break;
214                   case ';':
215                   case ',':
216                         if (! level && text_seen) {
217                                 text_seen = 0;
218                                 nparams++;
219                                 if (ch == ',' && (flag & 2)) {
220                                         warning(linecount, "Parameters may not be separated with a ','");
221                                         ch = ';';
222                                 }
223                         }
224                         break;
225                   case '\'':
226                   case '"' :
227                         /*
228                          * watch out for brackets in strings, they do not
229                          * count !
230                          */
231                         text_seen = 1;
232                         match = ch;
233                         putc(ch,f);
234                         while((ch = input())) {
235                                 if (ch == match) break;
236                                 if (ch == '\\') {
237                                         putc(ch,f);
238                                         ch = input();
239                                 }
240                                 if (ch == '\n') {
241                                         error(linecount,"Newline in string");
242                                         unput(match);
243                                 }
244                                 putc(ch,f);
245                         }
246                         if (ch == match) break;
247                         /* Fall through */
248                     case EOF :
249                         if (!level) error(saved,"Action does not terminate");
250                         strip_grammar = sav_strip;
251                         return;
252                     default:
253                         if (c_class[ch] != ISSPA) text_seen = 1;
254                 }
255                 putc(ch,f);
256         }
257 }
258
259 scanner() {
260         /*
261          * Lexical analyser, what else
262          */
263         register int    ch;             /* Current char */
264         register char *p = ltext;
265         int             reserved = 0;   /* reserved word? */
266         char            *max = &ltext[LTEXTSZ - 1];
267         static int      nextexpr;
268         int             expect_expr = nextexpr;
269         long            off;
270
271         nextexpr = 0;
272         if (savedtok.t_tokno) {
273                                 /* A token has been inserted.
274                                  * Now deliver the last lextoken again
275                                  */
276                 lextoken = savedtok;
277                 savedtok.t_tokno = 0;
278                 return lextoken.t_tokno;
279         }
280         for (;;) {
281                 ch = input();
282                 if (ch == EOF) return ch;
283 # ifdef LINE_DIRECTIVE
284                 if (ch == '#' && !nostartline) {
285                         linedirective();
286                         continue;
287                 }
288 # endif
289                 switch(c_class[ch]) {
290                   case ISACT :
291                         if (ch == '{') {
292                                 copyact('{', '}', in_production, 0);
293                                 return C_ACTION;
294                         }
295                         assert(ch == '(');
296                         if (expect_expr) {
297                                 copyact('(', ')', 1, 0);
298                                 return C_EXPR;
299                         }
300                         off = ftell(fact);
301                         copyact('(', ')', in_production != 0 ? 0 : 2, 0);
302                         if (nparams == 0) fseek(fact, off, 0);
303                         lextoken.t_num = nparams;
304                         return C_PARAMS;
305                   case ISLIT :
306                         for (;;) {
307                                 ch = input();
308                                 if (ch == '\n' || ch == EOF) {
309                                         error(linecount,"Missing '");
310                                         break;
311                                 }
312                                 if (ch == '\'') break;
313                                 if (ch == '\\') {
314                                         *p++ = ch;
315                                         ch = input();
316                                 }
317                                 *p++ = ch;
318                                 if (p > max) p--;
319                         }
320                         *p = '\0';
321                         lextoken.t_string = ltext;
322                         return C_LITERAL;
323                   case ISCOM :
324                         skipcomment(0);
325                         /* Fall through */
326                   case ISSPA :
327                         continue;
328                   case ISDIG : {
329                         register i = 0;
330                         do {
331                                 i = 10 * i + (ch - '0');
332                                 ch= input();
333                         } while (c_class[ch] == ISDIG);
334                         lextoken.t_num = i;
335                         unput(ch);
336                         return C_NUMBER; }
337                   default:
338                         return ch;
339                   case ISKEY :
340                         reserved = 1;
341                         ch = input();
342                         /* Fall through */
343                   case ISLET :
344                         do {
345                                 if (reserved && ch >= 'A' && ch <= 'Z') {
346                                         ch += 'a' - 'A';
347                                 }
348                                 *p++ = ch;
349                                 if (p > max) p--;
350                                 ch = input();
351                         } while (c_class[ch] == ISDIG || c_class[ch] == ISLET);
352                         unput(ch);
353                         *p = '\0';
354                         if (reserved) { /*
355                                          * Now search for the keyword
356                                          */
357                                 register p_keyw w;
358
359                                 w = resword;
360                                 while (w->w_word) {
361                                         if (! strcmp(ltext,w->w_word)) {
362                                                 /*
363                                                  * Return token number.
364                                                  */
365                                                 if (w->w_value == C_IF ||
366                                                     w->w_value == C_WHILE) {
367                                                         nextexpr = 1;
368                                                 }
369                                                 return w->w_value;
370                                         }
371                                         w++;
372                                 }
373                                 error(linecount,"Illegal reserved word");
374                         }
375                         lextoken.t_string = ltext;
376                         return C_IDENT;
377                 }
378         }
379 }
380
381 static int      backupc;        /* for unput() */
382 static int      nonline;        /* = 1 if last char read was a newline */
383
384 input() {
385         /*
386          * Low level input routine, used by all other input routines
387          */
388         register        c;
389
390         if (c = backupc) {
391                         /* Last char was "unput()". Deliver it again
392                          */
393                 backupc = 0;
394                 return c;
395         }
396         if ((c = getc(finput)) == EOF) {
397                 nonline = 0;
398                 return c;
399         }
400 # ifdef LINE_DIRECTIVE
401         nostartline = 1;
402 # endif
403         if (!nonline) {
404                 linecount++;
405 # ifdef LINE_DIRECTIVE
406                 nostartline = 0;
407 # endif
408                 nonline = 1;
409         }
410         if (c == '\n') nonline = 0;
411         if (strip_grammar) putchar(c);
412         return c;
413 }
414
415 unput(c) {
416         /*
417          * "unread" c
418          */
419         backupc = c;
420 }
421
422 skipcomment(flag) {
423         /*
424          * Skip comment. If flag != 0, the comment is inside a fragment
425          * of C-code, so keep it.
426          */
427         register int    ch;
428         int             saved;  /* line count on which comment starts */
429
430         saved = linecount;
431         if (input() != '*') error(linecount,"Illegal comment");
432         if (flag) putc('*', fact);
433         do {
434                 ch = input();
435                 if (flag) putc(ch, fact);
436                 while (ch == '*') {
437                         ch = input();
438                         if (flag) putc(ch, fact);
439                         if (ch == '/') return;
440                 }
441         } while (ch != EOF);
442         error(saved,"Comment does not terminate");
443 }
444
445 # ifdef LINE_DIRECTIVE
446 STATIC
447 linedirective() {
448         /*
449          * Read a line directive
450          */
451         register int    ch;
452         register int    i;
453         string          s_error = "Illegal line directive";
454         string          store();
455         register string c;
456
457         do {    /*
458                  * Skip to next digit
459                  * Do not skip newlines
460                  */
461                 ch = input();
462         } while (ch != '\n' && c_class[ch] != ISDIG);
463         if (ch == '\n') {
464                 error(linecount,s_error);
465                 return;
466         }
467         i = 0;
468         do  {
469                 i = i*10 + (ch - '0');
470                 ch = input();
471         } while (c_class[ch] == ISDIG);
472         while (ch != '\n' && ch != '"') ch = input();
473         if (ch == '"') {
474                 c = ltext;
475                 do {
476                         *c++ = ch = input();
477                 } while (ch != '"' && ch != '\n');
478                 if (ch == '\n') {
479                         error(linecount,s_error);
480                         return;
481                 }
482                 *--c = '\0';
483                 do {
484                         ch = input();
485                 } while (ch != '\n');
486                 /*
487                  * Remember the file name
488                  */
489                 if (strcmp(f_input,ltext)) f_input = store(ltext);
490         }
491         linecount = i;
492 }
493 # endif
494
495 STATIC string
496 vallookup(s) {
497         /*
498          * Look up the keyword that has token number s
499          */
500         register p_keyw p = resword;
501
502         while (p->w_value) {
503                 if (p->w_value == s) return p->w_word;
504                 p++;
505         }
506         return 0;
507 }
508
509 STATIC string
510 cpy(s,p,inserted) register string p; {
511         /*
512          * Create a piece of error message for token s and put it at p.
513          * inserted = 0 if the token s was deleted (in which case we have
514          * attributes), else it was inserted
515          */
516         register string t = 0;
517
518         switch(s) {
519           case C_IDENT :
520                 if (!inserted) t = lextoken.t_string;
521                 else t = "identifier";
522                 break;
523           case C_NUMBER :
524                 t = "number";
525                 break;
526           case C_LITERAL :
527                 if (!inserted) {
528                         *p++ = '\'';
529                         t = lextoken.t_string;
530                         break;
531                 }
532                 t = "literal";
533                 break;
534           case C_ACTION:
535                 t = "C action";
536                 break;
537           case C_PARAMS:
538                 t = "C parameter section";
539                 break;
540           case C_EXPR:
541                 t = "C expression";
542                 break;
543           case EOFILE :
544                 t = "end-of-file";
545                 break;
546         }
547         if (!t && (t = vallookup(s))) {
548                 *p++ = '%';
549         }
550         if (t) {        /*
551                          * We have a string for the token. Copy it
552                          */
553                 while (*t) *p++ = *t++;
554                 if (s == C_LITERAL && !inserted) {
555                         *p++ = '\'';
556                 }
557                 return p;
558         }
559         /*
560          * The token is a literal
561          */
562         *p++ = '\'';
563         if (s >= 040 && s <= 0176) *p++ = s;
564         else {
565             *p++ = '\\';
566             switch(s) {
567               case '\b' : *p++ = 'b'; break;
568               case '\f' : *p++ = 'f'; break;
569               case '\n' : *p++ = 'n'; break;
570               case '\r' : *p++ = 'r'; break;
571               case '\t' : *p++ = 't'; break;
572               default : *p++='0'+((s&0377)>>6); *p++='0'+((s>>3)&07);
573                         *p++='0'+(s&07);
574             }
575         }
576         *p++ = '\'';
577         return p;
578 }
579
580 string strcpy();
581
582 LLmessage(d) {
583         /*
584          * d is either 0, in which case the current token has been deleted,
585          * or non-zero, in which case it represents a token that is inserted
586          * before the current token
587          */
588         register string s,t;
589         char            buf[128];
590
591         nerrors++;
592         s = buf;
593         if (d < 0) {
594                 strcpy(buf, "end-of-file expected");
595         }
596         else if (d == 0) {
597 #ifdef LLNONCORR
598                 t = " unexpected";
599 #else
600                 t = " deleted";
601 #endif
602                 s = cpy(LLsymb,s,0);
603                 do *s++ = *t; while (*t++);
604         } else {
605                 s = cpy(d,s,1);
606                 t = " inserted in front of ";
607                 do *s++ = *t++; while (*t);
608                 s = cpy(LLsymb,s,0);
609                 *s = '\0';
610         }
611         if (d > 0) {    /*
612                          * Save the current token and make up some
613                          * attributes for the inserted token
614                          */
615                 savedtok = lextoken;
616                 savedtok.t_tokno = LLsymb;
617                 if (d == C_IDENT) lextoken.t_string = "dummy_identifier";
618                 else if (d == C_LITERAL) lextoken.t_string = "dummy_literal";
619                 else if (d == C_NUMBER) lextoken.t_num = 1;
620         }
621 #ifdef LLNONCORR
622         else
623 #endif
624         error(linecount, "%s", buf);
625                         /* Don't change this line to 
626                          * error(linecount, buf).
627                          * The string in "buf" might contain '%' ...
628                          */
629 #ifdef LLNONCORR
630         in_production = 1;
631                         /* To prevent warnings from copyact */
632 #endif
633 }
634