print_graph.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /* Output a graph of the generated parser, for Bison.
  2. Copyright (C) 2001-2007, 2009-2015, 2018-2019 Free Software
  3. 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 <http://www.gnu.org/licenses/>. */
  15. #include <config.h>
  16. #include "system.h"
  17. #include "LR0.h"
  18. #include "closure.h"
  19. #include "complain.h"
  20. #include "conflicts.h"
  21. #include "files.h"
  22. #include "getargs.h"
  23. #include "gram.h"
  24. #include "graphviz.h"
  25. #include "lalr.h"
  26. #include "print_graph.h"
  27. #include "reader.h"
  28. #include "state.h"
  29. #include "symtab.h"
  30. /*----------------------------.
  31. | Construct the node labels. |
  32. `----------------------------*/
  33. /* Print the lhs of a rule in such a manner that there is no vertical
  34. repetition, like in *.output files. */
  35. static void
  36. print_core (struct obstack *oout, state *s)
  37. {
  38. item_number const *sitems = s->items;
  39. sym_content *previous_lhs = NULL;
  40. size_t snritems = s->nitems;
  41. /* Output all the items of a state, not just its kernel. */
  42. if (report_flag & report_itemsets)
  43. {
  44. closure (sitems, snritems);
  45. sitems = itemset;
  46. snritems = nitemset;
  47. }
  48. obstack_printf (oout, _("State %d"), s->number);
  49. obstack_sgrow (oout, "\\n\\l");
  50. for (size_t i = 0; i < snritems; ++i)
  51. {
  52. item_number const *sp1 = ritem + sitems[i];
  53. item_number const *sp = sp1;
  54. while (0 <= *sp)
  55. sp++;
  56. rule *r = &rules[item_number_as_rule_number (*sp)];
  57. obstack_printf (oout, "%3d ", r->number);
  58. if (previous_lhs && UNIQSTR_EQ (previous_lhs->symbol->tag,
  59. r->lhs->symbol->tag))
  60. obstack_printf (oout, "%*s| ",
  61. (int) strlen (previous_lhs->symbol->tag), "");
  62. else
  63. obstack_printf (oout, "%s: ", escape (r->lhs->symbol->tag));
  64. previous_lhs = r->lhs;
  65. for (sp = r->rhs; sp < sp1; sp++)
  66. obstack_printf (oout, "%s ", escape (symbols[*sp]->tag));
  67. obstack_1grow (oout, '.');
  68. if (0 <= *r->rhs)
  69. for (/* Nothing */; *sp >= 0; ++sp)
  70. obstack_printf (oout, " %s", escape (symbols[*sp]->tag));
  71. else
  72. obstack_printf (oout, " %%empty");
  73. /* Experimental feature: display the lookahead tokens. */
  74. if (report_flag & report_lookahead_tokens
  75. && item_number_is_rule_number (*sp1))
  76. {
  77. /* Find the reduction we are handling. */
  78. reductions *reds = s->reductions;
  79. int redno = state_reduction_find (s, r);
  80. /* Print them if there are. */
  81. if (reds->lookahead_tokens && redno != -1)
  82. {
  83. bitset_iterator biter;
  84. int k;
  85. char const *sep = "";
  86. obstack_sgrow (oout, " [");
  87. BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0)
  88. {
  89. obstack_sgrow (oout, sep);
  90. obstack_sgrow (oout, escape (symbols[k]->tag));
  91. sep = ", ";
  92. }
  93. obstack_1grow (oout, ']');
  94. }
  95. }
  96. obstack_sgrow (oout, "\\l");
  97. }
  98. }
  99. /*---------------------------------------------------------------.
  100. | Output in graph_obstack edges specifications in incidence with |
  101. | current node. |
  102. `---------------------------------------------------------------*/
  103. static void
  104. print_actions (state const *s, FILE *fgraph)
  105. {
  106. transitions const *trans = s->transitions;
  107. if (!trans->num && !s->reductions)
  108. return;
  109. for (int i = 0; i < trans->num; i++)
  110. if (!TRANSITION_IS_DISABLED (trans, i))
  111. {
  112. const state *s1 = trans->states[i];
  113. const symbol_number sym = s1->accessing_symbol;
  114. /* Shifts are solid, gotos are dashed, and error is dotted. */
  115. char const *style =
  116. (TRANSITION_IS_ERROR (trans, i) ? "dotted"
  117. : TRANSITION_IS_SHIFT (trans, i) ? "solid"
  118. : "dashed");
  119. if (TRANSITION_IS_ERROR (trans, i)
  120. && STRNEQ (symbols[sym]->tag, "error"))
  121. abort ();
  122. output_edge (s->number, s1->number,
  123. TRANSITION_IS_ERROR (trans, i) ? NULL : symbols[sym]->tag,
  124. style, fgraph);
  125. }
  126. /* Display reductions. */
  127. output_red (s, s->reductions, fgraph);
  128. }
  129. /*-------------------------------------------------------------.
  130. | Output in FGRAPH the current node specifications and exiting |
  131. | edges. |
  132. `-------------------------------------------------------------*/
  133. static void
  134. print_state (state *s, FILE *fgraph)
  135. {
  136. struct obstack node_obstack;
  137. /* A node's label contains its items. */
  138. obstack_init (&node_obstack);
  139. print_core (&node_obstack, s);
  140. output_node (s->number, obstack_finish0 (&node_obstack), fgraph);
  141. obstack_free (&node_obstack, 0);
  142. /* Output the edges. */
  143. print_actions (s, fgraph);
  144. }
  145. void
  146. print_graph (void)
  147. {
  148. FILE *fgraph = xfopen (spec_graph_file, "w");
  149. start_graph (fgraph);
  150. /* Output nodes and edges. */
  151. new_closure (nritems);
  152. for (int i = 0; i < nstates; i++)
  153. print_state (states[i], fgraph);
  154. free_closure ();
  155. finish_graph (fgraph);
  156. xfclose (fgraph);
  157. }