1 /* LLgen generated code from source tokens.g */
3 #define LL_LEXI scanner
5 #if __STDC__ || __cplusplus
8 #define LL_LEXI scanner
9 /* $Id: incl,v 2.13 1997/02/21 15:44:09 ceriel Exp $ */
13 #define LL_assert(x) assert(x)
15 #define LL_assert(x) /* nothing */
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)
25 #define LLscan(x) if ((LLsymb = LL_LEXI()) != x) LLerror(x)
28 extern unsigned int LLscnt[];
29 extern unsigned int LLtcnt[];
33 extern int LLstartsymb;
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]++
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 *);
51 extern void LLscan(int);
54 extern int LLfirst(int, int);
57 extern void LLnc_recover(void);
59 #else /* not LL_ANSI_C */
74 extern LLnc_recover();
76 #endif /* not LL_ANSI_C */
87 static string rcsidc = "$Id: tokens.g,v 2.17 1997/02/21 15:44:44 ceriel Exp $";
90 /* Here are defined : */
96 # ifdef LINE_DIRECTIVE
97 STATIC linedirective();
100 STATIC string vallookup();
108 * Structure for a keyword
111 typedef struct keyword {
117 * The list of keywords, the most often used keywords come first.
118 * Linear search is used, as there are not many keywords
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 },
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 },
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 */
148 copyact(ch1,ch2,flag,level) char ch1,ch2; {
150 * Copy an action to file f. Opening bracket is ch1, closing bracket
152 * If flag & 1, copy opening and closing parameters too.
153 * If flag & 2, don't allow ','.
155 static int text_seen = 0;
157 register ch; /* Current char */
158 register match; /* used to read strings */
159 int saved = linecount;
161 int sav_strip = strip_grammar;
164 if (ch1 == '{' || flag != 1) strip_grammar = 0;
167 nparams = 0; /* count comma's */
169 fprintf(f,"# line %d \"%s\"\n", linecount,f_input);
171 if (level || (flag & 1)) putc(ch1,f);
176 if (text_seen) nparams++;
178 if (level || (flag & 1)) putc(ch,f);
179 if (strip_grammar != sav_strip) {
180 if (ch1 == '{' || flag != 1) putchar(ch);
182 strip_grammar = sav_strip;
189 error(linecount,"Parentheses mismatch");
193 copyact('(',')',flag,level+1);
197 copyact('{','}',flag,level+1);
201 copyact('[',']',flag,level+1);
216 if (! level && text_seen) {
219 if (ch == ',' && (flag & 2)) {
220 warning(linecount, "Parameters may not be separated with a ','");
228 * watch out for brackets in strings, they do not
234 while((ch = input())) {
235 if (ch == match) break;
241 error(linecount,"Newline in string");
246 if (ch == match) break;
249 if (!level) error(saved,"Action does not terminate");
250 strip_grammar = sav_strip;
253 if (c_class[ch] != ISSPA) text_seen = 1;
261 * Lexical analyser, what else
263 register int ch; /* Current char */
264 register char *p = ltext;
265 int reserved = 0; /* reserved word? */
266 char *max = <ext[LTEXTSZ - 1];
268 int expect_expr = nextexpr;
272 if (savedtok.t_tokno) {
273 /* A token has been inserted.
274 * Now deliver the last lextoken again
277 savedtok.t_tokno = 0;
278 return lextoken.t_tokno;
282 if (ch == EOF) return ch;
283 # ifdef LINE_DIRECTIVE
284 if (ch == '#' && !nostartline) {
289 switch(c_class[ch]) {
292 copyact('{', '}', in_production, 0);
297 copyact('(', ')', 1, 0);
301 copyact('(', ')', in_production != 0 ? 0 : 2, 0);
302 if (nparams == 0) fseek(fact, off, 0);
303 lextoken.t_num = nparams;
308 if (ch == '\n' || ch == EOF) {
309 error(linecount,"Missing '");
312 if (ch == '\'') break;
321 lextoken.t_string = ltext;
331 i = 10 * i + (ch - '0');
333 } while (c_class[ch] == ISDIG);
345 if (reserved && ch >= 'A' && ch <= 'Z') {
351 } while (c_class[ch] == ISDIG || c_class[ch] == ISLET);
355 * Now search for the keyword
361 if (! strcmp(ltext,w->w_word)) {
363 * Return token number.
365 if (w->w_value == C_IF ||
366 w->w_value == C_WHILE) {
373 error(linecount,"Illegal reserved word");
375 lextoken.t_string = ltext;
381 static int backupc; /* for unput() */
382 static int nonline; /* = 1 if last char read was a newline */
386 * Low level input routine, used by all other input routines
391 /* Last char was "unput()". Deliver it again
396 if ((c = getc(finput)) == EOF) {
400 # ifdef LINE_DIRECTIVE
405 # ifdef LINE_DIRECTIVE
410 if (c == '\n') nonline = 0;
411 if (strip_grammar) putchar(c);
424 * Skip comment. If flag != 0, the comment is inside a fragment
425 * of C-code, so keep it.
428 int saved; /* line count on which comment starts */
431 if (input() != '*') error(linecount,"Illegal comment");
432 if (flag) putc('*', fact);
435 if (flag) putc(ch, fact);
438 if (flag) putc(ch, fact);
439 if (ch == '/') return;
442 error(saved,"Comment does not terminate");
445 # ifdef LINE_DIRECTIVE
449 * Read a line directive
453 string s_error = "Illegal line directive";
459 * Do not skip newlines
462 } while (ch != '\n' && c_class[ch] != ISDIG);
464 error(linecount,s_error);
469 i = i*10 + (ch - '0');
471 } while (c_class[ch] == ISDIG);
472 while (ch != '\n' && ch != '"') ch = input();
477 } while (ch != '"' && ch != '\n');
479 error(linecount,s_error);
485 } while (ch != '\n');
487 * Remember the file name
489 if (strcmp(f_input,ltext)) f_input = store(ltext);
498 * Look up the keyword that has token number s
500 register p_keyw p = resword;
503 if (p->w_value == s) return p->w_word;
510 cpy(s,p,inserted) register string p; {
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
516 register string t = 0;
520 if (!inserted) t = lextoken.t_string;
521 else t = "identifier";
529 t = lextoken.t_string;
538 t = "C parameter section";
547 if (!t && (t = vallookup(s))) {
551 * We have a string for the token. Copy it
553 while (*t) *p++ = *t++;
554 if (s == C_LITERAL && !inserted) {
560 * The token is a literal
563 if (s >= 040 && s <= 0176) *p++ = 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);
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
594 strcpy(buf, "end-of-file expected");
603 do *s++ = *t; while (*t++);
606 t = " inserted in front of ";
607 do *s++ = *t++; while (*t);
612 * Save the current token and make up some
613 * attributes for the inserted token
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;
624 error(linecount, "%s", buf);
625 /* Don't change this line to
626 * error(linecount, buf).
627 * The string in "buf" might contain '%' ...
631 /* To prevent warnings from copyact */