nullable.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /* Calculate which nonterminals can expand into the null string for Bison.
  2. Copyright (C) 1984, 1989, 2000-2006, 2009-2015, 2018-2021 Free
  3. Software Foundation, Inc.
  4. This file is part of Bison, the GNU Compiler Compiler.
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  15. /* Set up NULLABLE, a vector saying which nonterminals can expand into
  16. the null string. NULLABLE[I - NTOKENS] is nonzero if symbol I can
  17. do so. */
  18. #include <config.h>
  19. #include "system.h"
  20. #include "getargs.h"
  21. #include "gram.h"
  22. #include "nullable.h"
  23. #include "reduce.h"
  24. #include "symtab.h"
  25. /* Linked list of rules. */
  26. typedef struct rule_list
  27. {
  28. struct rule_list *next;
  29. const rule *value;
  30. } rule_list;
  31. bool *nullable = NULL;
  32. static void
  33. nullable_print (FILE *out)
  34. {
  35. fputs ("NULLABLE\n", out);
  36. for (int i = ntokens; i < nsyms; i++)
  37. fprintf (out, " %s: %s\n", symbols[i]->tag,
  38. nullable[i - ntokens] ? "yes" : "no");
  39. fputs ("\n\n", out);
  40. }
  41. void
  42. nullable_compute (void)
  43. {
  44. nullable = xcalloc (nnterms, sizeof *nullable);
  45. size_t *rcount = xcalloc (nrules, sizeof *rcount);
  46. /* RITEM contains all the rules, including useless productions.
  47. Hence we must allocate room for useless nonterminals too. */
  48. rule_list **rsets = xcalloc (nnterms, sizeof *rsets);
  49. /* This is said to be more elements than we actually use.
  50. Supposedly NRITEMS - NRULES is enough. But why take the risk? */
  51. rule_list *relts = xnmalloc (nritems + nnterms + 1, sizeof *relts);
  52. symbol_number *squeue = xnmalloc (nnterms, sizeof *squeue);
  53. symbol_number *s2 = squeue;
  54. {
  55. rule_list *p = relts;
  56. for (rule_number ruleno = 0; ruleno < nrules; ++ruleno)
  57. if (rules[ruleno].useful)
  58. {
  59. const rule *r = &rules[ruleno];
  60. if (r->rhs[0] >= 0)
  61. {
  62. /* This rule has a non empty RHS. */
  63. bool any_tokens = false;
  64. for (item_number *rp = r->rhs; *rp >= 0; ++rp)
  65. if (ISTOKEN (*rp))
  66. any_tokens = true;
  67. /* This rule has only nonterminals: schedule it for the second
  68. pass. */
  69. if (!any_tokens)
  70. for (item_number *rp = r->rhs; *rp >= 0; ++rp)
  71. {
  72. rcount[ruleno]++;
  73. p->next = rsets[*rp - ntokens];
  74. p->value = r;
  75. rsets[*rp - ntokens] = p;
  76. p++;
  77. }
  78. }
  79. else
  80. {
  81. /* This rule has an empty RHS. */
  82. if (r->useful
  83. && ! nullable[r->lhs->number - ntokens])
  84. {
  85. nullable[r->lhs->number - ntokens] = true;
  86. *s2++ = r->lhs->number;
  87. }
  88. }
  89. }
  90. }
  91. symbol_number *s1 = squeue;
  92. while (s1 < s2)
  93. for (rule_list *p = rsets[*s1++ - ntokens]; p; p = p->next)
  94. {
  95. const rule *r = p->value;
  96. if (--rcount[r->number] == 0)
  97. if (r->useful && ! nullable[r->lhs->number - ntokens])
  98. {
  99. nullable[r->lhs->number - ntokens] = true;
  100. *s2++ = r->lhs->number;
  101. }
  102. }
  103. free (squeue);
  104. free (rcount);
  105. free (rsets);
  106. free (relts);
  107. if (trace_flag & trace_sets)
  108. nullable_print (stderr);
  109. }
  110. void
  111. nullable_free (void)
  112. {
  113. free (nullable);
  114. }