preen.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Copyright 2021
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  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. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * SPDX-License-Identifier: GPL-3.0+
  18. * License-Filename: LICENSE
  19. */
  20. #include <assert.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include "error.h"
  25. #include "preen.h"
  26. #include "syntax.h"
  27. /* XXX check_redef is O(n²) */
  28. static void check_redef(struct s_node *g) {
  29. struct s_node *p, *q;
  30. for (p = g->first->next; p; p = p->next)
  31. for (q = g->first->next; q != p; q = q->next)
  32. if (strcmp(p->text, q->text) == 0)
  33. fatal3("rule `", p->text, "' redefined");
  34. }
  35. static void resolve(struct s_node *g, struct s_node *n, struct s_node *from) {
  36. struct s_node *p;
  37. if (n->type == rule) from = n;
  38. if (n->type == call && !n->first) {
  39. struct s_node *i;
  40. for (i = g->first; i; i = i->next) {
  41. if (i->type != rule) continue;
  42. if (strcmp(i->text, n->text) == 0)
  43. n->first = i;
  44. }
  45. if (!n->first)
  46. fatal5("rule not found: `", n->text,
  47. "' (called from `", from->text, "')");
  48. }
  49. if (s_has_children(n->type))
  50. for (p = n->first; p; p = p->next)
  51. resolve(g, p, from);
  52. }
  53. /* Starting from the start rule, we should sooner or later call every rule in
  54. * the grammar. */
  55. static void reached(struct s_node *n) {
  56. struct s_node *p;
  57. if (n->type == rule)
  58. n->reached = 1;
  59. if (n->type == call && !n->first->reached)
  60. reached(n->first);
  61. if (s_has_children(n->type))
  62. for (p = n->first; p; p = p->next)
  63. reached(p);
  64. }
  65. static void check_reached(struct s_node *g) {
  66. struct s_node *p;
  67. for (p = g->first->next; p; p = p->next) {
  68. assert(p->type == rule);
  69. p->reached = 0;
  70. }
  71. reached(g->first->next);
  72. for (p = g->first->next; p; p = p->next) {
  73. assert(p->type == rule);
  74. if (!p->reached)
  75. warn3("rule `", p->text, "' not reached");
  76. p->reached = 0;
  77. }
  78. }
  79. /* Every path through a rule must consume some input before that rule is called
  80. * again, otherwise we have a left recursion. */
  81. static int consumes(struct s_node *n) {
  82. struct s_node *p;
  83. int r;
  84. switch (n->type) {
  85. case rule:
  86. if (n->reached)
  87. fatal3("left recursion in rule `", n->text, "'");
  88. r = 0;
  89. n->reached = 1;
  90. for (p = n->first; p; p = p->next)
  91. r += consumes(p);
  92. n->reached = 0;
  93. return r;
  94. case lit:
  95. return strlen(n->text) > 0;
  96. case any: case cclass:
  97. return 1;
  98. case rep:
  99. return n->text && n->text[0] == '1';
  100. case call:
  101. return consumes(n->first);
  102. case and: case not: case guard:
  103. return 0;
  104. case alt:
  105. r = 1;
  106. for (p = n->first; p; p = p->next)
  107. if (!consumes(p)) r = 0;
  108. return r;
  109. default:
  110. if (s_has_children(n->type))
  111. for (p = n->first; p; p = p->next)
  112. if (consumes(p)) return 1;
  113. return 0;
  114. }
  115. }
  116. void check_recursion(struct s_node *g) {
  117. struct s_node *p;
  118. for (p = g->first->next; p; p = p->next) {
  119. assert(p->type == rule);
  120. consumes(p);
  121. }
  122. }
  123. /* Every path through a non-void rule must include exactly 1 expression. No
  124. * path through a void rule can include any expressions. */
  125. static void check_expression(struct s_node *g) {
  126. struct s_node *r;
  127. for (r = g->first->next; r; r = r->next) {
  128. int p;
  129. assert(r->type == rule);
  130. p = path_max(r, expr);
  131. if (strcmp(r->first->text, "void") == 0) {
  132. if (p > 0)
  133. fatal3("expression in void rule `", r->text, "'");
  134. } else {
  135. int q = path_min(r, expr);
  136. if (p < 1 || q < 1)
  137. fatal3("no expressions in non-void rule `", r->text, "'");
  138. if (p > 1 || q > 1)
  139. fatal3("multiple expressions in rule `", r->text, "'");
  140. }
  141. }
  142. }
  143. /* A name cannot be bound more than once in any scope; each seq represents a
  144. * single scope. This is O(n^2), but n is the number of bindings in a sequence,
  145. * which is rarely more than 2. */
  146. static void check_rebound_seq(struct s_node *s) {
  147. char **names = 0;
  148. int namea = 0, namep = 0;
  149. struct s_node *p;
  150. for (p = s->first; p; p = p->next)
  151. if (p->type == bind) {
  152. int i;
  153. for (i = 0; i < namep; ++i)
  154. if (strcmp(names[i], p->text) == 0)
  155. fatal3("name `", p->text, "' rebound");
  156. if (namep == namea) {
  157. int l = 2 * namea + 1;
  158. char **n = realloc(names, l * sizeof *n);
  159. if (!n) nomem();
  160. names = n;
  161. namea = l;
  162. }
  163. names[namep++] = p->text;
  164. }
  165. }
  166. static void check_rebound(struct s_node *n) {
  167. struct s_node *p;
  168. if (n->type == seq)
  169. check_rebound_seq(n);
  170. if (s_has_children(n->type))
  171. for (p = n->first; p; p = p->next)
  172. check_rebound(p);
  173. }
  174. void preen(struct s_node *g, char *name) {
  175. assert(g && !g->text);
  176. g->text = name;
  177. resolve(g, g, 0);
  178. check_redef(g);
  179. check_reached(g);
  180. check_recursion(g);
  181. check_expression(g);
  182. check_rebound(g);
  183. }
  184. /* end. */