150 state_count =
static_cast<
int>(aut
.states.size());
151 terminal_count =
static_cast<
int>(grammar
.terminals.size());
152 non_terminal_count =
static_cast<
int>(grammar
.non_terminals.size());
154#define ACTION(i, j) table [(i) * terminal_count + (j)]
155#define GOTO(i, j) pgoto [(i) * non_terminal_count + (j)]
157 int *table =
new int [state_count * terminal_count];
158 ::memset (table, 0, state_count * terminal_count *
sizeof (
int));
160 int *pgoto =
new int [state_count * non_terminal_count];
161 ::memset (pgoto, 0, state_count * non_terminal_count *
sizeof (
int));
164 int shift_reduce_conflict_count = 0;
165 int reduce_reduce_conflict_count = 0;
169 int q = aut
.id (state
);
171 for (Bundle::iterator a = state->bundle.begin (); a != state->bundle.end (); ++a)
173 int symbol = aut
.id (a.key ()
);
174 int r = aut
.id (a.value ()
);
176 Q_ASSERT (r < state_count);
180 Q_ASSERT(symbol >= terminal_count && symbol <
static_cast<
int>(grammar.names.size()));
181 GOTO (q, symbol - terminal_count) = r;
188 for (
ItemPointer item = state->closure.begin (); item != state->closure.end (); ++item)
190 if (item->dot != item->end_rhs ())
193 int r = aut
.id (item->rule
);
195 const NameSet lookaheads = aut.lookaheads.value (item);
197 if (item->rule == grammar
.goal)
200 for (
const Name &s : lookaheads)
202 int &u =
ACTION (q, aut.id (s));
210 qout() <<
"*** Warning. Found a reduce/reduce conflict in state " << q <<
" on token ``" << s <<
"'' between rule "
211 << r <<
" and " << -u << Qt::endl;
213 ++reduce_reduce_conflict_count;
218 qout() <<
"\tresolved using rule " << -u << Qt::endl;
223 if (item->rule->prec != grammar.names.end() && grammar.token_info.contains (s))
225 Grammar::TokenInfo info_r = grammar.token_info.value (item->rule->prec);
226 Grammar::TokenInfo info_s = grammar.token_info.value (s);
228 if (info_r.prec > info_s.prec)
230 else if (info_r.prec == info_s.prec)
232 switch (info_r.assoc) {
239 case Grammar::NonAssoc:
248 ++shift_reduce_conflict_count;
251 qout() <<
"*** Warning. Found a shift/reduce conflict in state " << q <<
" on token ``" << s <<
"'' with rule " << r << Qt::endl;
258 if (shift_reduce_conflict_count || reduce_reduce_conflict_count)
263 qerr() <<
"*** Conflicts: " << shift_reduce_conflict_count <<
" shift/reduce, " << reduce_reduce_conflict_count <<
" reduce/reduce" << Qt::endl;
264 if (warnings_are_errors)
266 qerr() <<
"qlalr: error: warning occurred, treating as error due to "
267 "--exit-on-warn." << Qt::endl;
273 qout() << Qt::endl <<
"*** Conflicts: " << shift_reduce_conflict_count <<
" shift/reduce, " << reduce_reduce_conflict_count <<
" reduce/reduce" << Qt::endl
277 QBitArray used_rules{
static_cast<
int>(grammar
.rules.size())};
282 for (
int j = 0; j < terminal_count; ++j)
287 used_rules.setBit (-u - 1);
291 auto rule = grammar
.rules.begin();
292 for (
int i = 0; i < used_rules.size(); ++i, ++rule)
294 if (! used_rules.testBit (i))
296 if (rule != grammar
.goal)
298 qerr() <<
"*** Warning: Rule ``" << *rule <<
"'' is useless!" << Qt::endl;
299 if (warnings_are_errors)
301 qerr() <<
"qlalr: error: warning occurred, treating as error due to "
302 "--exit-on-warn." << Qt::endl;
312 for (
int j = 0; j < terminal_count; ++j)
321 if (state->defaultReduce == rule)
327 defgoto.resize (non_terminal_count);
328 for (
int j = 0; j < non_terminal_count; ++j)
330 count.fill (0, state_count);
332 int &mx = defgoto [j];
334 for (
int i = 0; i < state_count; ++i)
343 if (count [r] > count [mx])
348 for (
int i = 0; i < state_count; ++i)
350 for (
int j = 0; j < non_terminal_count; ++j)
352 int &r =
GOTO (i, j);
354 if (r == defgoto [j])
359 compressed_action (table, state_count, terminal_count);
360 compressed_goto (pgoto, state_count, non_terminal_count);
371 if (! grammar.merged_output.isEmpty())
373 QFile f(grammar.merged_output);
374 if (! f.open (QFile::WriteOnly))
376 fprintf (stderr,
"*** cannot create %s\n", qPrintable(grammar.merged_output));
385 out << copyrightHeader()
386 << privateCopyrightHeader()
390 out <<
"// This file was generated by qlalr - DO NOT EDIT!\n";
392 out << startIncludeGuard(grammar.merged_output) << Qt::endl;
395 out <<
"#if defined(ERROR)" << Qt::endl
396 <<
"# undef ERROR" << Qt::endl
397 <<
"#endif" << Qt::endl << Qt::endl;
406 out << endIncludeGuard(grammar.merged_output) << Qt::endl;
412 QString declFileName = grammar.table_name.toLower () +
"_p.h"_L1;
413 QString bitsFileName = grammar.table_name.toLower () +
".cpp"_L1;
416 QFile f (declFileName);
417 if (! f.open (QFile::WriteOnly))
419 fprintf (stderr,
"*** cannot create %s: %s\n",
420 qPrintable(declFileName), qPrintable(f.errorString()));
428 out << copyrightHeader()
429 << privateCopyrightHeader()
433 out <<
"// This file was generated by qlalr - DO NOT EDIT!\n";
435 out << startIncludeGuard(declFileName) << Qt::endl;
438 out <<
"#include <QtCore/qglobal.h>" << Qt::endl << Qt::endl;
439 out <<
"QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl;
443 out <<
"QT_END_NAMESPACE" << Qt::endl;
445 out << endIncludeGuard(declFileName) << Qt::endl;
449 QFile f (bitsFileName);
450 if (! f.open (QFile::WriteOnly))
452 fprintf (stderr,
"*** cannot create %s: %s\n",
453 qPrintable(bitsFileName), qPrintable(f.errorString()));
460 out << copyrightHeader();
462 out <<
"// This file was generated by qlalr - DO NOT EDIT!\n";
464 out <<
"#include \"" << declFileName <<
"\"" << Qt::endl << Qt::endl;
466 out <<
"QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl;
469 out <<
"QT_END_NAMESPACE" << Qt::endl;
473 if (! grammar.decl_file_name.isEmpty ())
475 QFile f (grammar.decl_file_name);
476 if (! f.open (QFile::WriteOnly))
478 fprintf (stderr,
"*** cannot create %s: %s\n",
479 qPrintable(grammar.decl_file_name), qPrintable(f.errorString()));
486 if (! grammar.impl_file_name.isEmpty ())
488 QFile f (grammar.impl_file_name);
489 if (! f.open (QFile::WriteOnly))
491 fprintf (stderr,
"*** cannot create %s: %s\n",
492 qPrintable(grammar.impl_file_name), qPrintable(f.errorString()));