Home | History | Annotate | Download | only in src
      1 /* Calculate which nonterminals can expand into the null string for Bison.
      2 
      3    Copyright (C) 1984, 1989, 2000, 2001, 2002, 2003, 2004, 2005, 2006
      4    Free Software Foundation, Inc.
      5 
      6    This file is part of Bison, the GNU Compiler Compiler.
      7 
      8    Bison 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 2, or (at your option)
     11    any later version.
     12 
     13    Bison 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 Bison; see the file COPYING.  If not, write to
     20    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     21    Boston, MA 02110-1301, USA.  */
     22 
     23 
     24 /* Set up NULLABLE, a vector saying which nonterminals can expand into
     25    the null string.  NULLABLE[I - NTOKENS] is nonzero if symbol I can
     26    do so.  */
     27 
     28 #include <config.h>
     29 #include "system.h"
     30 
     31 #include "getargs.h"
     32 #include "gram.h"
     33 #include "nullable.h"
     34 #include "reduce.h"
     35 #include "symtab.h"
     36 
     37 /* Linked list of rules.  */
     38 typedef struct rule_list
     39 {
     40   struct rule_list *next;
     41   rule *value;
     42 } rule_list;
     43 
     44 bool *nullable = NULL;
     45 
     46 static void
     47 nullable_print (FILE *out)
     48 {
     49   int i;
     50   fputs ("NULLABLE\n", out);
     51   for (i = ntokens; i < nsyms; i++)
     52     fprintf (out, "\t%s: %s\n", symbols[i]->tag,
     53 	     nullable[i - ntokens] ? "yes" : "no");
     54   fputs ("\n\n", out);
     55 }
     56 
     57 void
     58 nullable_compute (void)
     59 {
     60   rule_number ruleno;
     61   symbol_number *s1;
     62   symbol_number *s2;
     63   rule_list *p;
     64 
     65   symbol_number *squeue = xnmalloc (nvars, sizeof *squeue);
     66   size_t *rcount = xcalloc (nrules, sizeof *rcount);
     67   /* RITEM contains all the rules, including useless productions.
     68      Hence we must allocate room for useless nonterminals too.  */
     69   rule_list **rsets = xcalloc (nvars, sizeof *rsets);
     70   /* This is said to be more elements than we actually use.
     71      Supposedly NRITEMS - NRULES is enough.  But why take the risk?  */
     72   rule_list *relts = xnmalloc (nritems + nvars + 1, sizeof *relts);
     73 
     74   nullable = xcalloc (nvars, sizeof *nullable);
     75 
     76   s1 = s2 = squeue;
     77   p = relts;
     78 
     79   for (ruleno = 0; ruleno < nrules; ++ruleno)
     80     if (rules[ruleno].useful)
     81       {
     82 	rule *rules_ruleno = &rules[ruleno];
     83 	if (rules_ruleno->rhs[0] >= 0)
     84 	  {
     85 	    /* This rule has a non empty RHS. */
     86 	    item_number *rp = NULL;
     87 	    bool any_tokens = false;
     88 	    for (rp = rules_ruleno->rhs; *rp >= 0; ++rp)
     89 	      if (ISTOKEN (*rp))
     90 		any_tokens = true;
     91 
     92 	    /* This rule has only nonterminals: schedule it for the second
     93 	       pass.  */
     94 	    if (!any_tokens)
     95 	      for (rp = rules_ruleno->rhs; *rp >= 0; ++rp)
     96 		{
     97 		  rcount[ruleno]++;
     98 		  p->next = rsets[*rp - ntokens];
     99 		  p->value = rules_ruleno;
    100 		  rsets[*rp - ntokens] = p;
    101 		  p++;
    102 		}
    103 	  }
    104 	else
    105 	  {
    106 	    /* This rule has an empty RHS. */
    107 	    assert (item_number_as_rule_number (rules_ruleno->rhs[0])
    108 		    == ruleno);
    109 	    if (rules_ruleno->useful
    110 		&& ! nullable[rules_ruleno->lhs->number - ntokens])
    111 	      {
    112 		nullable[rules_ruleno->lhs->number - ntokens] = true;
    113 		*s2++ = rules_ruleno->lhs->number;
    114 	      }
    115 	  }
    116       }
    117 
    118   while (s1 < s2)
    119     for (p = rsets[*s1++ - ntokens]; p; p = p->next)
    120       {
    121 	rule *r = p->value;
    122 	if (--rcount[r->number] == 0)
    123 	  if (r->useful && ! nullable[r->lhs->number - ntokens])
    124 	    {
    125 	      nullable[r->lhs->number - ntokens] = true;
    126 	      *s2++ = r->lhs->number;
    127 	    }
    128       }
    129 
    130   free (squeue);
    131   free (rcount);
    132   free (rsets);
    133   free (relts);
    134 
    135   if (trace_flag & trace_sets)
    136     nullable_print (stderr);
    137 }
    138 
    139 
    140 void
    141 nullable_free (void)
    142 {
    143   free (nullable);
    144 }
    145