48int Recognizer::nextToken()
59 int token = ch.unicode ();
65 while (!ch.isNull () && ch != u'"')
79 qerr() << _M_input_file <<
":" << _M_line <<
": Warning. Expected `\"'" << Qt::endl;
81 _M_current_value = text;
82 return (token = STRING_LITERAL);
85 else if (ch.isLetterOrNumber () || ch == u'_')
88 do { text += ch; inp (); }
89 while (ch.isLetterOrNumber () || ch == u'_' || ch == u'.');
90 _M_current_value = text;
94 else if (token ==
'%')
99 while (ch.isSpace ());
101 do { text += ch; inp (); }
102 while (ch.isLetterOrNumber () || ch == u'_' || ch == u'-');
104 if (text ==
"token_prefix"_L1)
105 return (token = TOKEN_PREFIX);
106 else if (text ==
"merged_output"_L1)
107 return (token = MERGED_OUTPUT);
108 else if (text ==
"token"_L1)
109 return (token = TOKEN);
110 else if (text ==
"start"_L1)
111 return (token = START);
112 else if (text ==
"parser"_L1)
113 return (token = PARSER);
114 else if (text ==
"decl"_L1)
115 return (token = DECL_FILE);
116 else if (text ==
"impl"_L1)
117 return (token = IMPL_FILE);
118 else if (text ==
"expect"_L1)
119 return (token = EXPECT);
120 else if (text ==
"expect-rr"_L1)
121 return (token = EXPECT_RR);
122 else if (text ==
"left"_L1)
123 return (token = LEFT);
124 else if (text ==
"right"_L1)
125 return (token = RIGHT);
126 else if (text ==
"nonassoc"_L1)
127 return (token = NONASSOC);
128 else if (text ==
"prec"_L1)
129 return (token = PREC);
132 qerr() << _M_input_file <<
":" << _M_line <<
": Unknown keyword `" << text <<
"'" << Qt::endl;
134 return (token = ERROR);
140 if (token ==
'-' && ch == u'-')
143 while (!ch.isNull () && ch != u'\n');
147 else if (token ==
':' && ch == u':')
151 return (token = ERROR);
153 return (token = COLON);
156 else if (token ==
'/' && ch == u':')
158 _M_action_line = _M_line;
162 text +=
"\n#line "_L1 + QString::number(_M_action_line) +
163 " \""_L1 + QDir::fromNativeSeparators(_M_input_file) +
"\"\n"_L1;
168 while (! ch.isNull ())
170 token = ch.unicode ();
173 if (token ==
':' && ch == u'/')
176 text += QLatin1Char (token);
180 return (token = ERROR);
184 if (ch.isNull () || ch.isSpace ())
186 _M_current_value = text;
187 return (token = DECL);
194 else if (token ==
'/' && ch == u'.')
196 _M_action_line = _M_line;
200 text +=
"\n#line "_L1 + QString::number(_M_action_line) +
201 " \""_L1 + QDir::fromNativeSeparators(_M_input_file) +
"\"\n"_L1;
207 while (! ch.isNull ())
209 token = ch.unicode ();
212 if (token ==
'.' && ch == u'/')
215 text += QLatin1Char (token);
219 return (token = ERROR);
223 if (ch.isNull () || ch.isSpace ())
225 _M_current_value = text;
226 return (token = IMPL);
235 return (token = COLON);
238 return (token = SEMICOLON);
250bool Recognizer::parse (
const QString &input_file)
252 _M_input_file = input_file;
254 QFile file(_M_input_file);
255 if (! file.open(QFile::ReadOnly))
257 qerr() <<
"qlalr: no input file\n";
265 QStringList copyrightLines;
269 while (!stream.atEnd() && !done) {
270 QString line = stream.readLine();
271 auto trimmed = QStringView(line).trimmed();
272 if (trimmed.startsWith(
"--"_L1)) {
273 copyrightLines.append(line);
274 accumulated += line +
'\n'_L1;
275 }
else if (trimmed.isEmpty() && !copyrightLines.isEmpty()) {
276 accumulated += line +
'\n'_L1;
278 accumulated += line +
'\n'_L1;
283 _M_contents = done ? accumulated + stream.readAll() : accumulated;
284 _M_firstChar = _M_contents.constBegin();
285 _M_lastChar = _M_contents.constEnd();
286 _M_currentChar = _M_firstChar;
289 if (!copyrightLines.isEmpty()) {
292 for (
const QString &line : copyrightLines) {
293 QString cppLine = line;
294 int idx = cppLine.indexOf(
"--"_L1);
296 cppLine.replace(idx, 2,
"//"_L1);
300 _M_grammar->inputCopyright = header;
309 _M_current_rule = _M_grammar
->rules.end ();
314 state_stack[++tos] = 0;
318 if (yytoken == -1 && - TERMINAL_COUNT != action_index [state_stack [tos]])
319 yytoken = nextToken();
321 int act = t_action (state_stack [tos], yytoken);
323 if (act == ACCEPT_STATE)
328 if (++tos == stack_size)
331 sym_stack [tos] = _M_current_value;
332 state_stack [tos] = act;
341 act = state_stack [tos++];
352 _M_grammar->table_name = sym(2);
356 _M_grammar->merged_output = sym(2);
360 _M_grammar->decl_file_name = sym(2);
364 _M_grammar->impl_file_name = sym(2);
368 _M_grammar->expected_shift_reduce = sym(2).toInt();
372 _M_grammar->expected_reduce_reduce = sym(2).toInt();
376 _M_grammar->token_prefix = sym(2);
381 _M_grammar->spells.insert (name, sym(2));
406 _M_grammar->token_info.insert (name, info);
410 _M_decls += expand (sym(1));
414 _M_impls += expand (sym(1));
419 _M_current_rule->lhs = _M_grammar
->intern (sym(1));
424 qerr() << _M_input_file <<
":" << _M_line <<
": Invalid non terminal `" << *_M_current_rule->lhs <<
"'" << Qt::endl;
432 Name lhs = _M_current_rule->lhs;
434 _M_current_rule->lhs = lhs;
439 qerr() << _M_input_file <<
":" << _M_line <<
": Invalid non terminal `" << *_M_current_rule->lhs <<
"'" << Qt::endl;
447 _M_current_rule->prec = _M_grammar->names.end ();
449 for (NameList::iterator it = _M_current_rule->rhs.begin (); it != _M_current_rule->rhs.end (); ++it)
454 _M_current_rule->prec = *it;
462 qerr() << _M_input_file <<
":" << _M_line <<
": `" << *tok <<
" is not a terminal symbol" << Qt::endl;
463 _M_current_rule->prec = _M_grammar->names.end ();
466 _M_current_rule->prec = tok;
475 _M_current_rule->rhs.push_back (name);
484 state_stack [tos] = nt_action (act, lhs [r] - TERMINAL_COUNT);
493 qerr() << _M_input_file <<
":" << _M_line <<
": Syntax error" << Qt::endl;