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