| 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 (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(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 |  | 
| 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 (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 |  |