87 state_count =
static_cast<
int>(aut
.states.size());
88 terminal_count =
static_cast<
int>(grammar
.terminals.size());
89 non_terminal_count =
static_cast<
int>(grammar
.non_terminals.size());
91#define ACTION(i, j) table [(i) * terminal_count + (j)]
92#define GOTO(i, j) pgoto [(i) * non_terminal_count + (j)]
94 int *table =
new int [state_count * terminal_count];
95 ::memset (table, 0, state_count * terminal_count *
sizeof (
int));
97 int *pgoto =
new int [state_count * non_terminal_count];
98 ::memset (pgoto, 0, state_count * non_terminal_count *
sizeof (
int));
101 int shift_reduce_conflict_count = 0;
102 int reduce_reduce_conflict_count = 0;
106 int q = aut
.id (state
);
108 for (Bundle::iterator a = state->bundle.begin (); a != state->bundle.end (); ++a)
110 int symbol = aut
.id (a.key ()
);
111 int r = aut
.id (a.value ()
);
113 Q_ASSERT (r < state_count);
117 Q_ASSERT(symbol >= terminal_count && symbol <
static_cast<
int>(grammar.names.size()));
118 GOTO (q, symbol - terminal_count) = r;
125 for (
ItemPointer item = state->closure.begin (); item != state->closure.end (); ++item)
127 if (item->dot != item->end_rhs ())
130 int r = aut
.id (item->rule
);
132 const NameSet lookaheads = aut.lookaheads.value (item);
134 if (item->rule == grammar
.goal)
137 for (
const Name &s : lookaheads)
139 int &u =
ACTION (q, aut.id (s));
147 qout() <<
"*** Warning. Found a reduce/reduce conflict in state " << q <<
" on token ``" << s <<
"'' between rule "
148 << r <<
" and " << -u << Qt::endl;
150 ++reduce_reduce_conflict_count;
155 qout() <<
"\tresolved using rule " << -u << Qt::endl;
160 if (item->rule->prec != grammar.names.end() && grammar.token_info.contains (s))
162 Grammar::TokenInfo info_r = grammar.token_info.value (item->rule->prec);
163 Grammar::TokenInfo info_s = grammar.token_info.value (s);
165 if (info_r.prec > info_s.prec)
167 else if (info_r.prec == info_s.prec)
169 switch (info_r.assoc) {
176 case Grammar::NonAssoc:
185 ++shift_reduce_conflict_count;
188 qout() <<
"*** Warning. Found a shift/reduce conflict in state " << q <<
" on token ``" << s <<
"'' with rule " << r << Qt::endl;
195 if (shift_reduce_conflict_count || reduce_reduce_conflict_count)
200 qerr() <<
"*** Conflicts: " << shift_reduce_conflict_count <<
" shift/reduce, " << reduce_reduce_conflict_count <<
" reduce/reduce" << Qt::endl;
201 if (warnings_are_errors)
203 qerr() <<
"qlalr: error: warning occurred, treating as error due to "
204 "--exit-on-warn." << Qt::endl;
210 qout() << Qt::endl <<
"*** Conflicts: " << shift_reduce_conflict_count <<
" shift/reduce, " << reduce_reduce_conflict_count <<
" reduce/reduce" << Qt::endl
214 QBitArray used_rules{
static_cast<
int>(grammar
.rules.size())};
219 for (
int j = 0; j < terminal_count; ++j)
224 used_rules.setBit (-u - 1);
228 auto rule = grammar
.rules.begin();
229 for (
int i = 0; i < used_rules.size(); ++i, ++rule)
231 if (! used_rules.testBit (i))
233 if (rule != grammar
.goal)
235 qerr() <<
"*** Warning: Rule ``" << *rule <<
"'' is useless!" << Qt::endl;
236 if (warnings_are_errors)
238 qerr() <<
"qlalr: error: warning occurred, treating as error due to "
239 "--exit-on-warn." << Qt::endl;
249 for (
int j = 0; j < terminal_count; ++j)
258 if (state->defaultReduce == rule)
264 defgoto.resize (non_terminal_count);
265 for (
int j = 0; j < non_terminal_count; ++j)
267 count.fill (0, state_count);
269 int &mx = defgoto [j];
271 for (
int i = 0; i < state_count; ++i)
280 if (count [r] > count [mx])
285 for (
int i = 0; i < state_count; ++i)
287 for (
int j = 0; j < non_terminal_count; ++j)
289 int &r =
GOTO (i, j);
291 if (r == defgoto [j])
296 compressed_action (table, state_count, terminal_count);
297 compressed_goto (pgoto, state_count, non_terminal_count);
308 if (! grammar.merged_output.isEmpty())
310 QFile f(grammar.merged_output);
311 if (! f.open (QFile::WriteOnly))
313 fprintf (stderr,
"*** cannot create %s\n", qPrintable(grammar.merged_output));
322 out << copyrightHeader()
323 << privateCopyrightHeader()
327 out <<
"// This file was generated by qlalr - DO NOT EDIT!\n";
329 out << startIncludeGuard(grammar.merged_output) << Qt::endl;
332 out <<
"#if defined(ERROR)" << Qt::endl
333 <<
"# undef ERROR" << Qt::endl
334 <<
"#endif" << Qt::endl << Qt::endl;
343 out << endIncludeGuard(grammar.merged_output) << Qt::endl;
349 QString declFileName = grammar.table_name.toLower () +
"_p.h"_L1;
350 QString bitsFileName = grammar.table_name.toLower () +
".cpp"_L1;
353 QFile f (declFileName);
354 if (! f.open (QFile::WriteOnly))
356 fprintf (stderr,
"*** cannot create %s: %s\n",
357 qPrintable(declFileName), qPrintable(f.errorString()));
362 QString prot = declFileName.toUpper ().replace (QLatin1Char (
'.'), QLatin1Char (
'_'));
367 out << copyrightHeader()
368 << privateCopyrightHeader()
372 out <<
"// This file was generated by qlalr - DO NOT EDIT!\n";
374 out <<
"#ifndef " << prot << Qt::endl
375 <<
"#define " << prot << Qt::endl
379 out <<
"#include <QtCore/qglobal.h>" << Qt::endl << Qt::endl;
380 out <<
"QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl;
384 out <<
"QT_END_NAMESPACE" << Qt::endl;
386 out <<
"#endif // " << prot << Qt::endl << Qt::endl;
390 QFile f (bitsFileName);
391 if (! f.open (QFile::WriteOnly))
393 fprintf (stderr,
"*** cannot create %s: %s\n",
394 qPrintable(bitsFileName), qPrintable(f.errorString()));
401 out << copyrightHeader();
403 out <<
"// This file was generated by qlalr - DO NOT EDIT!\n";
405 out <<
"#include \"" << declFileName <<
"\"" << Qt::endl << Qt::endl;
407 out <<
"QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl;
410 out <<
"QT_END_NAMESPACE" << Qt::endl;
414 if (! grammar.decl_file_name.isEmpty ())
416 QFile f (grammar.decl_file_name);
417 if (! f.open (QFile::WriteOnly))
419 fprintf (stderr,
"*** cannot create %s: %s\n",
420 qPrintable(grammar.decl_file_name), qPrintable(f.errorString()));
427 if (! grammar.impl_file_name.isEmpty ())
429 QFile f (grammar.impl_file_name);
430 if (! f.open (QFile::WriteOnly))
432 fprintf (stderr,
"*** cannot create %s: %s\n",
433 qPrintable(grammar.impl_file_name), qPrintable(f.errorString()));