1 | /* Top level entry point of Bison. |
2 | |
3 | Copyright (C) 1984, 1986, 1989, 1992, 1995, 2000-2002, 2004-2015, |
4 | 2018-2019 Free 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 <http://www.gnu.org/licenses/>. */ |
20 | |
21 | #include <config.h> |
22 | #include "system.h" |
23 | |
24 | #include <bitset.h> |
25 | #include <bitset/stats.h> |
26 | #include <closeout.h> |
27 | #include <configmake.h> |
28 | #include <progname.h> |
29 | #include <quote.h> |
30 | #include <quotearg.h> |
31 | #include <relocatable.h> /* relocate2 */ |
32 | #include <timevar.h> |
33 | |
34 | #include "complain.h" |
35 | #include "conflicts.h" |
36 | #include "derives.h" |
37 | #include "files.h" |
38 | #include "fixits.h" |
39 | #include "getargs.h" |
40 | #include "gram.h" |
41 | #include "ielr.h" |
42 | #include "lalr.h" |
43 | #include "lr0.h" |
44 | #include "muscle-tab.h" |
45 | #include "nullable.h" |
46 | #include "output.h" |
47 | #include "print-graph.h" |
48 | #include "print-xml.h" |
49 | #include "print.h" |
50 | #include "reader.h" |
51 | #include "reduce.h" |
52 | #include "scan-code.h" |
53 | #include "scan-gram.h" |
54 | #include "scan-skel.h" |
55 | #include "symtab.h" |
56 | #include "tables.h" |
57 | #include "uniqstr.h" |
58 | |
59 | |
60 | int |
61 | main (int argc, char *argv[]) |
62 | { |
63 | #define DEPENDS_ON_LIBINTL 1 |
64 | set_program_name (argv[0]); |
65 | setlocale (LC_ALL, "" ); |
66 | { |
67 | char *cp = NULL; |
68 | char const *localedir = relocate2 (LOCALEDIR, &cp); |
69 | bindtextdomain ("bison" , localedir); |
70 | bindtextdomain ("bison-gnulib" , localedir); |
71 | bindtextdomain ("bison-runtime" , localedir); |
72 | free (cp); |
73 | } |
74 | textdomain ("bison" ); |
75 | |
76 | { |
77 | char const *cp = getenv ("LC_CTYPE" ); |
78 | if (cp && STREQ (cp, "C" )) |
79 | set_custom_quoting ("e_quoting_options, "'" , "'" ); |
80 | else |
81 | set_quoting_style ("e_quoting_options, locale_quoting_style); |
82 | } |
83 | |
84 | atexit (close_stdout); |
85 | |
86 | uniqstrs_new (); |
87 | muscle_init (); |
88 | complain_init (); |
89 | |
90 | getargs (argc, argv); |
91 | |
92 | timevar_enabled = trace_flag & trace_time; |
93 | timevar_init (); |
94 | timevar_start (tv_total); |
95 | |
96 | if (trace_flag & trace_bitsets) |
97 | bitset_stats_enable (); |
98 | |
99 | /* Read the input. Copy some parts of it to FGUARD, FACTION, FTABLE |
100 | and FATTRS. In file reader.c. The other parts are recorded in |
101 | the grammar; see gram.h. */ |
102 | |
103 | timevar_push (tv_reader); |
104 | reader (); |
105 | timevar_pop (tv_reader); |
106 | |
107 | if (complaint_status == status_complaint) |
108 | goto finish; |
109 | |
110 | /* Find useless nonterminals and productions and reduce the grammar. */ |
111 | timevar_push (tv_reduce); |
112 | reduce_grammar (); |
113 | timevar_pop (tv_reduce); |
114 | |
115 | /* Record other info about the grammar. In files derives and |
116 | nullable. */ |
117 | timevar_push (tv_sets); |
118 | derives_compute (); |
119 | nullable_compute (); |
120 | timevar_pop (tv_sets); |
121 | |
122 | /* Compute LR(0) parser states. See state.h for more info. */ |
123 | timevar_push (tv_lr0); |
124 | generate_states (); |
125 | timevar_pop (tv_lr0); |
126 | |
127 | /* Add lookahead sets to parser states. Except when LALR(1) is |
128 | requested, split states to eliminate LR(1)-relative |
129 | inadequacies. */ |
130 | ielr (); |
131 | |
132 | /* Find and record any conflicts: places where one token of |
133 | lookahead is not enough to disambiguate the parsing. In file |
134 | conflicts. Also resolve s/r conflicts based on precedence |
135 | declarations. */ |
136 | timevar_push (tv_conflicts); |
137 | conflicts_solve (); |
138 | if (!muscle_percent_define_flag_if ("lr.keep-unreachable-state" )) |
139 | { |
140 | state_number *old_to_new = xnmalloc (nstates, sizeof *old_to_new); |
141 | state_number nstates_old = nstates; |
142 | state_remove_unreachable_states (old_to_new); |
143 | lalr_update_state_numbers (old_to_new, nstates_old); |
144 | conflicts_update_state_numbers (old_to_new, nstates_old); |
145 | free (old_to_new); |
146 | } |
147 | conflicts_print (); |
148 | timevar_pop (tv_conflicts); |
149 | |
150 | /* Compute the parser tables. */ |
151 | timevar_push (tv_actions); |
152 | tables_generate (); |
153 | timevar_pop (tv_actions); |
154 | |
155 | grammar_rules_useless_report (_("rule useless in parser due to conflicts" )); |
156 | |
157 | print_precedence_warnings (); |
158 | |
159 | /* Whether to generate output files. */ |
160 | bool generate = !(feature_flag & feature_syntax_only); |
161 | |
162 | if (generate) |
163 | { |
164 | /* Output file names. */ |
165 | compute_output_file_names (); |
166 | |
167 | /* Output the detailed report on the grammar. */ |
168 | if (report_flag) |
169 | { |
170 | timevar_push (tv_report); |
171 | print_results (); |
172 | timevar_pop (tv_report); |
173 | } |
174 | |
175 | /* Output the graph. */ |
176 | if (graph_flag) |
177 | { |
178 | timevar_push (tv_graph); |
179 | print_graph (); |
180 | timevar_pop (tv_graph); |
181 | } |
182 | |
183 | /* Output xml. */ |
184 | if (xml_flag) |
185 | { |
186 | timevar_push (tv_xml); |
187 | print_xml (); |
188 | timevar_pop (tv_xml); |
189 | } |
190 | } |
191 | |
192 | /* Stop if there were errors, to avoid trashing previous output |
193 | files. */ |
194 | if (complaint_status == status_complaint) |
195 | goto finish; |
196 | |
197 | /* Lookahead tokens are no longer needed. */ |
198 | timevar_push (tv_free); |
199 | lalr_free (); |
200 | timevar_pop (tv_free); |
201 | |
202 | /* Output the tables and the parser to ftable. In file output. */ |
203 | if (generate) |
204 | { |
205 | timevar_push (tv_parser); |
206 | output (); |
207 | timevar_pop (tv_parser); |
208 | } |
209 | |
210 | timevar_push (tv_free); |
211 | nullable_free (); |
212 | derives_free (); |
213 | tables_free (); |
214 | states_free (); |
215 | reduce_free (); |
216 | conflicts_free (); |
217 | grammar_free (); |
218 | output_file_names_free (); |
219 | |
220 | /* The scanner memory cannot be released right after parsing, as it |
221 | contains things such as user actions, prologue, epilogue etc. */ |
222 | gram_scanner_free (); |
223 | muscle_free (); |
224 | code_scanner_free (); |
225 | skel_scanner_free (); |
226 | quotearg_free (); |
227 | timevar_pop (tv_free); |
228 | |
229 | if (trace_flag & trace_bitsets) |
230 | bitset_stats_dump (stderr); |
231 | |
232 | finish: |
233 | |
234 | /* Stop timing and print the times. */ |
235 | timevar_stop (tv_total); |
236 | timevar_print (stderr); |
237 | |
238 | /* Fix input file now, even if there are errors: that's less |
239 | warnings in the following runs. */ |
240 | if (!fixits_empty ()) |
241 | { |
242 | if (update_flag) |
243 | fixits_run (); |
244 | else |
245 | complain (NULL, Wother, |
246 | _("fix-its can be applied. Rerun with option '--update'." )); |
247 | fixits_free (); |
248 | } |
249 | uniqstrs_free (); |
250 | |
251 | complain_free (); |
252 | |
253 | return complaint_status ? EXIT_FAILURE : EXIT_SUCCESS; |
254 | } |
255 | |