]> git.saurik.com Git - bison.git/blame - src/reader.c
* src/lex.h: Prototype `lex.c' exported functions.
[bison.git] / src / reader.c
CommitLineData
1ff442ca 1/* Input parser for bison
41aca2e0 2 Copyright (C) 1984, 86, 89, 92, 98, 2000 Free Software Foundation, Inc.
1ff442ca 3
41aca2e0 4 This file is part of Bison, the GNU Compiler Compiler.
1ff442ca 5
41aca2e0
AD
6 Bison is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
1ff442ca 10
41aca2e0
AD
11 Bison is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
1ff442ca 15
41aca2e0
AD
16 You should have received a copy of the GNU General Public License
17 along with Bison; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
1ff442ca
NF
20
21
41aca2e0
AD
22/* Read in the grammar specification and record it in the format
23 described in gram.h. All guards are copied into the fguard file
24 and all actions into faction, in each case forming the body of a C
25 function (yyguard or yyaction) which contains a switch statement to
26 decide which guard or action to execute.
1ff442ca 27
41aca2e0 28 The entry point is reader (). */
1ff442ca 29
1ff442ca 30#include "system.h"
ceed8467 31#include "getargs.h"
1ff442ca 32#include "files.h"
7612000c 33#include "alloc.h"
1ff442ca
NF
34#include "symtab.h"
35#include "lex.h"
36#include "gram.h"
a0f6b076 37#include "complain.h"
6c89f1c1 38#include "output.h"
1ff442ca 39
6666f98f
AD
40#define LTYPESTR "\
41\n\
42#ifndef YYLTYPE\n\
43typedef\n\
44 struct yyltype\n\
45\
46 {\n\
47 int timestamp;\n\
48 int first_line;\n\
49 int first_column;\
50\n\
51 int last_line;\n\
52 int last_column;\n\
53 char *text;\n\
54 }\n\
55\
56 yyltype;\n\
57\n\
58#define YYLTYPE yyltype\n\
59#endif\n\
60\n"
1ff442ca
NF
61
62/* Number of slots allocated (but not necessarily used yet) in `rline' */
4a120d45 63static int rline_allocated;
1ff442ca 64
1ff442ca
NF
65extern bucket *symval;
66extern int numval;
1ff442ca
NF
67extern int expected_conflicts;
68extern char *token_buffer;
118fb205
JT
69extern int maxtoken;
70
118fb205 71extern void tabinit PARAMS((void));
118fb205
JT
72extern void free_symtab PARAMS((void));
73extern void open_extra_files PARAMS((void));
118fb205 74extern char *printable_version PARAMS((int));
1ff442ca
NF
75
76typedef
77 struct symbol_list
78 {
79 struct symbol_list *next;
80 bucket *sym;
81 bucket *ruleprec;
82 }
83 symbol_list;
84
85
4a120d45
JT
86extern void reader PARAMS((void));
87extern void reader_output_yylsp PARAMS((FILE *));
88
89static void read_declarations PARAMS((void));
90static void copy_definition PARAMS((void));
91static void parse_token_decl PARAMS((int, int));
92static void parse_start_decl PARAMS((void));
93static void parse_type_decl PARAMS((void));
94static void parse_assoc_decl PARAMS((int));
95static void parse_union_decl PARAMS((void));
96static void parse_expect_decl PARAMS((void));
97static char *get_type_name PARAMS((int, symbol_list *));
98static void copy_guard PARAMS((symbol_list *, int));
99static void parse_thong_decl PARAMS((void));
100static void copy_action PARAMS((symbol_list *, int));
101static bucket *gensym PARAMS((void));
102static void readgram PARAMS((void));
103static void record_rule_line PARAMS((void));
104static void packsymbols PARAMS((void));
105static void output_token_defines PARAMS((FILE *));
106static void packgram PARAMS((void));
118fb205 107
2686a6e7
JT
108#if 0
109static int get_type PARAMS((void));
110#endif
1ff442ca
NF
111
112int lineno;
1ff442ca 113char **tags;
d019d655 114short *user_toknums;
4a120d45
JT
115static symbol_list *grammar;
116static int start_flag;
117static bucket *startval;
1ff442ca
NF
118
119/* Nonzero if components of semantic values are used, implying
120 they must be unions. */
121static int value_components_used;
122
123static int typed; /* nonzero if %union has been seen. */
124
125static int lastprec; /* incremented for each %left, %right or %nonassoc seen */
126
127static int gensym_count; /* incremented for each generated symbol */
128
129static bucket *errtoken;
5b2e3c89 130static bucket *undeftoken;
1ff442ca
NF
131
132/* Nonzero if any action or guard uses the @n construct. */
133static int yylsp_needed;
134
0d533154
AD
135\f
136/*===================\
137| Low level lexing. |
138\===================*/
943819bf
RS
139
140static void
118fb205 141skip_to_char (int target)
943819bf
RS
142{
143 int c;
144 if (target == '\n')
a0f6b076 145 complain (_(" Skipping to next \\n"));
943819bf 146 else
a0f6b076 147 complain (_(" Skipping to next %c"), target);
943819bf
RS
148
149 do
0d533154 150 c = skip_white_space ();
943819bf 151 while (c != target && c != EOF);
a083fbbf 152 if (c != EOF)
0d533154 153 ungetc (c, finput);
943819bf
RS
154}
155
156
0d533154
AD
157/*---------------------------------------------------------.
158| Read a signed integer from STREAM and return its value. |
159`---------------------------------------------------------*/
160
161static inline int
162read_signed_integer (FILE *stream)
163{
164 register int c = getc (stream);
165 register int sign = 1;
166 register int n = 0;
167
168 if (c == '-')
169 {
170 c = getc (stream);
171 sign = -1;
172 }
173
174 while (isdigit (c))
175 {
176 n = 10 * n + (c - '0');
177 c = getc (stream);
178 }
179
180 ungetc (c, stream);
181
182 return sign * n;
183}
184\f
185/*-------------------------------------------------------------------.
186| Dump the string from FINPUT to FOUTPUT. MATCH is the delimiter of |
187| the string (either ' or "). |
188`-------------------------------------------------------------------*/
ae3c3164
AD
189
190static inline void
4a120d45 191copy_string (FILE *fin, FILE *fout, int match)
ae3c3164
AD
192{
193 int c;
194
4a120d45
JT
195 putc (match, fout);
196 c = getc (fin);
ae3c3164
AD
197
198 while (c != match)
199 {
200 if (c == EOF)
201 fatal (_("unterminated string at end of file"));
202 if (c == '\n')
203 {
a0f6b076 204 complain (_("unterminated string"));
4a120d45 205 ungetc (c, fin);
ae3c3164
AD
206 c = match; /* invent terminator */
207 continue;
208 }
209
4a120d45 210 putc(c, fout);
ae3c3164
AD
211
212 if (c == '\\')
213 {
4a120d45 214 c = getc (fin);
ae3c3164
AD
215 if (c == EOF)
216 fatal (_("unterminated string at end of file"));
4a120d45 217 putc (c, fout);
ae3c3164
AD
218 if (c == '\n')
219 lineno++;
220 }
221
4a120d45 222 c = getc(fin);
ae3c3164
AD
223 }
224
4a120d45 225 putc(c, fout);
ae3c3164
AD
226}
227
228
6c89f1c1
AD
229/*---------------------------------------------------------------.
230| Dump the comment from IN to OUT1 and OUT2. C is either `*' or |
231| `/', depending upon the type of comments used. OUT2 might be |
232| NULL. |
233`---------------------------------------------------------------*/
ae3c3164
AD
234
235static inline void
27821bff 236copy_comment2 (FILE *in, FILE *out1, FILE* out2, int c)
ae3c3164
AD
237{
238 int cplus_comment;
ae3c3164
AD
239 register int ended;
240
241 cplus_comment = (c == '/');
27821bff
AD
242 putc (c, out1);
243 if (out2)
244 putc (c, out2);
245 c = getc (in);
ae3c3164
AD
246
247 ended = 0;
248 while (!ended)
249 {
250 if (!cplus_comment && c == '*')
251 {
252 while (c == '*')
253 {
27821bff
AD
254 putc (c, out1);
255 if (out2)
256 putc (c, out2);
257 c = getc (in);
ae3c3164
AD
258 }
259
260 if (c == '/')
261 {
27821bff
AD
262 putc(c, out1);
263 if (out2)
264 putc(c, out2);
ae3c3164
AD
265 ended = 1;
266 }
267 }
268 else if (c == '\n')
269 {
270 lineno++;
27821bff
AD
271 putc (c, out1);
272 if (out2)
273 putc (c, out2);
ae3c3164
AD
274 if (cplus_comment)
275 ended = 1;
276 else
27821bff 277 c = getc (in);
ae3c3164
AD
278 }
279 else if (c == EOF)
280 fatal (_("unterminated comment"));
281 else
282 {
27821bff
AD
283 putc (c, out1);
284 if (out2)
285 putc (c, out2);
286 c = getc (in);
ae3c3164
AD
287 }
288 }
289}
290
291
d019d655
AD
292/*------------------------------------------------------------.
293| Dump the comment from FIN to FOUT. C is either `*' or `/', |
294| depending upon the type of comments used. |
295`------------------------------------------------------------*/
27821bff
AD
296
297static inline void
4a120d45 298copy_comment (FILE *fin, FILE *fout, int c)
27821bff 299{
4a120d45 300 copy_comment2 (fin, fout, NULL, c);
27821bff
AD
301}
302
303
1ff442ca 304void
118fb205 305reader (void)
1ff442ca
NF
306{
307 start_flag = 0;
308 startval = NULL; /* start symbol not specified yet. */
309
310#if 0
e79137ac
AD
311 /* initially assume token number translation not needed. */
312 translations = 0;
1ff442ca 313#endif
e79137ac
AD
314 /* Nowadays translations is always set to 1, since we give `error' a
315 user-token-number to satisfy the Posix demand for YYERRCODE==256.
316 */
1ff442ca
NF
317 translations = 1;
318
319 nsyms = 1;
320 nvars = 0;
321 nrules = 0;
322 nitems = 0;
323 rline_allocated = 10;
e79137ac 324 rline = NEW2 (rline_allocated, short);
1ff442ca
NF
325
326 typed = 0;
327 lastprec = 0;
328
329 gensym_count = 0;
330
331 semantic_parser = 0;
332 pure_parser = 0;
333 yylsp_needed = 0;
334
335 grammar = NULL;
336
e79137ac 337 init_lex ();
1ff442ca
NF
338 lineno = 1;
339
e79137ac
AD
340 /* Initialize the symbol table. */
341 tabinit ();
342 /* Construct the error token */
343 errtoken = getsym ("error");
1ff442ca 344 errtoken->class = STOKEN;
e79137ac
AD
345 errtoken->user_token_number = 256; /* Value specified by POSIX. */
346 /* Construct a token that represents all undefined literal tokens.
347 It is always token number 2. */
348 undeftoken = getsym ("$undefined.");
5b2e3c89
JT
349 undeftoken->class = STOKEN;
350 undeftoken->user_token_number = 2;
e79137ac
AD
351
352 /* Read the declaration section. Copy %{ ... %} groups to FTABLE
353 and FDEFINES file. Also notice any %token, %left, etc. found
354 there. */
355 putc ('\n', ftable);
356 fprintf (ftable, "\
357/* %s, made from %s\n\
358 by GNU bison %s. */\n\
359\n",
360 noparserflag ? "Bison-generated parse tables" : "A Bison parser",
361 infile,
362 VERSION);
363
364 fputs ("#define YYBISON 1 /* Identify Bison output. */\n\n", ftable);
365 read_declarations ();
366 /* Start writing the guard and action files, if they are needed. */
367 output_headers ();
368 /* Read in the grammar, build grammar in list form. Write out
369 guards and actions. */
370 readgram ();
371 /* Now we know whether we need the line-number stack. If we do,
372 write its type into the .tab.h file. */
943819bf 373 if (fdefines)
e79137ac
AD
374 reader_output_yylsp (fdefines);
375 /* Write closing delimiters for actions and guards. */
376 output_trailers ();
1ff442ca 377 if (yylsp_needed)
0d533154 378 fputs ("#define YYLSP_NEEDED\n\n", ftable);
e79137ac
AD
379 /* Assign the symbols their symbol numbers. Write #defines for the
380 token symbols into FDEFINES if requested. */
381 packsymbols ();
382 /* Convert the grammar into the format described in gram.h. */
383 packgram ();
384 /* Free the symbol table data structure since symbols are now all
385 referred to by symbol number. */
386 free_symtab ();
1ff442ca
NF
387}
388
943819bf 389void
118fb205 390reader_output_yylsp (FILE *f)
943819bf
RS
391{
392 if (yylsp_needed)
393 fprintf(f, LTYPESTR);
394}
1ff442ca 395
41aca2e0
AD
396/* Read from finput until `%%' is seen. Discard the `%%'. Handle any
397 `%' declarations, and copy the contents of any `%{ ... %}' groups
398 to fattrs. */
1ff442ca 399
4a120d45 400static void
118fb205 401read_declarations (void)
1ff442ca
NF
402{
403 register int c;
404 register int tok;
405
406 for (;;)
407 {
408 c = skip_white_space();
409
410 if (c == '%')
411 {
412 tok = parse_percent_token();
413
414 switch (tok)
415 {
416 case TWO_PERCENTS:
417 return;
418
419 case PERCENT_LEFT_CURLY:
420 copy_definition();
421 break;
422
423 case TOKEN:
424 parse_token_decl (STOKEN, SNTERM);
425 break;
a083fbbf 426
1ff442ca
NF
427 case NTERM:
428 parse_token_decl (SNTERM, STOKEN);
429 break;
a083fbbf 430
1ff442ca
NF
431 case TYPE:
432 parse_type_decl();
433 break;
a083fbbf 434
1ff442ca
NF
435 case START:
436 parse_start_decl();
437 break;
a083fbbf 438
1ff442ca 439 case UNION:
27821bff 440 parse_union_decl ();
1ff442ca 441 break;
a083fbbf 442
1ff442ca
NF
443 case EXPECT:
444 parse_expect_decl();
445 break;
943819bf
RS
446 case THONG:
447 parse_thong_decl();
448 break;
1ff442ca
NF
449 case LEFT:
450 parse_assoc_decl(LEFT_ASSOC);
451 break;
452
453 case RIGHT:
454 parse_assoc_decl(RIGHT_ASSOC);
455 break;
456
457 case NONASSOC:
458 parse_assoc_decl(NON_ASSOC);
459 break;
460
461 case SEMANTIC_PARSER:
462 if (semantic_parser == 0)
463 {
464 semantic_parser = 1;
465 open_extra_files();
466 }
467 break;
468
469 case PURE_PARSER:
470 pure_parser = 1;
471 break;
472
943819bf
RS
473 case NOOP:
474 break;
475
1ff442ca 476 default:
a0f6b076 477 complain (_("unrecognized: %s"), token_buffer);
943819bf
RS
478 skip_to_char('%');
479 }
1ff442ca
NF
480 }
481 else if (c == EOF)
a0f6b076 482 fatal (_("no input grammar"));
1ff442ca 483 else
943819bf 484 {
a0f6b076 485 complain (_("unknown character: %s"), printable_version(c));
6666f98f 486 skip_to_char('%');
943819bf 487 }
1ff442ca
NF
488 }
489}
490
491
ae3c3164
AD
492/* Copy the contents of a `%{ ... %}' into the definitions file. The
493 `%{' has already been read. Return after reading the `%}'. */
1ff442ca 494
4a120d45 495static void
118fb205 496copy_definition (void)
1ff442ca
NF
497{
498 register int c;
ae3c3164
AD
499 /* -1 while reading a character if prev char was %. */
500 register int after_percent;
1ff442ca
NF
501
502 if (!nolinesflag)
503 fprintf(fattrs, "#line %d \"%s\"\n", lineno, infile);
504
505 after_percent = 0;
506
ae3c3164 507 c = getc (finput);
1ff442ca
NF
508
509 for (;;)
510 {
511 switch (c)
512 {
513 case '\n':
514 putc(c, fattrs);
515 lineno++;
516 break;
517
518 case '%':
519 after_percent = -1;
520 break;
a083fbbf 521
1ff442ca
NF
522 case '\'':
523 case '"':
ae3c3164 524 copy_string (finput, fattrs, c);
1ff442ca
NF
525 break;
526
527 case '/':
ae3c3164
AD
528 putc (c, fattrs);
529 c = getc (finput);
1ff442ca
NF
530 if (c != '*' && c != '/')
531 continue;
ae3c3164 532 copy_comment (finput, fattrs, c);
1ff442ca
NF
533 break;
534
535 case EOF:
a0f6b076
AD
536 fatal ("%s",
537 _("unterminated `%{' definition"));
1ff442ca
NF
538
539 default:
540 putc(c, fattrs);
541 }
542
543 c = getc(finput);
544
545 if (after_percent)
546 {
547 if (c == '}')
548 return;
549 putc('%', fattrs);
550 }
551 after_percent = 0;
552
553 }
554
555}
556
557
558
559/* parse what comes after %token or %nterm.
560For %token, what_is is STOKEN and what_is_not is SNTERM.
561For %nterm, the arguments are reversed. */
562
4a120d45 563static void
118fb205 564parse_token_decl (int what_is, int what_is_not)
1ff442ca 565{
1ff442ca 566 register int token = 0;
1ff442ca 567 register char *typename = 0;
943819bf 568 register struct bucket *symbol = NULL; /* pts to symbol being defined */
1ff442ca
NF
569 int k;
570
1ff442ca
NF
571 for (;;)
572 {
e6011337
JT
573 int tmp_char = ungetc (skip_white_space (), finput);
574
575 if (tmp_char == '%')
1ff442ca 576 return;
e6011337 577 if (tmp_char == EOF)
a0f6b076 578 fatal (_("Premature EOF after %s"), token_buffer);
e6011337 579
1ff442ca
NF
580 token = lex();
581 if (token == COMMA)
943819bf
RS
582 {
583 symbol = NULL;
584 continue;
585 }
1ff442ca
NF
586 if (token == TYPENAME)
587 {
588 k = strlen(token_buffer);
589 typename = NEW2(k + 1, char);
590 strcpy(typename, token_buffer);
591 value_components_used = 1;
943819bf
RS
592 symbol = NULL;
593 }
594 else if (token == IDENTIFIER && *symval->tag == '\"'
a083fbbf 595 && symbol)
943819bf
RS
596 {
597 translations = 1;
598 symval->class = STOKEN;
599 symval->type_name = typename;
600 symval->user_token_number = symbol->user_token_number;
601 symbol->user_token_number = SALIAS;
602
a083fbbf
RS
603 symval->alias = symbol;
604 symbol->alias = symval;
943819bf
RS
605 symbol = NULL;
606
607 nsyms--; /* symbol and symval combined are only one symbol */
1ff442ca
NF
608 }
609 else if (token == IDENTIFIER)
610 {
611 int oldclass = symval->class;
943819bf 612 symbol = symval;
1ff442ca 613
943819bf 614 if (symbol->class == what_is_not)
a0f6b076 615 complain (_("symbol %s redefined"), symbol->tag);
943819bf 616 symbol->class = what_is;
1ff442ca 617 if (what_is == SNTERM && oldclass != SNTERM)
943819bf 618 symbol->value = nvars++;
1ff442ca
NF
619
620 if (typename)
621 {
943819bf
RS
622 if (symbol->type_name == NULL)
623 symbol->type_name = typename;
624 else if (strcmp(typename, symbol->type_name) != 0)
a0f6b076 625 complain (_("type redeclaration for %s"), symbol->tag);
1ff442ca
NF
626 }
627 }
943819bf 628 else if (symbol && token == NUMBER)
1ff442ca 629 {
943819bf 630 symbol->user_token_number = numval;
1ff442ca
NF
631 translations = 1;
632 }
633 else
943819bf 634 {
a0f6b076
AD
635 complain (_("`%s' is invalid in %s"),
636 token_buffer,
943819bf
RS
637 (what_is == STOKEN) ? "%token" : "%nterm");
638 skip_to_char('%');
639 }
1ff442ca
NF
640 }
641
642}
643
a083fbbf 644/* parse what comes after %thong
943819bf
RS
645 the full syntax is
646 %thong <type> token number literal
647 the <type> or number may be omitted. The number specifies the
648 user_token_number.
649
650 Two symbols are entered in the table, one for the token symbol and
651 one for the literal. Both are given the <type>, if any, from the declaration.
652 The ->user_token_number of the first is SALIAS and the ->user_token_number
653 of the second is set to the number, if any, from the declaration.
654 The two symbols are linked via pointers in their ->alias fields.
a083fbbf 655
943819bf
RS
656 during output_defines_table, the symbol is reported
657 thereafter, only the literal string is retained
658 it is the literal string that is output to yytname
659*/
660
4a120d45 661static void
118fb205 662parse_thong_decl (void)
943819bf
RS
663{
664 register int token;
665 register struct bucket *symbol;
666 register char *typename = 0;
667 int k, usrtoknum;
668
669 translations = 1;
670 token = lex(); /* fetch typename or first token */
671 if (token == TYPENAME) {
672 k = strlen(token_buffer);
673 typename = NEW2(k + 1, char);
674 strcpy(typename, token_buffer);
675 value_components_used = 1;
676 token = lex(); /* fetch first token */
677 }
678
679 /* process first token */
680
a083fbbf 681 if (token != IDENTIFIER)
943819bf 682 {
a0f6b076
AD
683 complain (_("unrecognized item %s, expected an identifier"),
684 token_buffer);
943819bf
RS
685 skip_to_char('%');
686 return;
687 }
688 symval->class = STOKEN;
689 symval->type_name = typename;
690 symval->user_token_number = SALIAS;
691 symbol = symval;
692
693 token = lex(); /* get number or literal string */
a083fbbf 694
943819bf
RS
695 if (token == NUMBER) {
696 usrtoknum = numval;
697 token = lex(); /* okay, did number, now get literal */
698 }
699 else usrtoknum = 0;
700
701 /* process literal string token */
702
a083fbbf 703 if (token != IDENTIFIER || *symval->tag != '\"')
943819bf 704 {
a0f6b076
AD
705 complain (_("expected string constant instead of %s"),
706 token_buffer);
943819bf
RS
707 skip_to_char('%');
708 return;
709 }
710 symval->class = STOKEN;
711 symval->type_name = typename;
712 symval->user_token_number = usrtoknum;
713
a083fbbf
RS
714 symval->alias = symbol;
715 symbol->alias = symval;
943819bf
RS
716
717 nsyms--; /* symbol and symval combined are only one symbol */
718}
1ff442ca
NF
719
720
a0f6b076 721/* Parse what comes after %start */
1ff442ca 722
4a120d45 723static void
118fb205 724parse_start_decl (void)
1ff442ca
NF
725{
726 if (start_flag)
27821bff
AD
727 complain (_("multiple %s declarations"), "%start");
728 if (lex () != IDENTIFIER)
729 complain (_("invalid %s declaration"), "%start");
943819bf
RS
730 else
731 {
732 start_flag = 1;
733 startval = symval;
734 }
1ff442ca
NF
735}
736
737
738
739/* read in a %type declaration and record its information for get_type_name to access */
740
4a120d45 741static void
118fb205 742parse_type_decl (void)
1ff442ca
NF
743{
744 register int k;
745 register char *name;
1ff442ca
NF
746
747 if (lex() != TYPENAME)
943819bf 748 {
a0f6b076 749 complain ("%s", _("%type declaration has no <typename>"));
943819bf
RS
750 skip_to_char('%');
751 return;
752 }
1ff442ca
NF
753
754 k = strlen(token_buffer);
755 name = NEW2(k + 1, char);
756 strcpy(name, token_buffer);
757
1ff442ca
NF
758 for (;;)
759 {
760 register int t;
e6011337 761 int tmp_char = ungetc (skip_white_space (), finput);
1ff442ca 762
e6011337 763 if (tmp_char == '%')
1ff442ca 764 return;
e6011337 765 if (tmp_char == EOF)
a0f6b076 766 fatal (_("Premature EOF after %s"), token_buffer);
1ff442ca 767
1ff442ca
NF
768 t = lex();
769
770 switch (t)
771 {
772
773 case COMMA:
774 case SEMICOLON:
775 break;
776
777 case IDENTIFIER:
778 if (symval->type_name == NULL)
779 symval->type_name = name;
943819bf 780 else if (strcmp(name, symval->type_name) != 0)
a0f6b076 781 complain (_("type redeclaration for %s"), symval->tag);
1ff442ca
NF
782
783 break;
784
785 default:
a0f6b076
AD
786 complain (_("invalid %%type declaration due to item: %s"),
787 token_buffer);
943819bf 788 skip_to_char('%');
1ff442ca
NF
789 }
790 }
791}
792
793
794
795/* read in a %left, %right or %nonassoc declaration and record its information. */
796/* assoc is either LEFT_ASSOC, RIGHT_ASSOC or NON_ASSOC. */
797
4a120d45 798static void
118fb205 799parse_assoc_decl (int assoc)
1ff442ca
NF
800{
801 register int k;
802 register char *name = NULL;
943819bf 803 register int prev = 0;
1ff442ca
NF
804
805 lastprec++; /* Assign a new precedence level, never 0. */
806
1ff442ca
NF
807 for (;;)
808 {
809 register int t;
e6011337 810 int tmp_char = ungetc (skip_white_space (), finput);
1ff442ca 811
e6011337 812 if (tmp_char == '%')
1ff442ca 813 return;
e6011337 814 if (tmp_char == EOF)
a0f6b076 815 fatal (_("Premature EOF after %s"), token_buffer);
1ff442ca 816
1ff442ca
NF
817 t = lex();
818
819 switch (t)
820 {
821
822 case TYPENAME:
823 k = strlen(token_buffer);
824 name = NEW2(k + 1, char);
825 strcpy(name, token_buffer);
826 break;
827
828 case COMMA:
829 break;
830
831 case IDENTIFIER:
832 if (symval->prec != 0)
a0f6b076 833 complain (_("redefining precedence of %s"), symval->tag);
1ff442ca
NF
834 symval->prec = lastprec;
835 symval->assoc = assoc;
836 if (symval->class == SNTERM)
a0f6b076 837 complain (_("symbol %s redefined"), symval->tag);
1ff442ca
NF
838 symval->class = STOKEN;
839 if (name)
840 { /* record the type, if one is specified */
841 if (symval->type_name == NULL)
842 symval->type_name = name;
943819bf 843 else if (strcmp(name, symval->type_name) != 0)
a0f6b076 844 complain (_("type redeclaration for %s"), symval->tag);
1ff442ca
NF
845 }
846 break;
847
848 case NUMBER:
849 if (prev == IDENTIFIER)
850 {
851 symval->user_token_number = numval;
852 translations = 1;
853 }
a083fbbf 854 else
943819bf 855 {
a0f6b076 856 complain (_("invalid text (%s) - number should be after identifier"),
943819bf
RS
857 token_buffer);
858 skip_to_char('%');
859 }
1ff442ca
NF
860 break;
861
862 case SEMICOLON:
863 return;
864
865 default:
a0f6b076 866 complain (_("unexpected item: %s"), token_buffer);
943819bf 867 skip_to_char('%');
1ff442ca
NF
868 }
869
870 prev = t;
871
872 }
873}
874
875
876
877/* copy the union declaration into fattrs (and fdefines),
878 where it is made into the
879 definition of YYSTYPE, the type of elements of the parser value stack. */
880
4a120d45 881static void
118fb205 882parse_union_decl (void)
1ff442ca
NF
883{
884 register int c;
27821bff 885 register int count = 0;
1ff442ca
NF
886
887 if (typed)
27821bff 888 complain (_("multiple %s declarations"), "%union");
1ff442ca
NF
889
890 typed = 1;
891
892 if (!nolinesflag)
27821bff 893 fprintf (fattrs, "\n#line %d \"%s\"\n", lineno, infile);
1ff442ca 894 else
27821bff 895 fprintf (fattrs, "\n");
1ff442ca 896
27821bff 897 fprintf (fattrs, "typedef union");
1ff442ca 898 if (fdefines)
27821bff 899 fprintf (fdefines, "typedef union");
1ff442ca 900
27821bff 901 c = getc (finput);
1ff442ca
NF
902
903 while (c != EOF)
904 {
27821bff 905 putc (c, fattrs);
1ff442ca 906 if (fdefines)
27821bff 907 putc (c, fdefines);
1ff442ca
NF
908
909 switch (c)
910 {
911 case '\n':
912 lineno++;
913 break;
914
915 case '/':
27821bff 916 c = getc (finput);
1ff442ca 917 if (c != '*' && c != '/')
27821bff
AD
918 continue;
919 copy_comment2 (finput, fattrs, fdefines, c);
1ff442ca
NF
920 break;
921
922
923 case '{':
924 count++;
925 break;
926
927 case '}':
928 if (count == 0)
27821bff 929 complain (_("unmatched %s"), "`}'");
1ff442ca 930 count--;
943819bf 931 if (count <= 0)
1ff442ca 932 {
27821bff 933 fprintf (fattrs, " YYSTYPE;\n");
1ff442ca 934 if (fdefines)
27821bff 935 fprintf (fdefines, " YYSTYPE;\n");
1ff442ca 936 /* JF don't choke on trailing semi */
27821bff
AD
937 c = skip_white_space ();
938 if (c != ';')
939 ungetc (c,finput);
1ff442ca
NF
940 return;
941 }
942 }
943
27821bff 944 c = getc (finput);
1ff442ca
NF
945 }
946}
947
948/* parse the declaration %expect N which says to expect N
949 shift-reduce conflicts. */
950
4a120d45 951static void
118fb205 952parse_expect_decl (void)
1ff442ca
NF
953{
954 register int c;
955 register int count;
956 char buffer[20];
957
958 c = getc(finput);
959 while (c == ' ' || c == '\t')
960 c = getc(finput);
961
962 count = 0;
963 while (c >= '0' && c <= '9')
964 {
965 if (count < 20)
966 buffer[count++] = c;
967 c = getc(finput);
968 }
969 buffer[count] = 0;
970
971 ungetc (c, finput);
972
943819bf 973 if (count <= 0 || count > 10)
a0f6b076 974 complain ("%s", _("argument of %expect is not an integer"));
1ff442ca
NF
975 expected_conflicts = atoi (buffer);
976}
977
978/* that's all of parsing the declaration section */
979\f
4a120d45 980/* FIN is pointing to a location (i.e., a `@'). Output to FOUT
7b306f52
AD
981 a reference to this location. STACK_OFFSET is the number of values
982 in the current rule so far, which says where to find `$0' with
983 respect to the top of the stack. */
984static inline void
4a120d45 985copy_at (FILE *fin, FILE *fout, int stack_offset)
7b306f52
AD
986{
987 int c;
988
4a120d45 989 c = getc (fin);
7b306f52
AD
990 if (c == '$')
991 {
4a120d45 992 fprintf (fout, "yyloc");
7b306f52
AD
993 yylsp_needed = 1;
994 }
995 else if (isdigit(c) || c == '-')
996 {
997 int n;
998
4a120d45
JT
999 ungetc (c, fin);
1000 n = read_signed_integer (fin);
7b306f52 1001
4a120d45 1002 fprintf (fout, "yylsp[%d]", n - stack_offset);
7b306f52
AD
1003 yylsp_needed = 1;
1004 }
1005 else
a0f6b076 1006 complain (_("@%s is invalid"), printable_version (c));
7b306f52
AD
1007}
1008
1009
a0f6b076
AD
1010/* Get the data type (alternative in the union) of the value for
1011 symbol n in rule rule. */
1ff442ca 1012
4a120d45 1013static char *
118fb205 1014get_type_name (int n, symbol_list *rule)
1ff442ca 1015{
1ff442ca
NF
1016 register int i;
1017 register symbol_list *rp;
1018
1019 if (n < 0)
943819bf 1020 {
a0f6b076 1021 complain (_("invalid $ value"));
943819bf
RS
1022 return NULL;
1023 }
1ff442ca
NF
1024
1025 rp = rule;
1026 i = 0;
1027
1028 while (i < n)
1029 {
1030 rp = rp->next;
1031 if (rp == NULL || rp->sym == NULL)
943819bf 1032 {
a0f6b076 1033 complain (_("invalid $ value"));
943819bf
RS
1034 return NULL;
1035 }
1ff442ca
NF
1036 i++;
1037 }
1038
36281465 1039 return rp->sym->type_name;
1ff442ca
NF
1040}
1041
1042
3cef001a 1043
41aca2e0
AD
1044/* After `%guard' is seen in the input file, copy the actual guard
1045 into the guards file. If the guard is followed by an action, copy
1046 that into the actions file. STACK_OFFSET is the number of values
1047 in the current rule so far, which says where to find `$0' with
1048 respect to the top of the stack, for the simple parser in which the
1049 stack is not popped until after the guard is run. */
1ff442ca 1050
4a120d45 1051static void
118fb205 1052copy_guard (symbol_list *rule, int stack_offset)
1ff442ca
NF
1053{
1054 register int c;
1055 register int n;
1056 register int count;
1ff442ca
NF
1057 register char *type_name;
1058 int brace_flag = 0;
1ff442ca
NF
1059
1060 /* offset is always 0 if parser has already popped the stack pointer */
1061 if (semantic_parser) stack_offset = 0;
1062
1063 fprintf(fguard, "\ncase %d:\n", nrules);
1064 if (!nolinesflag)
41aca2e0 1065 fprintf (fguard, "#line %d \"%s\"\n", lineno, infile);
1ff442ca
NF
1066 putc('{', fguard);
1067
1068 count = 0;
1069 c = getc(finput);
1070
1071 while (brace_flag ? (count > 0) : (c != ';'))
1072 {
1073 switch (c)
1074 {
1075 case '\n':
1076 putc(c, fguard);
1077 lineno++;
1078 break;
1079
1080 case '{':
1081 putc(c, fguard);
1082 brace_flag = 1;
1083 count++;
1084 break;
1085
1086 case '}':
1087 putc(c, fguard);
1088 if (count > 0)
1089 count--;
a083fbbf 1090 else
943819bf 1091 {
27821bff 1092 complain (_("unmatched %s"), "`}'");
943819bf
RS
1093 c = getc(finput); /* skip it */
1094 }
1ff442ca
NF
1095 break;
1096
1097 case '\'':
1098 case '"':
ca36d2ef 1099 copy_string (finput, fguard, c);
1ff442ca
NF
1100 break;
1101
1102 case '/':
3cef001a
AD
1103 putc (c, fguard);
1104 c = getc (finput);
1ff442ca
NF
1105 if (c != '*' && c != '/')
1106 continue;
3cef001a 1107 copy_comment (finput, fguard, c);
1ff442ca
NF
1108 break;
1109
1110 case '$':
1111 c = getc(finput);
1112 type_name = NULL;
1113
1114 if (c == '<')
1115 {
1116 register char *cp = token_buffer;
1117
1118 while ((c = getc(finput)) != '>' && c > 0)
118fb205
JT
1119 {
1120 if (cp == token_buffer + maxtoken)
1121 cp = grow_token_buffer(cp);
1122
1123 *cp++ = c;
1124 }
1ff442ca
NF
1125 *cp = 0;
1126 type_name = token_buffer;
1127
1128 c = getc(finput);
1129 }
1130
1131 if (c == '$')
1132 {
1133 fprintf(fguard, "yyval");
41aca2e0
AD
1134 if (!type_name)
1135 type_name = rule->sym->type_name;
1ff442ca
NF
1136 if (type_name)
1137 fprintf(fguard, ".%s", type_name);
943819bf 1138 if(!type_name && typed)
a0f6b076
AD
1139 complain (_("$$ of `%s' has no declared type"),
1140 rule->sym->tag);
1ff442ca 1141 }
1ff442ca
NF
1142 else if (isdigit(c) || c == '-')
1143 {
1144 ungetc (c, finput);
41aca2e0
AD
1145 n = read_signed_integer (finput);
1146 c = getc (finput);
1ff442ca
NF
1147
1148 if (!type_name && n > 0)
1149 type_name = get_type_name(n, rule);
1150
1151 fprintf(fguard, "yyvsp[%d]", n - stack_offset);
1152 if (type_name)
1153 fprintf(fguard, ".%s", type_name);
6666f98f 1154 if (!type_name && typed)
a0f6b076
AD
1155 complain (_("$%d of `%s' has no declared type"),
1156 n, rule->sym->tag);
1ff442ca
NF
1157 continue;
1158 }
1159 else
a0f6b076 1160 complain (_("$%s is invalid"), printable_version (c));
1ff442ca
NF
1161 break;
1162
1163 case '@':
7b306f52 1164 copy_at (finput, fguard, stack_offset);
6666f98f 1165 break;
1ff442ca
NF
1166
1167 case EOF:
a0f6b076
AD
1168 fatal ("%s",
1169 _("unterminated %guard clause"));
1ff442ca
NF
1170
1171 default:
6666f98f 1172 putc (c, fguard);
1ff442ca
NF
1173 }
1174
1175 if (c != '}' || count != 0)
1176 c = getc(finput);
1177 }
1178
1179 c = skip_white_space();
1180
1181 fprintf(fguard, ";\n break;}");
1182 if (c == '{')
7b306f52 1183 copy_action (rule, stack_offset);
1ff442ca
NF
1184 else if (c == '=')
1185 {
943819bf 1186 c = getc(finput); /* why not skip_white_space -wjh */
1ff442ca 1187 if (c == '{')
7b306f52 1188 copy_action (rule, stack_offset);
1ff442ca
NF
1189 }
1190 else
1191 ungetc(c, finput);
1192}
1193
1194
1195
41aca2e0
AD
1196/* Assuming that a `{' has just been seen, copy everything up to the
1197 matching `}' into the actions file. STACK_OFFSET is the number of
1198 values in the current rule so far, which says where to find `$0'
1199 with respect to the top of the stack. */
1ff442ca 1200
4a120d45 1201static void
118fb205 1202copy_action (symbol_list *rule, int stack_offset)
1ff442ca
NF
1203{
1204 register int c;
1205 register int n;
1206 register int count;
1ff442ca 1207 register char *type_name;
1ff442ca
NF
1208
1209 /* offset is always 0 if parser has already popped the stack pointer */
41aca2e0
AD
1210 if (semantic_parser)
1211 stack_offset = 0;
1ff442ca 1212
41aca2e0 1213 fprintf (faction, "\ncase %d:\n", nrules);
1ff442ca 1214 if (!nolinesflag)
41aca2e0
AD
1215 fprintf (faction, "#line %d \"%s\"\n", lineno, infile);
1216 putc ('{', faction);
1ff442ca
NF
1217
1218 count = 1;
1219 c = getc(finput);
1220
1221 while (count > 0)
1222 {
1223 while (c != '}')
1224 {
1225 switch (c)
1226 {
1227 case '\n':
1228 putc(c, faction);
1229 lineno++;
1230 break;
1231
1232 case '{':
1233 putc(c, faction);
1234 count++;
1235 break;
1236
1237 case '\'':
1238 case '"':
ca36d2ef 1239 copy_string (finput, faction, c);
1ff442ca
NF
1240 break;
1241
1242 case '/':
27821bff
AD
1243 putc (c, faction);
1244 c = getc (finput);
1ff442ca
NF
1245 if (c != '*' && c != '/')
1246 continue;
3cef001a 1247 copy_comment (finput, faction, c);
1ff442ca
NF
1248 break;
1249
1250 case '$':
1251 c = getc(finput);
1252 type_name = NULL;
1253
1254 if (c == '<')
1255 {
1256 register char *cp = token_buffer;
1257
1258 while ((c = getc(finput)) != '>' && c > 0)
118fb205
JT
1259 {
1260 if (cp == token_buffer + maxtoken)
1261 cp = grow_token_buffer(cp);
1262
1263 *cp++ = c;
1264 }
1ff442ca
NF
1265 *cp = 0;
1266 type_name = token_buffer;
1267 value_components_used = 1;
1268
1269 c = getc(finput);
1270 }
1271 if (c == '$')
1272 {
1273 fprintf(faction, "yyval");
41aca2e0
AD
1274 if (!type_name)
1275 type_name = get_type_name(0, rule);
1ff442ca
NF
1276 if (type_name)
1277 fprintf(faction, ".%s", type_name);
a083fbbf 1278 if(!type_name && typed)
a0f6b076
AD
1279 complain (_("$$ of `%s' has no declared type"),
1280 rule->sym->tag);
1ff442ca
NF
1281 }
1282 else if (isdigit(c) || c == '-')
1283 {
1284 ungetc (c, finput);
1285 n = read_signed_integer(finput);
1286 c = getc(finput);
1287
1288 if (!type_name && n > 0)
1289 type_name = get_type_name(n, rule);
1290
1291 fprintf(faction, "yyvsp[%d]", n - stack_offset);
1292 if (type_name)
1293 fprintf(faction, ".%s", type_name);
a083fbbf 1294 if(!type_name && typed)
a0f6b076
AD
1295 complain (_("$%d of `%s' has no declared type"),
1296 n, rule->sym->tag);
1ff442ca
NF
1297 continue;
1298 }
1299 else
a0f6b076 1300 complain (_("$%s is invalid"), printable_version (c));
1ff442ca
NF
1301
1302 break;
1303
1304 case '@':
7b306f52 1305 copy_at (finput, faction, stack_offset);
6666f98f 1306 break;
1ff442ca
NF
1307
1308 case EOF:
27821bff 1309 fatal (_("unmatched %s"), "`{'");
1ff442ca
NF
1310
1311 default:
1312 putc(c, faction);
1313 }
1314
1315 c = getc(finput);
1316 }
1317
1318 /* above loop exits when c is '}' */
1319
1320 if (--count)
1321 {
1322 putc(c, faction);
1323 c = getc(finput);
1324 }
1325 }
1326
1327 fprintf(faction, ";\n break;}");
1328}
1329
1330
1331
1332/* generate a dummy symbol, a nonterminal,
1333whose name cannot conflict with the user's names. */
1334
4a120d45 1335static bucket *
118fb205 1336gensym (void)
1ff442ca
NF
1337{
1338 register bucket *sym;
1339
1340 sprintf (token_buffer, "@%d", ++gensym_count);
1341 sym = getsym(token_buffer);
1342 sym->class = SNTERM;
1343 sym->value = nvars++;
36281465 1344 return sym;
1ff442ca
NF
1345}
1346
1347/* Parse the input grammar into a one symbol_list structure.
1348Each rule is represented by a sequence of symbols: the left hand side
1349followed by the contents of the right hand side, followed by a null pointer
1350instead of a symbol to terminate the rule.
1351The next symbol is the lhs of the following rule.
1352
1353All guards and actions are copied out to the appropriate files,
1354labelled by the rule number they apply to. */
1355
4a120d45 1356static void
118fb205 1357readgram (void)
1ff442ca
NF
1358{
1359 register int t;
2686a6e7 1360 register bucket *lhs = NULL;
1ff442ca
NF
1361 register symbol_list *p;
1362 register symbol_list *p1;
1363 register bucket *bp;
1364
1365 symbol_list *crule; /* points to first symbol_list of current rule. */
1366 /* its symbol is the lhs of the rule. */
1367 symbol_list *crule1; /* points to the symbol_list preceding crule. */
1368
1369 p1 = NULL;
1370
1371 t = lex();
1372
1373 while (t != TWO_PERCENTS && t != ENDFILE)
1374 {
1375 if (t == IDENTIFIER || t == BAR)
1376 {
1377 register int actionflag = 0;
1378 int rulelength = 0; /* number of symbols in rhs of this rule so far */
1379 int xactions = 0; /* JF for error checking */
1380 bucket *first_rhs = 0;
1381
1382 if (t == IDENTIFIER)
1383 {
1384 lhs = symval;
943819bf
RS
1385
1386 if (!start_flag)
1387 {
1388 startval = lhs;
1389 start_flag = 1;
1390 }
a083fbbf 1391
1ff442ca
NF
1392 t = lex();
1393 if (t != COLON)
943819bf 1394 {
a0f6b076 1395 complain (_("ill-formed rule: initial symbol not followed by colon"));
943819bf
RS
1396 unlex(t);
1397 }
1ff442ca
NF
1398 }
1399
943819bf 1400 if (nrules == 0 && t == BAR)
1ff442ca 1401 {
a0f6b076 1402 complain (_("grammar starts with vertical bar"));
943819bf 1403 lhs = symval; /* BOGUS: use a random symval */
1ff442ca 1404 }
1ff442ca
NF
1405 /* start a new rule and record its lhs. */
1406
1407 nrules++;
1408 nitems++;
1409
1410 record_rule_line ();
1411
1412 p = NEW(symbol_list);
1413 p->sym = lhs;
1414
1415 crule1 = p1;
1416 if (p1)
1417 p1->next = p;
1418 else
1419 grammar = p;
1420
1421 p1 = p;
1422 crule = p;
1423
1424 /* mark the rule's lhs as a nonterminal if not already so. */
1425
1426 if (lhs->class == SUNKNOWN)
1427 {
1428 lhs->class = SNTERM;
1429 lhs->value = nvars;
1430 nvars++;
1431 }
1432 else if (lhs->class == STOKEN)
a0f6b076 1433 complain (_("rule given for %s, which is a token"), lhs->tag);
1ff442ca
NF
1434
1435 /* read the rhs of the rule. */
1436
1437 for (;;)
1438 {
1439 t = lex();
943819bf
RS
1440 if (t == PREC)
1441 {
1442 t = lex();
1443 crule->ruleprec = symval;
1444 t = lex();
1445 }
1ff442ca
NF
1446
1447 if (! (t == IDENTIFIER || t == LEFT_CURLY)) break;
1448
1449 /* If next token is an identifier, see if a colon follows it.
1450 If one does, exit this rule now. */
1451 if (t == IDENTIFIER)
1452 {
1453 register bucket *ssave;
1454 register int t1;
1455
1456 ssave = symval;
1457 t1 = lex();
1458 unlex(t1);
1459 symval = ssave;
1460 if (t1 == COLON) break;
1461
1462 if(!first_rhs) /* JF */
1463 first_rhs = symval;
1464 /* Not followed by colon =>
1465 process as part of this rule's rhs. */
1466 }
1467
1468 /* If we just passed an action, that action was in the middle
1469 of a rule, so make a dummy rule to reduce it to a
1470 non-terminal. */
1471 if (actionflag)
1472 {
1473 register bucket *sdummy;
1474
1475 /* Since the action was written out with this rule's */
943819bf 1476 /* number, we must give the new rule this number */
1ff442ca
NF
1477 /* by inserting the new rule before it. */
1478
1479 /* Make a dummy nonterminal, a gensym. */
1480 sdummy = gensym();
1481
1482 /* Make a new rule, whose body is empty,
1483 before the current one, so that the action
1484 just read can belong to it. */
1485 nrules++;
1486 nitems++;
1487 record_rule_line ();
1488 p = NEW(symbol_list);
1489 if (crule1)
1490 crule1->next = p;
1491 else grammar = p;
1492 p->sym = sdummy;
1493 crule1 = NEW(symbol_list);
1494 p->next = crule1;
1495 crule1->next = crule;
1496
1497 /* insert the dummy generated by that rule into this rule. */
1498 nitems++;
1499 p = NEW(symbol_list);
1500 p->sym = sdummy;
1501 p1->next = p;
1502 p1 = p;
1503
1504 actionflag = 0;
1505 }
1506
1507 if (t == IDENTIFIER)
1508 {
1509 nitems++;
1510 p = NEW(symbol_list);
1511 p->sym = symval;
1512 p1->next = p;
1513 p1 = p;
1514 }
1515 else /* handle an action. */
1516 {
1517 copy_action(crule, rulelength);
1518 actionflag = 1;
1519 xactions++; /* JF */
1520 }
1521 rulelength++;
943819bf 1522 } /* end of read rhs of rule */
1ff442ca
NF
1523
1524 /* Put an empty link in the list to mark the end of this rule */
1525 p = NEW(symbol_list);
1526 p1->next = p;
1527 p1 = p;
1528
1529 if (t == PREC)
1530 {
a0f6b076 1531 complain (_("two @prec's in a row"));
1ff442ca
NF
1532 t = lex();
1533 crule->ruleprec = symval;
1534 t = lex();
1535 }
1536 if (t == GUARD)
1537 {
1538 if (! semantic_parser)
a0f6b076
AD
1539 complain ("%s",
1540 _("%guard present but %semantic_parser not specified"));
1ff442ca
NF
1541
1542 copy_guard(crule, rulelength);
1543 t = lex();
1544 }
1545 else if (t == LEFT_CURLY)
1546 {
943819bf 1547 /* This case never occurs -wjh */
6666f98f 1548 if (actionflag)
a0f6b076 1549 complain (_("two actions at end of one rule"));
1ff442ca 1550 copy_action(crule, rulelength);
943819bf
RS
1551 actionflag = 1;
1552 xactions++; /* -wjh */
1ff442ca
NF
1553 t = lex();
1554 }
a0f6b076 1555 /* If $$ is being set in default way, report if any type
6666f98f
AD
1556 mismatch. */
1557 else if (!xactions
1558 && first_rhs
1559 && lhs->type_name != first_rhs->type_name)
1ff442ca 1560 {
6666f98f
AD
1561 if (lhs->type_name == 0
1562 || first_rhs->type_name == 0
1ff442ca 1563 || strcmp(lhs->type_name,first_rhs->type_name))
a0f6b076
AD
1564 complain (_("type clash (`%s' `%s') on default action"),
1565 lhs->type_name ? lhs->type_name : "",
1566 first_rhs->type_name ? first_rhs->type_name : "");
1ff442ca
NF
1567 }
1568 /* Warn if there is no default for $$ but we need one. */
1569 else if (!xactions && !first_rhs && lhs->type_name != 0)
a0f6b076 1570 complain (_("empty rule for typed nonterminal, and no action"));
1ff442ca
NF
1571 if (t == SEMICOLON)
1572 t = lex();
a083fbbf 1573 }
943819bf
RS
1574#if 0
1575 /* these things can appear as alternatives to rules. */
1576/* NO, they cannot.
1577 a) none of the documentation allows them
1578 b) most of them scan forward until finding a next %
1579 thus they may swallow lots of intervening rules
1580*/
1ff442ca
NF
1581 else if (t == TOKEN)
1582 {
1583 parse_token_decl(STOKEN, SNTERM);
1584 t = lex();
1585 }
1586 else if (t == NTERM)
1587 {
1588 parse_token_decl(SNTERM, STOKEN);
1589 t = lex();
1590 }
1591 else if (t == TYPE)
1592 {
1593 t = get_type();
1594 }
1595 else if (t == UNION)
1596 {
1597 parse_union_decl();
1598 t = lex();
1599 }
1600 else if (t == EXPECT)
1601 {
1602 parse_expect_decl();
1603 t = lex();
1604 }
1605 else if (t == START)
1606 {
1607 parse_start_decl();
1608 t = lex();
1609 }
943819bf
RS
1610#endif
1611
1ff442ca 1612 else
943819bf 1613 {
a0f6b076 1614 complain (_("invalid input: %s"), token_buffer);
943819bf
RS
1615 t = lex();
1616 }
1ff442ca
NF
1617 }
1618
943819bf
RS
1619 /* grammar has been read. Do some checking */
1620
1ff442ca 1621 if (nsyms > MAXSHORT)
a0f6b076
AD
1622 fatal (_("too many symbols (tokens plus nonterminals); maximum %d"),
1623 MAXSHORT);
1ff442ca 1624 if (nrules == 0)
a0f6b076 1625 fatal (_("no rules in the input grammar"));
1ff442ca
NF
1626
1627 if (typed == 0 /* JF put out same default YYSTYPE as YACC does */
1628 && !value_components_used)
1629 {
1630 /* We used to use `unsigned long' as YYSTYPE on MSDOS,
1631 but it seems better to be consistent.
1632 Most programs should declare their own type anyway. */
1633 fprintf(fattrs, "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n");
1634 if (fdefines)
1635 fprintf(fdefines, "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n");
1636 }
1637
1638 /* Report any undefined symbols and consider them nonterminals. */
1639
1640 for (bp = firstsymbol; bp; bp = bp->next)
1641 if (bp->class == SUNKNOWN)
1642 {
a0f6b076
AD
1643 complain (_("symbol %s is used, but is not defined as a token and has no rules"),
1644 bp->tag);
1ff442ca
NF
1645 bp->class = SNTERM;
1646 bp->value = nvars++;
1647 }
1648
1649 ntokens = nsyms - nvars;
1650}
1651
1652
4a120d45 1653static void
118fb205 1654record_rule_line (void)
1ff442ca
NF
1655{
1656 /* Record each rule's source line number in rline table. */
1657
1658 if (nrules >= rline_allocated)
1659 {
1660 rline_allocated = nrules * 2;
118fb205
JT
1661 rline = (short *) xrealloc ((char *) rline,
1662 rline_allocated * sizeof (short));
1ff442ca
NF
1663 }
1664 rline[nrules] = lineno;
1665}
1666
1667
2686a6e7 1668#if 0
1ff442ca 1669/* read in a %type declaration and record its information for get_type_name to access */
943819bf
RS
1670/* this is unused. it is only called from the #if 0 part of readgram */
1671static int
118fb205 1672get_type (void)
1ff442ca
NF
1673{
1674 register int k;
1675 register int t;
1676 register char *name;
1677
1678 t = lex();
1679
a083fbbf 1680 if (t != TYPENAME)
943819bf 1681 {
27821bff 1682 complain (_("invalid %s declaration"), "%type");
943819bf
RS
1683 return t;
1684 }
1ff442ca
NF
1685
1686 k = strlen(token_buffer);
1687 name = NEW2(k + 1, char);
1688 strcpy(name, token_buffer);
1689
1690 for (;;)
1691 {
1692 t = lex();
1693
1694 switch (t)
1695 {
1696 case SEMICOLON:
36281465 1697 return lex();
1ff442ca
NF
1698
1699 case COMMA:
1700 break;
1701
1702 case IDENTIFIER:
1703 if (symval->type_name == NULL)
1704 symval->type_name = name;
943819bf 1705 else if (strcmp(name, symval->type_name) != 0)
a0f6b076 1706 complain (_("type redeclaration for %s"), symval->tag);
1ff442ca
NF
1707
1708 break;
1709
1710 default:
36281465 1711 return t;
1ff442ca
NF
1712 }
1713 }
1714}
2686a6e7 1715#endif
1ff442ca
NF
1716
1717
0a6384c4
AD
1718/* Assign symbol numbers, and write definition of token names into
1719 fdefines. Set up vectors tags and sprec of names and precedences
1720 of symbols. */
1ff442ca 1721
4a120d45 1722static void
118fb205 1723packsymbols (void)
1ff442ca
NF
1724{
1725 register bucket *bp;
1726 register int tokno = 1;
1727 register int i;
1728 register int last_user_token_number;
4a120d45 1729 static char DOLLAR[] = "$";
1ff442ca
NF
1730
1731 /* int lossage = 0; JF set but not used */
1732
1733 tags = NEW2(nsyms + 1, char *);
4a120d45 1734 tags[0] = DOLLAR;
d019d655 1735 user_toknums = NEW2(nsyms + 1, short);
943819bf 1736 user_toknums[0] = 0;
1ff442ca
NF
1737
1738 sprec = NEW2(nsyms, short);
1739 sassoc = NEW2(nsyms, short);
1740
1741 max_user_token_number = 256;
1742 last_user_token_number = 256;
1743
1744 for (bp = firstsymbol; bp; bp = bp->next)
1745 {
1746 if (bp->class == SNTERM)
1747 {
1748 bp->value += ntokens;
1749 }
943819bf
RS
1750 else if (bp->alias)
1751 {
0a6384c4
AD
1752 /* this symbol and its alias are a single token defn.
1753 allocate a tokno, and assign to both check agreement of
1754 ->prec and ->assoc fields and make both the same */
1755 if (bp->value == 0)
1756 bp->value = bp->alias->value = tokno++;
943819bf 1757
0a6384c4
AD
1758 if (bp->prec != bp->alias->prec)
1759 {
1760 if (bp->prec != 0 && bp->alias->prec != 0
1761 && bp->user_token_number == SALIAS)
a0f6b076
AD
1762 complain (_("conflicting precedences for %s and %s"),
1763 bp->tag, bp->alias->tag);
0a6384c4
AD
1764 if (bp->prec != 0)
1765 bp->alias->prec = bp->prec;
1766 else
1767 bp->prec = bp->alias->prec;
1768 }
943819bf 1769
0a6384c4
AD
1770 if (bp->assoc != bp->alias->assoc)
1771 {
a0f6b076
AD
1772 if (bp->assoc != 0 && bp->alias->assoc != 0
1773 && bp->user_token_number == SALIAS)
1774 complain (_("conflicting assoc values for %s and %s"),
1775 bp->tag, bp->alias->tag);
1776 if (bp->assoc != 0)
1777 bp->alias->assoc = bp->assoc;
1778 else
1779 bp->assoc = bp->alias->assoc;
1780 }
0a6384c4
AD
1781
1782 if (bp->user_token_number == SALIAS)
1783 continue; /* do not do processing below for SALIASs */
943819bf
RS
1784
1785 }
1786 else /* bp->class == STOKEN */
1787 {
1788 bp->value = tokno++;
1789 }
1790
1791 if (bp->class == STOKEN)
1ff442ca
NF
1792 {
1793 if (translations && !(bp->user_token_number))
1794 bp->user_token_number = ++last_user_token_number;
1795 if (bp->user_token_number > max_user_token_number)
1796 max_user_token_number = bp->user_token_number;
1ff442ca
NF
1797 }
1798
1799 tags[bp->value] = bp->tag;
943819bf 1800 user_toknums[bp->value] = bp->user_token_number;
1ff442ca
NF
1801 sprec[bp->value] = bp->prec;
1802 sassoc[bp->value] = bp->assoc;
1803
1804 }
1805
1806 if (translations)
1807 {
4a120d45 1808 register int j;
1ff442ca
NF
1809
1810 token_translations = NEW2(max_user_token_number+1, short);
1811
0a6384c4
AD
1812 /* initialize all entries for literal tokens to 2, the internal
1813 token number for $undefined., which represents all invalid
1814 inputs. */
4a120d45
JT
1815 for (j = 0; j <= max_user_token_number; j++)
1816 token_translations[j] = 2;
1ff442ca 1817
943819bf
RS
1818 for (bp = firstsymbol; bp; bp = bp->next)
1819 {
0a6384c4
AD
1820 if (bp->value >= ntokens)
1821 continue; /* non-terminal */
1822 if (bp->user_token_number == SALIAS)
1823 continue;
943819bf 1824 if (token_translations[bp->user_token_number] != 2)
a0f6b076
AD
1825 complain (_("tokens %s and %s both assigned number %d"),
1826 tags[token_translations[bp->user_token_number]],
1827 bp->tag,
1828 bp->user_token_number);
943819bf
RS
1829 token_translations[bp->user_token_number] = bp->value;
1830 }
1ff442ca
NF
1831 }
1832
1833 error_token_number = errtoken->value;
1834
943819bf
RS
1835 if (! noparserflag)
1836 output_token_defines(ftable);
1ff442ca
NF
1837
1838 if (startval->class == SUNKNOWN)
a0f6b076 1839 fatal (_("the start symbol %s is undefined"), startval->tag);
1ff442ca 1840 else if (startval->class == STOKEN)
a0f6b076 1841 fatal (_("the start symbol %s is a token"), startval->tag);
1ff442ca
NF
1842
1843 start_symbol = startval->value;
1844
1845 if (definesflag)
1846 {
1847 output_token_defines(fdefines);
1848
1849 if (!pure_parser)
1850 {
1851 if (spec_name_prefix)
1852 fprintf(fdefines, "\nextern YYSTYPE %slval;\n", spec_name_prefix);
1853 else
1854 fprintf(fdefines, "\nextern YYSTYPE yylval;\n");
1855 }
1856
1857 if (semantic_parser)
1858 for (i = ntokens; i < nsyms; i++)
1859 {
1860 /* don't make these for dummy nonterminals made by gensym. */
1861 if (*tags[i] != '@')
1862 fprintf(fdefines, "#define\tNT%s\t%d\n", tags[i], i);
1863 }
1864#if 0
1865 /* `fdefines' is now a temporary file, so we need to copy its
1866 contents in `done', so we can't close it here. */
1867 fclose(fdefines);
1868 fdefines = NULL;
1869#endif
1870 }
1871}
a083fbbf 1872
0a6384c4
AD
1873/* For named tokens, but not literal ones, define the name. The value
1874 is the user token number. */
1875
4a120d45 1876static void
118fb205 1877output_token_defines (FILE *file)
1ff442ca
NF
1878{
1879 bucket *bp;
943819bf
RS
1880 register char *cp, *symbol;
1881 register char c;
1ff442ca
NF
1882
1883 for (bp = firstsymbol; bp; bp = bp->next)
1884 {
943819bf 1885 symbol = bp->tag; /* get symbol */
1ff442ca 1886
943819bf
RS
1887 if (bp->value >= ntokens) continue;
1888 if (bp->user_token_number == SALIAS) continue;
1889 if ('\'' == *symbol) continue; /* skip literal character */
1890 if (bp == errtoken) continue; /* skip error token */
a083fbbf 1891 if ('\"' == *symbol)
1ff442ca 1892 {
943819bf
RS
1893 /* use literal string only if given a symbol with an alias */
1894 if (bp->alias)
1895 symbol = bp->alias->tag;
1896 else
1897 continue;
1898 }
1ff442ca 1899
943819bf
RS
1900 /* Don't #define nonliteral tokens whose names contain periods. */
1901 cp = symbol;
1902 while ((c = *cp++) && c != '.');
1903 if (c != '\0') continue;
1ff442ca 1904
a0f6b076
AD
1905 fprintf (file, "#define\t%s\t%d\n", symbol,
1906 ((translations && ! rawtoknumflag)
1907 ? bp->user_token_number
1908 : bp->value));
943819bf 1909 if (semantic_parser)
a0f6b076 1910 fprintf (file, "#define\tT%s\t%d\n", symbol, bp->value);
1ff442ca
NF
1911 }
1912
1913 putc('\n', file);
1914}
1915
1916
1917
1918/* convert the rules into the representation using rrhs, rlhs and ritems. */
1919
4a120d45 1920static void
118fb205 1921packgram (void)
1ff442ca
NF
1922{
1923 register int itemno;
1924 register int ruleno;
1925 register symbol_list *p;
1926/* register bucket *bp; JF unused */
1927
1928 bucket *ruleprec;
1929
1930 ritem = NEW2(nitems + 1, short);
1931 rlhs = NEW2(nrules, short) - 1;
1932 rrhs = NEW2(nrules, short) - 1;
1933 rprec = NEW2(nrules, short) - 1;
1934 rprecsym = NEW2(nrules, short) - 1;
1935 rassoc = NEW2(nrules, short) - 1;
1936
1937 itemno = 0;
1938 ruleno = 1;
1939
1940 p = grammar;
1941 while (p)
1942 {
1943 rlhs[ruleno] = p->sym->value;
1944 rrhs[ruleno] = itemno;
1945 ruleprec = p->ruleprec;
1946
1947 p = p->next;
1948 while (p && p->sym)
1949 {
1950 ritem[itemno++] = p->sym->value;
1951 /* A rule gets by default the precedence and associativity
1952 of the last token in it. */
1953 if (p->sym->class == STOKEN)
1954 {
1955 rprec[ruleno] = p->sym->prec;
1956 rassoc[ruleno] = p->sym->assoc;
1957 }
1958 if (p) p = p->next;
1959 }
1960
1961 /* If this rule has a %prec,
1962 the specified symbol's precedence replaces the default. */
1963 if (ruleprec)
1964 {
1965 rprec[ruleno] = ruleprec->prec;
1966 rassoc[ruleno] = ruleprec->assoc;
1967 rprecsym[ruleno] = ruleprec->value;
1968 }
1969
1970 ritem[itemno++] = -ruleno;
1971 ruleno++;
1972
1973 if (p) p = p->next;
1974 }
1975
1976 ritem[itemno] = 0;
1977}