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