(root)/
bison-3.8.2/
src/
gram.c
       1  /* Allocate input grammar variables for Bison.
       2  
       3     Copyright (C) 1984, 1986, 1989, 2001-2003, 2005-2015, 2018-2021 Free
       4     Software Foundation, Inc.
       5  
       6     This file is part of Bison, the GNU Compiler Compiler.
       7  
       8     This program is free software: you can redistribute it and/or modify
       9     it under the terms of the GNU General Public License as published by
      10     the Free Software Foundation, either version 3 of the License, or
      11     (at your option) any later version.
      12  
      13     This program is distributed in the hope that it will be useful,
      14     but WITHOUT ANY WARRANTY; without even the implied warranty of
      15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16     GNU General Public License for more details.
      17  
      18     You should have received a copy of the GNU General Public License
      19     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      20  
      21  #include <config.h>
      22  #include "system.h"
      23  
      24  #include "complain.h"
      25  #include "getargs.h"
      26  #include "glyphs.h"
      27  #include "gram.h"
      28  #include "print-xml.h"
      29  #include "reader.h"
      30  #include "reduce.h"
      31  #include "symtab.h"
      32  
      33  /* Comments for these variables are in gram.h.  */
      34  
      35  item_number *ritem = NULL;
      36  int nritems = 0;
      37  
      38  rule *rules = NULL;
      39  rule_number nrules = 0;
      40  
      41  symbol **symbols = NULL;
      42  int nsyms = 0;
      43  int ntokens = 1;
      44  int nnterms = 0;
      45  
      46  symbol_number *token_translations = NULL;
      47  
      48  int max_code = 256;
      49  
      50  int required_version = 0;
      51  
      52  void
      53  item_print (item_number *item, rule const *previous_rule, FILE *out)
      54  {
      55    rule const *r = item_rule (item);
      56    rule_lhs_print (r, previous_rule ? previous_rule->lhs : NULL, out);
      57  
      58    if (0 <= *r->rhs)
      59      {
      60        // Non-empty rhs.
      61        for (item_number *sp = r->rhs; sp < item; sp++)
      62          fprintf (out, " %s", symbols[*sp]->tag);
      63        fprintf (out, " %s", dot);
      64        for (item_number *sp = item; 0 <= *sp; ++sp)
      65          fprintf (out, " %s", symbols[*sp]->tag);
      66      }
      67    else
      68      fprintf (out, " %s %s", empty, dot);
      69  }
      70  
      71  
      72  bool
      73  rule_useful_in_grammar_p (rule const *r)
      74  {
      75    return r->number < nrules;
      76  }
      77  
      78  bool
      79  rule_useless_in_grammar_p (rule const *r)
      80  {
      81    return !rule_useful_in_grammar_p (r);
      82  }
      83  
      84  bool
      85  rule_useless_in_parser_p (rule const *r)
      86  {
      87    return !r->useful && rule_useful_in_grammar_p (r);
      88  }
      89  
      90  bool
      91  rule_useless_chain_p (rule const *r)
      92  {
      93    return rule_rhs_length (r) == 1 && !r->action;
      94  }
      95  
      96  void
      97  rule_lhs_print (rule const *r, sym_content const *previous_lhs, FILE *out)
      98  {
      99    fprintf (out, "  %3d ", r->number);
     100    if (previous_lhs != r->lhs)
     101      fprintf (out, "%s:", r->lhs->symbol->tag);
     102    else
     103      fprintf (out, "%*s|", (int) strlen (previous_lhs->symbol->tag), "");
     104  }
     105  
     106  void
     107  rule_lhs_print_xml (rule const *r, FILE *out, int level)
     108  {
     109    xml_printf (out, level, "<lhs>%s</lhs>", r->lhs->symbol->tag);
     110  }
     111  
     112  size_t
     113  rule_rhs_length (rule const *r)
     114  {
     115    size_t res = 0;
     116    for (item_number *rhsp = r->rhs; 0 <= *rhsp; ++rhsp)
     117      ++res;
     118    return res;
     119  }
     120  
     121  void
     122  rule_rhs_print (rule const *r, FILE *out)
     123  {
     124    if (0 <= *r->rhs)
     125      for (item_number *rhsp = r->rhs; 0 <= *rhsp; ++rhsp)
     126        fprintf (out, " %s", symbols[*rhsp]->tag);
     127    else
     128      fprintf (out, " %s", empty);
     129  }
     130  
     131  static void
     132  rule_rhs_print_xml (rule const *r, FILE *out, int level)
     133  {
     134    if (*r->rhs >= 0)
     135      {
     136        xml_puts (out, level, "<rhs>");
     137        for (item_number *rhsp = r->rhs; 0 <= *rhsp; ++rhsp)
     138          xml_printf (out, level + 1, "<symbol>%s</symbol>",
     139                      xml_escape (symbols[*rhsp]->tag));
     140        xml_puts (out, level, "</rhs>");
     141      }
     142    else
     143      {
     144        xml_puts (out, level, "<rhs>");
     145        xml_puts (out, level + 1, "<empty/>");
     146        xml_puts (out, level, "</rhs>");
     147      }
     148  }
     149  
     150  void
     151  rule_print (rule const *r, rule const *prev_rule, FILE *out)
     152  {
     153    rule_lhs_print (r, prev_rule ? prev_rule->lhs : NULL, out);
     154    rule_rhs_print (r, out);
     155  }
     156  
     157  void
     158  ritem_print (FILE *out)
     159  {
     160    fputs ("RITEM\n", out);
     161    bool first = true;
     162    for (int i = 0; i < nritems; ++i)
     163      {
     164        if (first)
     165          {
     166            fprintf (out, "  %d: ", i);
     167            first = false;
     168          }
     169        if (ritem[i] >= 0)
     170          fprintf (out, "  %s", symbols[ritem[i]]->tag);
     171        else
     172          {
     173            fprintf (out, "  (rule %d)\n", item_number_as_rule_number (ritem[i]));
     174            first = true;
     175          }
     176      }
     177    fputs ("\n\n", out);
     178  }
     179  
     180  size_t
     181  ritem_longest_rhs (void)
     182  {
     183    int max = 0;
     184    for (rule_number r = 0; r < nrules; ++r)
     185      {
     186        size_t length = rule_rhs_length (&rules[r]);
     187        if (length > max)
     188          max = length;
     189      }
     190  
     191    return max;
     192  }
     193  
     194  void
     195  grammar_rules_partial_print (FILE *out, const char *title,
     196                               rule_filter filter)
     197  {
     198    bool first = true;
     199    rule *previous_rule = NULL;
     200  
     201    /* rule # : LHS -> RHS */
     202    for (rule_number r = 0; r < nrules + nuseless_productions; r++)
     203      {
     204        if (filter && !filter (&rules[r]))
     205          continue;
     206        if (first)
     207          fprintf (out, "%s\n\n", title);
     208        else if (previous_rule && previous_rule->lhs != rules[r].lhs)
     209          putc ('\n', out);
     210        first = false;
     211        rule_print (&rules[r], previous_rule, out);
     212        putc ('\n', out);
     213        previous_rule = &rules[r];
     214      }
     215    if (!first)
     216      fputs ("\n\n", out);
     217  }
     218  
     219  void
     220  grammar_rules_print (FILE *out)
     221  {
     222    grammar_rules_partial_print (out, _("Grammar"), rule_useful_in_grammar_p);
     223  }
     224  
     225  void
     226  grammar_rules_print_xml (FILE *out, int level)
     227  {
     228    bool first = true;
     229  
     230    for (rule_number r = 0; r < nrules + nuseless_productions; r++)
     231      {
     232        if (first)
     233          xml_puts (out, level + 1, "<rules>");
     234        first = false;
     235        {
     236          char const *usefulness
     237            = rule_useless_in_grammar_p (&rules[r]) ? "useless-in-grammar"
     238            : rule_useless_in_parser_p (&rules[r])  ? "useless-in-parser"
     239            :                                         "useful";
     240          xml_indent (out, level + 2);
     241          fprintf (out, "<rule number=\"%d\" usefulness=\"%s\"",
     242                   rules[r].number, usefulness);
     243          if (rules[r].precsym)
     244            fprintf (out, " percent_prec=\"%s\"",
     245                     xml_escape (rules[r].precsym->symbol->tag));
     246          fputs (">\n", out);
     247        }
     248        rule_lhs_print_xml (&rules[r], out, level + 3);
     249        rule_rhs_print_xml (&rules[r], out, level + 3);
     250        xml_puts (out, level + 2, "</rule>");
     251      }
     252    if (!first)
     253      xml_puts (out, level + 1, "</rules>");
     254    else
     255     xml_puts (out, level + 1, "<rules/>");
     256  }
     257  
     258  static void
     259  section (FILE *out, const char *s)
     260  {
     261    fprintf (out, "%s\n", s);
     262    for (int i = strlen (s); 0 < i; --i)
     263      putc ('-', out);
     264    putc ('\n', out);
     265    putc ('\n', out);
     266  }
     267  
     268  void
     269  grammar_dump (FILE *out, const char *title)
     270  {
     271    fprintf (out, "%s\n\n", title);
     272    fprintf (out,
     273             "ntokens = %d, nnterms = %d, nsyms = %d, nrules = %d, nritems = %d\n\n",
     274             ntokens, nnterms, nsyms, nrules, nritems);
     275  
     276    section (out, "Tokens");
     277    {
     278      fprintf (out, "Value  Sprec  Sassoc  Tag\n");
     279  
     280      for (symbol_number i = 0; i < ntokens; i++)
     281        fprintf (out, "%5d  %5d   %5d  %s\n",
     282                 i,
     283                 symbols[i]->content->prec, symbols[i]->content->assoc,
     284                 symbols[i]->tag);
     285      fprintf (out, "\n\n");
     286    }
     287  
     288    section (out, "Nonterminals");
     289    {
     290      fprintf (out, "Value  Tag\n");
     291  
     292      for (symbol_number i = ntokens; i < nsyms; i++)
     293        fprintf (out, "%5d  %s\n",
     294                 i, symbols[i]->tag);
     295      fprintf (out, "\n\n");
     296    }
     297  
     298    section (out, "Rules");
     299    {
     300      fprintf (out,
     301               "Num (Prec, Assoc, Useful, UselessChain) Lhs"
     302               " -> (Ritem Range) Rhs\n");
     303      for (rule_number i = 0; i < nrules + nuseless_productions; ++i)
     304        {
     305          rule const *rule_i = &rules[i];
     306          int const rhs_itemno = rule_i->rhs - ritem;
     307          int length = rule_rhs_length (rule_i);
     308          aver (item_number_as_rule_number (rule_i->rhs[length]) == i);
     309          fprintf (out, "%3d (%2d, %2d, %2s, %2s)   %2d -> (%2u-%2u)",
     310                   i,
     311                   rule_i->prec ? rule_i->prec->prec : 0,
     312                   rule_i->prec ? rule_i->prec->assoc : 0,
     313                   rule_i->useful ? "t" : "f",
     314                   rule_useless_chain_p (rule_i) ? "t" : "f",
     315                   rule_i->lhs->number,
     316                   rhs_itemno, rhs_itemno + length - 1);
     317          /* Dumped the RHS. */
     318          for (item_number *rhsp = rule_i->rhs; 0 <= *rhsp; ++rhsp)
     319            fprintf (out, " %3d", *rhsp);
     320          putc ('\n', out);
     321        }
     322    }
     323    fprintf (out, "\n\n");
     324  
     325    section (out, "Rules interpreted");
     326    for (rule_number r = 0; r < nrules + nuseless_productions; ++r)
     327      {
     328        fprintf (out, "%-5d  %s:", r, rules[r].lhs->symbol->tag);
     329        rule_rhs_print (&rules[r], out);
     330        putc ('\n', out);
     331      }
     332    fprintf (out, "\n\n");
     333  }
     334  
     335  void
     336  grammar_rules_useless_report (const char *message)
     337  {
     338    for (rule_number r = 0; r < nrules; ++r)
     339      /* Don't complain about rules whose LHS is useless, we already
     340         complained about it.  */
     341      if (!reduce_nonterminal_useless_in_grammar (rules[r].lhs)
     342          && !rules[r].useful)
     343        complain (&rules[r].location, Wother, "%s", message);
     344  }
     345  
     346  void
     347  grammar_free (void)
     348  {
     349    if (ritem)
     350      free (ritem - 1);
     351    free (rules);
     352    free (token_translations);
     353    /* Free the symbol table data structure.  */
     354    symbols_free ();
     355    free_merger_functions ();
     356  }