X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/9e7f6bbd5930d4d7365f65d33721cfbf651ca487..ea6cfe9ebd960e2cb4573c2c6f02b02931ac1f86:/src/output.c diff --git a/src/output.c b/src/output.c index 94ad4256..702f0cb1 100644 --- a/src/output.c +++ b/src/output.c @@ -1,5 +1,5 @@ /* Output the generated parsing program for bison, - Copyright 1984, 1986, 1989, 1992, 2000, 2001 + Copyright (C) 1984, 1986, 1989, 1992, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -90,6 +90,7 @@ #include "system.h" #include "quotearg.h" +#include "error.h" #include "getargs.h" #include "files.h" #include "gram.h" @@ -98,9 +99,16 @@ #include "output.h" #include "lalr.h" #include "reader.h" +#include "symtab.h" #include "conflicts.h" #include "muscle_tab.h" +/* From lib/readpipe.h. */ +FILE *readpipe PARAMS ((const char *, ...)); + +/* From src/scan-skel.l. */ +int skel_lex PARAMS ((void)); +extern FILE *skel_in; static int nvectors; static int nentries; @@ -124,7 +132,7 @@ static struct obstack format_obstack; int error_verbose = 0; /* Returns the number of lines of S. */ -static size_t +size_t get_lines_number (const char *s) { size_t lines = 0; @@ -184,7 +192,7 @@ output_gram (void) int i; short *values = XCALLOC (short, nrules + 1); for (i = 0; i < nrules + 1; ++i) - values[i] = rule_table[i].rhs; + values[i] = rules[i].rhs; output_table_data (&format_obstack, values, 0, 1, nrules + 1); XFREE (values); @@ -221,7 +229,7 @@ output_stos (void) int i; short *values = (short *) alloca (sizeof (short) * nstates); for (i = 0; i < nstates; ++i) - values[i] = state_table[i]->accessing_symbol; + values[i] = states[i]->accessing_symbol; output_table_data (&format_obstack, values, 0, 1, nstates); muscle_insert ("stos", obstack_finish (&format_obstack)); @@ -238,7 +246,7 @@ output_rule_data (void) { short *values = XCALLOC (short, nrules + 1); for (i = 0; i < nrules + 1; ++i) - values[i] = rule_table[i].line; + values[i] = rules[i].line; output_table_data (&format_obstack, values, 0, 1, nrules + 1); muscle_insert ("rline", obstack_finish (&format_obstack)); @@ -252,7 +260,7 @@ output_rule_data (void) /* Be sure not to use twice the same quotearg slot. */ const char *cp = quotearg_n_style (1, c_quoting_style, - quotearg_style (escape_quoting_style, tags[i])); + quotearg_style (escape_quoting_style, symbols[i]->tag)); /* Width of the next token, including the two quotes, the coma and the space. */ int strsize = strlen (cp) + 2; @@ -275,15 +283,22 @@ output_rule_data (void) muscle_insert ("tname", obstack_finish (&format_obstack)); /* Output YYTOKNUM. */ - output_table_data (&format_obstack, user_toknums, - 0, 1, ntokens + 1); - muscle_insert ("toknum", obstack_finish (&format_obstack)); + { + short *values = XCALLOC (short, ntokens + 1); + for (i = 0; i < ntokens + 1; ++i) + values[i] = symbols[i]->user_token_number; + output_table_data (&format_obstack, values, + 0, 1, ntokens + 1); + muscle_insert ("toknum", obstack_finish (&format_obstack)); + XFREE (values); + } + /* Output YYR1. */ { short *values = XCALLOC (short, nrules + 1); for (i = 0; i < nrules + 1; ++i) - values[i] = rule_table[i].lhs; + values[i] = rules[i].lhs; output_table_data (&format_obstack, values, 0, 1, nrules + 1); muscle_insert ("r1", obstack_finish (&format_obstack)); @@ -293,8 +308,8 @@ output_rule_data (void) /* Output YYR2. */ short_tab = XMALLOC (short, nrules + 1); for (i = 1; i < nrules; i++) - short_tab[i] = rule_table[i + 1].rhs - rule_table[i].rhs - 1; - short_tab[nrules] = nritems - rule_table[nrules].rhs - 1; + short_tab[i] = rules[i + 1].rhs - rules[i].rhs - 1; + short_tab[nrules] = nritems - rules[nrules].rhs - 1; output_table_data (&format_obstack, short_tab, 0, 1, nrules + 1); muscle_insert ("r2", obstack_finish (&format_obstack)); @@ -354,7 +369,7 @@ action_row (state_t *state) if (!shift_state) continue; - symbol = state_table[shift_state]->accessing_symbol; + symbol = states[shift_state]->accessing_symbol; if (ISVAR (symbol)) break; @@ -478,7 +493,7 @@ token_actions (void) actrow = XCALLOC (short, ntokens); for (i = 0; i < nstates; ++i) { - yydefact[i] = action_row (state_table[i]); + yydefact[i] = action_row (states[i]); save_row (i); } @@ -495,34 +510,26 @@ token_actions (void) | Output the actions to OOUT. | `-----------------------------*/ -static void -actions_output (FILE *out, size_t *line) +void +actions_output (FILE *out) { int rule; for (rule = 1; rule < nrules + 1; ++rule) - if (rule_table[rule].action) + if (rules[rule].action) { fprintf (out, " case %d:\n", rule); if (!no_lines_flag) fprintf (out, muscle_find ("linef"), - rule_table[rule].action_line, + rules[rule].action_line, quotearg_style (c_quoting_style, muscle_find ("filename"))); /* As a Bison extension, add the ending semicolon. Since some Yacc don't do that, help people using bison as a Yacc finding their missing semicolons. */ fprintf (out, "{ %s%s }\n break;\n\n", - rule_table[rule].action, + rules[rule].action, yacc_flag ? ";" : ""); - - /* We always output 4 '\n' per action. */ - *line += 4; - /* Plus one if !no_lines_flag. */ - if (!no_lines_flag) - ++*line; - /* Get the number of lines written by the user. */ - *line += get_lines_number (rule_table[rule].action); } } @@ -531,34 +538,70 @@ actions_output (FILE *out, size_t *line) | Output the guards to OOUT. | `----------------------------*/ -static void -guards_output (FILE *out, size_t *line) +void +guards_output (FILE *out) { int rule; for (rule = 1; rule < nrules + 1; ++rule) - if (rule_table[rule].action) + if (rules[rule].guard) { fprintf (out, " case %d:\n", rule); if (!no_lines_flag) fprintf (out, muscle_find ("linef"), - rule_table[rule].guard_line, + rules[rule].guard_line, quotearg_style (c_quoting_style, muscle_find ("filename"))); fprintf (out, "{ %s; }\n break;\n\n", - rule_table[rule].guard); - - /* We always output 4 '\n' per action. */ - *line += 4; - /* Plus one if !no_lines_flag. */ - if (!no_lines_flag) - ++*line; - /* Get the number of lines written by the user. */ - *line += get_lines_number (rule_table[rule].guard); + rules[rule].guard); } } +/*---------------------------------------. +| Output the tokens definition to OOUT. | +`---------------------------------------*/ + +void +token_definitions_output (FILE *out) +{ + int i; + for (i = 0; i < ntokens; ++i) + { + bucket *symbol = symbols[i]; + int number = symbol->user_token_number; + + if (number == SALIAS) + continue; + /* Skip error token. */ + if (symbol->value == error_token_number) + continue; + if (symbol->tag[0] == '\'') + continue; /* skip literal character */ + if (symbol->tag[0] == '\"') + { + /* use literal string only if given a symbol with an alias */ + if (symbol->alias) + symbol = symbol->alias; + else + continue; + } + + /* Don't #define nonliteral tokens whose names contain periods + or '$' (as does the default value of the EOF token). */ + if (strchr (symbol->tag, '.') || strchr (symbol->tag, '$')) + continue; + + fprintf (out, "# define %s\t%d\n", + symbol->tag, number); + if (semantic_parser) + /* FIXME: This is probably wrong, and should be just as + above. --akim. */ + fprintf (out, "# define T%s\t%d\n", symbol->tag, symbol->value); + } +} + + static void save_column (int symbol, int default_state) { @@ -896,130 +939,77 @@ output_actions (void) for (i = 0; i < nstates; ++i) { - free (state_table[i]->shifts); - XFREE (state_table[i]->reductions); - free (state_table[i]->errs); - free (state_table[i]); + free (states[i]->shifts); + XFREE (states[i]->reductions); + free (states[i]->errs); + free (states[i]); } - XFREE (state_table); + XFREE (states); } -/*------------------------------------------------------------. -| Copy the parser code from SKEL_FILENAME into OOUT obstack. | -| and do the muscle substitution. | -`------------------------------------------------------------*/ +/*---------------------------. +| Call the skeleton parser. | +`---------------------------*/ static void -output_parser (const char *skel_filename, FILE *out) +output_skeleton (void) { - int c; - FILE *fskel; - size_t output_line; - size_t skeleton_line; - - fskel = xfopen (skel_filename, "r"); - - /* New output code. */ - output_line = 1; - skeleton_line = 1; - c = getc (fskel); - while (c != EOF) - { - if (c != '%') - { - if (c == '\n') - { - ++output_line; - ++skeleton_line; - } - putc (c, out); - c = getc (fskel); - } - else if ((c = getc (fskel)) == '%') - { - /* Read the muscle. */ - const char *muscle_key = 0; - const char *muscle_value = 0; - - while (isalnum (c = getc (fskel)) || c == '-') - obstack_1grow (&muscle_obstack, c); - obstack_1grow (&muscle_obstack, 0); - - /* Output the right value, or see if it's something special. */ - muscle_key = obstack_finish (&muscle_obstack); - muscle_value = muscle_find (muscle_key); - if (!strcmp (muscle_key, "actions")) - actions_output (out, &output_line); - else if (!strcmp (muscle_key, "guards")) - guards_output (out, &output_line); - else if (!strcmp (muscle_key, "line")) - fprintf (out, "%d", output_line); - else if (!strcmp (muscle_key, "skeleton-line")) - fprintf (out, "%d", skeleton_line); - else if (muscle_value) - { - fputs (muscle_value, out); - output_line += get_lines_number (muscle_value); - } - else - { - fputs ("%%", out); - fputs (muscle_key, out); - } - } - else - putc ('%', out); - } - - /* End. */ - xfclose (fskel); -} - -/*----------------------------------------. -| Prepare the master parser to be output | -`----------------------------------------*/ - -static void -output_master_parser (void) -{ - FILE *parser = xfopen (parser_file_name, "w"); + /* Find the right skeleton file. */ if (!skeleton) { if (semantic_parser) - skeleton = skeleton_find ("BISON_HAIRY", BISON_HAIRY); + skeleton = "bison.hairy"; else - skeleton = skeleton_find ("BISON_SIMPLE", BISON_SIMPLE); + skeleton = "bison.simple"; } + + /* Parse the skeleton file and output the needed parsers. */ muscle_insert ("skeleton", skeleton); - muscle_insert ("parser-file-name", parser_file_name); - output_parser (skeleton, parser); - xfclose (parser); -} + /* Store the definition of all the muscles. */ + { + FILE *muscles_m4 = xfopen ("/tmp/muscles.m4", "w"); + /* There are no comments, especially not `#': we do want M4 expansion + after `#': think of CPP macros! */ + fprintf (muscles_m4, "m4_changecom()\n"); + fprintf (muscles_m4, "m4_init()\n"); + fprintf (muscles_m4, "m4_define([b4_actions], \n[["); + actions_output (muscles_m4); + fprintf (muscles_m4, "]])\n\n"); -/* FIXME. */ + fprintf (muscles_m4, "m4_define([b4_guards], \n[["); + guards_output (muscles_m4); + fprintf (muscles_m4, "]])\n\n"); -#define MUSCLE_INSERT_INT(Key, Value) \ -{ \ - obstack_fgrow1 (&muscle_obstack, "%d", Value); \ - obstack_1grow (&muscle_obstack, 0); \ - muscle_insert (Key, obstack_finish (&muscle_obstack)); \ -} + fprintf (muscles_m4, "m4_define([b4_tokendef], \n[["); + token_definitions_output (muscles_m4); + fprintf (muscles_m4, "]])\n\n"); -#define MUSCLE_INSERT_STRING(Key, Value) \ -{ \ - obstack_sgrow (&muscle_obstack, Value); \ - obstack_1grow (&muscle_obstack, 0); \ - muscle_insert (Key, obstack_finish (&muscle_obstack)); \ -} + muscles_m4_output (muscles_m4); -#define MUSCLE_INSERT_PREFIX(Key, Value) \ -{ \ - obstack_fgrow2 (&muscle_obstack, "%s%s", spec_name_prefix, Value); \ - obstack_1grow (&muscle_obstack, 0); \ - muscle_insert (Key, obstack_finish (&muscle_obstack)); \ + fprintf (muscles_m4, "m4_wrap([m4_divert_pop(0)])\n"); + fprintf (muscles_m4, "m4_divert_push(0)dnl\n"); + xfclose (muscles_m4); + } + + /* Invoke m4 on the definition of the muscles, and the skeleton. */ + { + const char *bison_pkgdatadir = getenv ("BISON_PKGDATADIR"); + if (!bison_pkgdatadir) + bison_pkgdatadir = PKGDATADIR; + skel_in = readpipe ("m4", + "-I", + bison_pkgdatadir, + "m4sugar/m4sugar.m4", + "/tmp/muscles.m4", + skeleton, + NULL); + if (!skel_in) + error (EXIT_FAILURE, errno, "cannot run m4"); + skel_lex (); + } } static void @@ -1032,18 +1022,25 @@ prepare (void) MUSCLE_INSERT_INT ("debug", debug_flag); MUSCLE_INSERT_INT ("final", final_state); MUSCLE_INSERT_INT ("maxtok", max_user_token_number); - MUSCLE_INSERT_INT ("error-verbose", error_verbose); - MUSCLE_INSERT_STRING ("prefix", spec_name_prefix); + MUSCLE_INSERT_INT ("error_verbose", error_verbose); + MUSCLE_INSERT_STRING ("prefix", spec_name_prefix ? spec_name_prefix : "yy"); + + /* FIXME: This is wrong: the muscles should decide whether they hold + a copy or not, but the situation is too obscure currently. */ + MUSCLE_INSERT_STRING ("output_infix", output_infix ? output_infix : ""); + MUSCLE_INSERT_STRING ("output_prefix", short_base_name); + MUSCLE_INSERT_STRING ("output_parser_name", parser_file_name); + MUSCLE_INSERT_STRING ("output_header_name", spec_defines_file); MUSCLE_INSERT_INT ("nnts", nvars); MUSCLE_INSERT_INT ("nrules", nrules); MUSCLE_INSERT_INT ("nstates", nstates); MUSCLE_INSERT_INT ("ntokens", ntokens); - MUSCLE_INSERT_INT ("locations-flag", locations_flag); + MUSCLE_INSERT_INT ("locations_flag", locations_flag); + MUSCLE_INSERT_INT ("defines_flag", defines_flag); } - /*-------------------------. | Output the header file. | `-------------------------*/ @@ -1057,7 +1054,7 @@ header_output (void) fprintf (out, "#ifndef %s\n", macro_name); fprintf (out, "# define %s\n\n", macro_name); - fputs (muscle_find ("tokendef"), out); + token_definitions_output (out); fprintf (out, "\ #ifndef YYSTYPE\n\ typedef %s @@ -1068,15 +1065,35 @@ yystype;\n\ if (!pure_parser) fprintf (out, "\nextern YYSTYPE %slval;\n", - spec_name_prefix); + spec_name_prefix ? spec_name_prefix : "yy"); + + if (locations_flag) + { + fputs ("\n\n", out); + fprintf (out, "\ +#ifndef YYLTYPE\n\ +typedef struct yyltype\n\ +{\n\ + int first_line;\n\ + int first_column;\n\ + int last_line;\n\ + int last_column;\n\ +} yyltype;\n\ +# define YYLTYPE yyltype\n\ +#endif\n"); + if (!pure_parser) + fprintf (out, "\nextern YYLTYPE %slloc;\n", + spec_name_prefix ? spec_name_prefix : "yy"); + } + if (semantic_parser) { int i; for (i = ntokens; i < nsyms; i++) /* don't make these for dummy nonterminals made by gensym. */ - if (*tags[i] != '@') - fprintf (out, "# define NT%s\t%d\n", tags[i], i); + if (*symbols[i]->tag != '@') + fprintf (out, "# define NT%s\t%d\n", symbols[i]->tag, i); } fprintf (out, "\n#endif /* not %s */\n", macro_name); @@ -1101,7 +1118,6 @@ output (void) if (semantic_parser) output_stos (); output_rule_data (); - XFREE (user_toknums); output_actions (); prepare (); @@ -1109,13 +1125,15 @@ output (void) obstack_1grow (&attrs_obstack, 0); muscle_insert ("prologue", obstack_finish (&attrs_obstack)); - /* Output the parser. */ - output_master_parser (); + /* Process the selected skeleton file. */ + output_skeleton (); + /* Output the header if needed. */ - if (defines_flag) + + if (0) header_output (); - free (rule_table + 1); + free (rules + 1); obstack_free (&muscle_obstack, NULL); obstack_free (&format_obstack, NULL); obstack_free (&action_obstack, NULL);