156 state_count =
static_cast<
int>(aut
.states.size());
157 terminal_count =
static_cast<
int>(grammar
.terminals.size());
158 non_terminal_count =
static_cast<
int>(grammar
.non_terminals.size());
160#define ACTION(i, j) table [(i) * terminal_count + (j)]
161#define GOTO(i, j) pgoto [(i) * non_terminal_count + (j)]
163 int *table =
new int [state_count * terminal_count];
164 ::memset (table, 0, state_count * terminal_count *
sizeof (
int));
166 int *pgoto =
new int [state_count * non_terminal_count];
167 ::memset (pgoto, 0, state_count * non_terminal_count *
sizeof (
int));
170 int shift_reduce_conflict_count = 0;
171 int reduce_reduce_conflict_count = 0;
175 int q = aut
.id (state
);
177 for (Bundle::iterator a = state->bundle.begin (); a != state->bundle.end (); ++a)
179 int symbol = aut
.id (a.key ()
);
180 int r = aut
.id (a.value ()
);
182 Q_ASSERT (r < state_count);
186 Q_ASSERT(symbol >= terminal_count && symbol <
static_cast<
int>(grammar.names.size()));
187 GOTO (q, symbol - terminal_count) = r;
194 for (
ItemPointer item = state->closure.begin (); item != state->closure.end (); ++item)
196 if (item->dot != item->end_rhs ())
199 int r = aut
.id (item->rule
);
201 const NameSet lookaheads = aut.lookaheads.value (item);
203 if (item->rule == grammar
.goal)
206 for (
const Name &s : lookaheads)
208 int &u =
ACTION (q, aut.id (s));
216 qout() <<
"*** Warning. Found a reduce/reduce conflict in state " << q <<
" on token ``" << s <<
"'' between rule "
217 << r <<
" and " << -u << Qt::endl;
219 ++reduce_reduce_conflict_count;
224 qout() <<
"\tresolved using rule " << -u << Qt::endl;
229 if (item->rule->prec != grammar.names.end() && grammar.token_info.contains (s))
231 Grammar::TokenInfo info_r = grammar.token_info.value (item->rule->prec);
232 Grammar::TokenInfo info_s = grammar.token_info.value (s);
234 if (info_r.prec > info_s.prec)
236 else if (info_r.prec == info_s.prec)
238 switch (info_r.assoc) {
245 case Grammar::NonAssoc:
254 ++shift_reduce_conflict_count;
257 qout() <<
"*** Warning. Found a shift/reduce conflict in state " << q <<
" on token ``" << s <<
"'' with rule " << r << Qt::endl;
264 if (shift_reduce_conflict_count || reduce_reduce_conflict_count)
269 qerr() <<
"*** Conflicts: " << shift_reduce_conflict_count <<
" shift/reduce, " << reduce_reduce_conflict_count <<
" reduce/reduce" << Qt::endl;
270 if (warnings_are_errors)
272 qerr() <<
"qlalr: error: warning occurred, treating as error due to "
273 "--exit-on-warn." << Qt::endl;
279 qout() << Qt::endl <<
"*** Conflicts: " << shift_reduce_conflict_count <<
" shift/reduce, " << reduce_reduce_conflict_count <<
" reduce/reduce" << Qt::endl
283 QBitArray used_rules{
static_cast<
int>(grammar
.rules.size())};
288 for (
int j = 0; j < terminal_count; ++j)
293 used_rules.setBit (-u - 1);
297 auto rule = grammar
.rules.begin();
298 for (
int i = 0; i < used_rules.size(); ++i, ++rule)
300 if (! used_rules.testBit (i))
302 if (rule != grammar
.goal)
304 qerr() <<
"*** Warning: Rule ``" << *rule <<
"'' is useless!" << Qt::endl;
305 if (warnings_are_errors)
307 qerr() <<
"qlalr: error: warning occurred, treating as error due to "
308 "--exit-on-warn." << Qt::endl;
318 for (
int j = 0; j < terminal_count; ++j)
327 if (state->defaultReduce == rule)
333 defgoto.resize (non_terminal_count);
334 for (
int j = 0; j < non_terminal_count; ++j)
336 count.fill (0, state_count);
338 int &mx = defgoto [j];
340 for (
int i = 0; i < state_count; ++i)
349 if (count [r] > count [mx])
354 for (
int i = 0; i < state_count; ++i)
356 for (
int j = 0; j < non_terminal_count; ++j)
358 int &r =
GOTO (i, j);
360 if (r == defgoto [j])
365 compressed_action (table, state_count, terminal_count);
366 compressed_goto (pgoto, state_count, non_terminal_count);
377 if (! grammar.merged_output.isEmpty())
379 QFile f(grammar.merged_output);
380 if (! f.open (QFile::WriteOnly))
382 fprintf (stderr,
"*** cannot create %s\n", qPrintable(grammar.merged_output));
391 out << copyrightHeader()
392 << privateCopyrightHeader()
396 out <<
"// This file was generated by qlalr - DO NOT EDIT!\n";
398 out << startIncludeGuard(grammar.merged_output) << Qt::endl;
400 out <<
"#if defined(ERROR)" << Qt::endl
401 <<
"# undef ERROR" << Qt::endl
402 <<
"#endif" << Qt::endl << Qt::endl;
410 out << endIncludeGuard(grammar.merged_output) << Qt::endl;
416 QString declFileName = grammar.table_name.toLower () +
"_p.h"_L1;
417 QString bitsFileName = grammar.table_name.toLower () +
".cpp"_L1;
420 QFile f (declFileName);
421 if (! f.open (QFile::WriteOnly))
423 fprintf (stderr,
"*** cannot create %s: %s\n",
424 qPrintable(declFileName), qPrintable(f.errorString()));
432 out << copyrightHeader()
433 << privateCopyrightHeader()
437 out <<
"// This file was generated by qlalr - DO NOT EDIT!\n";
439 out << startIncludeGuard(declFileName) << Qt::endl;
442 out <<
"#include <QtCore/qglobal.h>" << Qt::endl << Qt::endl;
443 out <<
"QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl;
447 out <<
"QT_END_NAMESPACE" << Qt::endl;
449 out << endIncludeGuard(declFileName) << Qt::endl;
453 QFile f (bitsFileName);
454 if (! f.open (QFile::WriteOnly))
456 fprintf (stderr,
"*** cannot create %s: %s\n",
457 qPrintable(bitsFileName), qPrintable(f.errorString()));
464 out << copyrightHeader();
466 out <<
"// This file was generated by qlalr - DO NOT EDIT!\n";
468 out <<
"#include \"" << declFileName <<
"\"" << Qt::endl << Qt::endl;
470 out <<
"QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl;
473 out <<
"QT_END_NAMESPACE" << Qt::endl;
477 if (! grammar.decl_file_name.isEmpty ())
479 QFile f (grammar.decl_file_name);
480 if (! f.open (QFile::WriteOnly))
482 fprintf (stderr,
"*** cannot create %s: %s\n",
483 qPrintable(grammar.decl_file_name), qPrintable(f.errorString()));
490 if (! grammar.impl_file_name.isEmpty ())
492 QFile f (grammar.impl_file_name);
493 if (! f.open (QFile::WriteOnly))
495 fprintf (stderr,
"*** cannot create %s: %s\n",
496 qPrintable(grammar.impl_file_name), qPrintable(f.errorString()));