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 #ifndef GENERATOR_H 29 #define GENERATOR_H 30 31 #include <QTextStream> 32 #include <QStringList> 33 34 #include "nfa.h" 35 36 class LineStream 37 { 38 private: 39 struct SharedStream 40 { 41 int ref; 42 QTextStream *stream; 43 }; 44 45 public: LineStream(QTextStream * textStream)46 LineStream(QTextStream *textStream) 47 { 48 shared = new SharedStream; 49 shared->ref = 1; 50 shared->stream = textStream; 51 } LineStream(const LineStream & other)52 LineStream(const LineStream &other) 53 { 54 shared = other.shared; 55 shared->ref++; 56 } 57 LineStream &operator=(const LineStream &other) 58 { 59 if (this == &other) 60 return *this; 61 LineStream copy(other); // keep refcount up 62 qSwap(*shared, *other.shared); 63 return *this; 64 } ~LineStream()65 ~LineStream() 66 { 67 if (!--shared->ref) { 68 (*shared->stream) << endl; 69 delete shared; 70 } 71 } 72 73 template <typename T> 74 LineStream &operator<<(const T &value) 75 { (*shared->stream) << value; return *this; } 76 77 SharedStream *shared; 78 }; 79 80 class CodeBlock 81 { 82 public: CodeBlock()83 inline CodeBlock() { stream.setString(&output, QIODevice::WriteOnly); } 84 indent()85 inline void indent() { indentStr += QLatin1String(" "); } outdent()86 inline void outdent() { indentStr.remove(0, 4); } 87 88 template <typename T> 89 LineStream operator<<(const T &value) 90 { stream << indentStr; stream << value; return LineStream(&stream); } 91 addNewLine()92 inline void addNewLine() { stream << endl; } 93 toString()94 inline QString toString() const { stream.flush(); return output; } 95 96 private: 97 QString output; 98 mutable QTextStream stream; 99 QString indentStr; 100 }; 101 102 class Function 103 { 104 public: Function(const QString & returnType,const QString & name)105 inline Function(const QString &returnType, const QString &name) 106 : rtype(returnType), fname(name), iline(false), cnst(false) {} Function()107 inline Function() : iline(false), cnst(false) {} 108 setName(const QString & name)109 inline void setName(const QString &name) { fname = name; } name()110 inline QString name() const { return fname; } 111 setInline(bool i)112 inline void setInline(bool i) { iline = i; } isInline()113 inline bool isInline() const { return iline; } 114 setReturnType(const QString & type)115 inline void setReturnType(const QString &type) { rtype = type; } returnType()116 inline QString returnType() const { return rtype; } 117 addBody(const QString & _body)118 inline void addBody(const QString &_body) { body += _body; } addBody(const CodeBlock & block)119 inline void addBody(const CodeBlock &block) { body += block.toString(); } hasBody()120 inline bool hasBody() const { return !body.isEmpty(); } 121 setConst(bool konst)122 inline void setConst(bool konst) { cnst = konst; } isConst()123 inline bool isConst() const { return cnst; } 124 125 void printDeclaration(CodeBlock &block, const QString &funcNamePrefix = QString()) const; 126 QString definition() const; 127 128 private: 129 QString signature(const QString &funcNamePrefix = QString()) const; 130 131 QString rtype; 132 QString fname; 133 QString body; 134 bool iline; 135 bool cnst; 136 }; 137 138 class Class 139 { 140 public: 141 enum Access { PublicMember, ProtectedMember, PrivateMember }; 142 Class(const QString & name)143 inline Class(const QString &name) : cname(name) {} 144 setName(const QString & name)145 inline void setName(const QString &name) { cname = name; } name()146 inline QString name() const { return cname; } 147 addMember(Access access,const QString & name)148 inline void addMember(Access access, const QString &name) 149 { sections[access].variables.append(name); } addMember(Access access,const Function & func)150 inline void addMember(Access access, const Function &func) 151 { sections[access].functions.append(func); } 152 153 void addConstructor(Access access, const QString &body, const QString &args = QString()); 154 inline void addConstructor(Access access, const CodeBlock &body, const QString &args = QString()) 155 { addConstructor(access, body.toString(), args); } 156 157 QString declaration() const; 158 QString definition() const; 159 160 private: 161 QString cname; 162 struct Section 163 { 164 QVector<Function> functions; 165 QStringList variables; 166 QVector<Function> constructors; 167 isEmptySection168 inline bool isEmpty() const 169 { return functions.isEmpty() && variables.isEmpty() && constructors.isEmpty(); } 170 171 void printDeclaration(const Class *klass, CodeBlock &block) const; 172 QString definition(const Class *klass) const; 173 }; 174 175 Section sections[3]; 176 }; 177 178 class Generator 179 { 180 public: 181 Generator(const DFA &dfa, const Config &config); 182 183 QString generate(); 184 185 private: 186 void generateTransitions(CodeBlock &body, const TransitionMap &transitions); 187 bool isSingleReferencedFinalState(int i) const; 188 189 DFA dfa; 190 Config cfg; 191 InputType minInput; 192 InputType maxInput; 193 QHash<int, int> backReferenceMap; 194 QString headerFileName; 195 public: 196 struct TransitionSequence 197 { TransitionSequenceTransitionSequence198 inline TransitionSequence() : first(-1), last(-1), transition(-1) {} 199 InputType first; 200 InputType last; 201 int transition; 202 QString testFunction; 203 }; 204 private: 205 QVector<TransitionSequence> charFunctionRanges; 206 }; 207 208 #endif 209