1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the utils of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "lalr.h"
30#include "dotgraph.h"
31#include "parsetable.h"
32#include "cppgenerator.h"
33#include "recognizer.h"
34
35#include <QtCore/qcoreapplication.h>
36#include <QtCore/qfile.h>
37#include <QtCore/qstringlist.h>
38#include <QtCore/qdebug.h>
39
40#include <cstdlib>
41
42#define QLALR_NO_DEBUG_TABLE
43#define QLALR_NO_DEBUG_DOT
44
45static void help_me ()
46{
47 qerr() << "Usage: qlalr [options] [input file name]" << Qt::endl
48 << Qt::endl
49 << " --help, -h\t\tdisplay this help and exit" << Qt::endl
50 << " --verbose, -v\t\tverbose output" << Qt::endl
51 << " --no-debug\t\tno debug information" << Qt::endl
52 << " --no-lines\t\tno #line directives" << Qt::endl
53 << " --dot\t\t\tgenerate a graph" << Qt::endl
54 << " --qt\t\tadd the Qt copyright header and Qt-specific types and macros" << Qt::endl
55 << Qt::endl;
56 exit (0);
57}
58
59int main (int argc, char *argv[])
60{
61 QCoreApplication app (argc, argv);
62
63 bool generate_dot = false;
64 bool generate_report = false;
65 bool no_lines = false;
66 bool debug_info = true;
67 bool qt_copyright = false;
68 QString file_name;
69
70 const QStringList args = app.arguments().mid(1);
71 for (const QString &arg : args) {
72 if (arg == QLatin1String ("-h") || arg == QLatin1String ("--help"))
73 help_me ();
74
75 else if (arg == QLatin1String ("-v") || arg == QLatin1String ("--verbose"))
76 generate_report = true;
77
78 else if (arg == QLatin1String ("--dot"))
79 generate_dot = true;
80
81 else if (arg == QLatin1String ("--no-lines"))
82 no_lines = true;
83
84 else if (arg == QLatin1String ("--no-debug"))
85 debug_info = false;
86
87 else if (arg == QLatin1String ("--qt"))
88 qt_copyright = true;
89
90 else if (file_name.isEmpty ())
91 file_name = arg;
92
93 else
94 qerr() << "*** Warning. Ignore argument `" << arg << "'" << Qt::endl;
95 }
96
97 if (file_name.isEmpty ())
98 {
99 help_me ();
100 exit (EXIT_SUCCESS);
101 }
102
103 Grammar grammar;
104 Recognizer p (&grammar, no_lines);
105
106 if (! p.parse (file_name))
107 exit (EXIT_FAILURE);
108
109 if (grammar.rules.empty())
110 {
111 qerr() << "*** Fatal. No rules!" << Qt::endl;
112 exit (EXIT_FAILURE);
113 }
114
115 else if (grammar.start == grammar.names.end ())
116 {
117 qerr() << "*** Fatal. No start symbol!" << Qt::endl;
118 exit (EXIT_FAILURE);
119 }
120
121 grammar.buildExtendedGrammar ();
122 grammar.buildRuleMap ();
123
124 Automaton aut (&grammar);
125 aut.build ();
126
127 CppGenerator gen (p, grammar, aut, generate_report);
128 gen.setDebugInfo (debug_info);
129 gen.setCopyright (qt_copyright);
130 gen ();
131
132 if (generate_dot)
133 {
134 DotGraph genDotFile (qout());
135 genDotFile (&aut);
136 }
137
138 else if (generate_report)
139 {
140 ParseTable genParseTable (qout());
141 genParseTable(&aut);
142 }
143
144 return EXIT_SUCCESS;
145}
146
147QString Recognizer::expand (const QString &text) const
148{
149 QString code = text;
150
151 if (_M_grammar->start != _M_grammar->names.end ())
152 {
153 code = code.replace (QLatin1String("$start_id"), QString::number (std::distance (_M_grammar->names.begin (), _M_grammar->start)));
154 code = code.replace (QLatin1String("$start"), *_M_grammar->start);
155 }
156
157 code = code.replace (QLatin1String("$header"), _M_grammar->table_name.toLower () + QLatin1String("_p.h"));
158
159 code = code.replace (QLatin1String("$table"), _M_grammar->table_name);
160 code = code.replace (QLatin1String("$parser"), _M_grammar->table_name);
161
162 if (_M_current_rule != _M_grammar->rules.end ())
163 {
164 code = code.replace (QLatin1String("$rule_number"), QString::number (std::distance (_M_grammar->rules.begin (), _M_current_rule)));
165 code = code.replace (QLatin1String("$rule"), *_M_current_rule->lhs);
166 }
167
168 return code;
169}
170