94 state_count =
static_cast<
int>(aut
.states.size());
95 terminal_count =
static_cast<
int>(grammar
.terminals.size());
96 non_terminal_count =
static_cast<
int>(grammar
.non_terminals.size());
98#define ACTION(i, j) table [(i) * terminal_count + (j)]
99#define GOTO(i, j) pgoto [(i) * non_terminal_count + (j)]
101 int *table =
new int [state_count * terminal_count];
102 ::memset (table, 0, state_count * terminal_count *
sizeof (
int));
104 int *pgoto =
new int [state_count * non_terminal_count];
105 ::memset (pgoto, 0, state_count * non_terminal_count *
sizeof (
int));
108 int shift_reduce_conflict_count = 0;
109 int reduce_reduce_conflict_count = 0;
113 int q = aut
.id (state
);
115 for (Bundle::iterator a = state->bundle.begin (); a != state->bundle.end (); ++a)
117 int symbol = aut
.id (a.key ()
);
118 int r = aut
.id (a.value ()
);
120 Q_ASSERT (r < state_count);
124 Q_ASSERT(symbol >= terminal_count && symbol <
static_cast<
int>(grammar.names.size()));
125 GOTO (q, symbol - terminal_count) = r;
132 for (
ItemPointer item = state->closure.begin (); item != state->closure.end (); ++item)
134 if (item->dot != item->end_rhs ())
137 int r = aut
.id (item->rule
);
139 const NameSet lookaheads = aut.lookaheads.value (item);
141 if (item->rule == grammar
.goal)
144 for (
const Name &s : lookaheads)
146 int &u =
ACTION (q, aut.id (s));
154 qout() <<
"*** Warning. Found a reduce/reduce conflict in state " << q <<
" on token ``" << s <<
"'' between rule "
155 << r <<
" and " << -u << Qt::endl;
157 ++reduce_reduce_conflict_count;
162 qout() <<
"\tresolved using rule " << -u << Qt::endl;
167 if (item->rule->prec != grammar.names.end() && grammar.token_info.contains (s))
169 Grammar::TokenInfo info_r = grammar.token_info.value (item->rule->prec);
170 Grammar::TokenInfo info_s = grammar.token_info.value (s);
172 if (info_r.prec > info_s.prec)
174 else if (info_r.prec == info_s.prec)
176 switch (info_r.assoc) {
183 case Grammar::NonAssoc:
192 ++shift_reduce_conflict_count;
195 qout() <<
"*** Warning. Found a shift/reduce conflict in state " << q <<
" on token ``" << s <<
"'' with rule " << r << Qt::endl;
202 if (shift_reduce_conflict_count || reduce_reduce_conflict_count)
207 qerr() <<
"*** Conflicts: " << shift_reduce_conflict_count <<
" shift/reduce, " << reduce_reduce_conflict_count <<
" reduce/reduce" << Qt::endl;
208 if (warnings_are_errors)
210 qerr() <<
"qlalr: error: warning occurred, treating as error due to "
211 "--exit-on-warn." << Qt::endl;
217 qout() << Qt::endl <<
"*** Conflicts: " << shift_reduce_conflict_count <<
" shift/reduce, " << reduce_reduce_conflict_count <<
" reduce/reduce" << Qt::endl
221 QBitArray used_rules{
static_cast<
int>(grammar
.rules.size())};
226 for (
int j = 0; j < terminal_count; ++j)
231 used_rules.setBit (-u - 1);
235 auto rule = grammar
.rules.begin();
236 for (
int i = 0; i < used_rules.size(); ++i, ++rule)
238 if (! used_rules.testBit (i))
240 if (rule != grammar
.goal)
242 qerr() <<
"*** Warning: Rule ``" << *rule <<
"'' is useless!" << Qt::endl;
243 if (warnings_are_errors)
245 qerr() <<
"qlalr: error: warning occurred, treating as error due to "
246 "--exit-on-warn." << Qt::endl;
256 for (
int j = 0; j < terminal_count; ++j)
265 if (state->defaultReduce == rule)
271 defgoto.resize (non_terminal_count);
272 for (
int j = 0; j < non_terminal_count; ++j)
274 count.fill (0, state_count);
276 int &mx = defgoto [j];
278 for (
int i = 0; i < state_count; ++i)
287 if (count [r] > count [mx])
292 for (
int i = 0; i < state_count; ++i)
294 for (
int j = 0; j < non_terminal_count; ++j)
296 int &r =
GOTO (i, j);
298 if (r == defgoto [j])
303 compressed_action (table, state_count, terminal_count);
304 compressed_goto (pgoto, state_count, non_terminal_count);
315 if (! grammar.merged_output.isEmpty())
317 QFile f(grammar.merged_output);
318 if (! f.open (QFile::WriteOnly))
320 fprintf (stderr,
"*** cannot create %s\n", qPrintable(grammar.merged_output));
329 out << copyrightHeader()
330 << privateCopyrightHeader()
334 out <<
"// This file was generated by qlalr - DO NOT EDIT!\n";
336 out << startIncludeGuard(grammar.merged_output) << Qt::endl;
339 out <<
"#if defined(ERROR)" << Qt::endl
340 <<
"# undef ERROR" << Qt::endl
341 <<
"#endif" << Qt::endl << Qt::endl;
350 out << endIncludeGuard(grammar.merged_output) << Qt::endl;
356 QString declFileName = grammar.table_name.toLower () +
"_p.h"_L1;
357 QString bitsFileName = grammar.table_name.toLower () +
".cpp"_L1;
360 QFile f (declFileName);
361 if (! f.open (QFile::WriteOnly))
363 fprintf (stderr,
"*** cannot create %s: %s\n",
364 qPrintable(declFileName), qPrintable(f.errorString()));
372 out << copyrightHeader()
373 << privateCopyrightHeader()
377 out <<
"// This file was generated by qlalr - DO NOT EDIT!\n";
379 out << startIncludeGuard(declFileName) << Qt::endl;
382 out <<
"#include <QtCore/qglobal.h>" << Qt::endl << Qt::endl;
383 out <<
"QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl;
387 out <<
"QT_END_NAMESPACE" << Qt::endl;
389 out << endIncludeGuard(declFileName) << Qt::endl;
393 QFile f (bitsFileName);
394 if (! f.open (QFile::WriteOnly))
396 fprintf (stderr,
"*** cannot create %s: %s\n",
397 qPrintable(bitsFileName), qPrintable(f.errorString()));
404 out << copyrightHeader();
406 out <<
"// This file was generated by qlalr - DO NOT EDIT!\n";
408 out <<
"#include \"" << declFileName <<
"\"" << Qt::endl << Qt::endl;
410 out <<
"QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl;
413 out <<
"QT_END_NAMESPACE" << Qt::endl;
417 if (! grammar.decl_file_name.isEmpty ())
419 QFile f (grammar.decl_file_name);
420 if (! f.open (QFile::WriteOnly))
422 fprintf (stderr,
"*** cannot create %s: %s\n",
423 qPrintable(grammar.decl_file_name), qPrintable(f.errorString()));
430 if (! grammar.impl_file_name.isEmpty ())
432 QFile f (grammar.impl_file_name);
433 if (! f.open (QFile::WriteOnly))
435 fprintf (stderr,
"*** cannot create %s: %s\n",
436 qPrintable(grammar.impl_file_name), qPrintable(f.errorString()));