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 | |
45 | static 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 (status: 0); |
57 | } |
58 | |
59 | int 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(pos: 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 (input_file: 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 | |
147 | QString 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 (before: QLatin1String("$start_id" ), after: QString::number (std::distance (first: _M_grammar->names.begin (), last: _M_grammar->start))); |
154 | code = code.replace (before: QLatin1String("$start" ), after: *_M_grammar->start); |
155 | } |
156 | |
157 | code = code.replace (before: QLatin1String("$header" ), after: _M_grammar->table_name.toLower () + QLatin1String("_p.h" )); |
158 | |
159 | code = code.replace (before: QLatin1String("$table" ), after: _M_grammar->table_name); |
160 | code = code.replace (before: QLatin1String("$parser" ), after: _M_grammar->table_name); |
161 | |
162 | if (_M_current_rule != _M_grammar->rules.end ()) |
163 | { |
164 | code = code.replace (before: QLatin1String("$rule_number" ), after: QString::number (std::distance (first: _M_grammar->rules.begin (), last: _M_current_rule))); |
165 | code = code.replace (before: QLatin1String("$rule" ), after: *_M_current_rule->lhs); |
166 | } |
167 | |
168 | return code; |
169 | } |
170 | |