| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the utils of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| #ifndef GENERATOR_H |
| #define GENERATOR_H |
| |
| #include <QTextStream> |
| #include <QStringList> |
| |
| #include "nfa.h" |
| |
| class LineStream |
| { |
| private: |
| struct SharedStream |
| { |
| int ref; |
| QTextStream *stream; |
| }; |
| |
| public: |
| LineStream(QTextStream *textStream) |
| { |
| shared = new SharedStream; |
| shared->ref = 1; |
| shared->stream = textStream; |
| } |
| LineStream(const LineStream &other) |
| { |
| shared = other.shared; |
| shared->ref++; |
| } |
| LineStream &operator=(const LineStream &other) |
| { |
| if (this == &other) |
| return *this; |
| LineStream copy(other); // keep refcount up |
| qSwap(*shared, *other.shared); |
| return *this; |
| } |
| ~LineStream() |
| { |
| if (!--shared->ref) { |
| (*shared->stream) << endl; |
| delete shared; |
| } |
| } |
| |
| template <typename T> |
| LineStream &operator<<(const T &value) |
| { (*shared->stream) << value; return *this; } |
| |
| SharedStream *shared; |
| }; |
| |
| class CodeBlock |
| { |
| public: |
| inline CodeBlock() { stream.setString(&output, QIODevice::WriteOnly); } |
| |
| inline void indent() { indentStr += QLatin1String(" "); } |
| inline void outdent() { indentStr.remove(0, 4); } |
| |
| template <typename T> |
| LineStream operator<<(const T &value) |
| { stream << indentStr; stream << value; return LineStream(&stream); } |
| |
| inline void addNewLine() { stream << endl; } |
| |
| inline QString toString() const { stream.flush(); return output; } |
| |
| private: |
| QString output; |
| mutable QTextStream stream; |
| QString indentStr; |
| }; |
| |
| class Function |
| { |
| public: |
| inline Function(const QString &returnType, const QString &name) |
| : rtype(returnType), fname(name), iline(false), cnst(false) {} |
| inline Function() : iline(false), cnst(false) {} |
| |
| inline void setName(const QString &name) { fname = name; } |
| inline QString name() const { return fname; } |
| |
| inline void setInline(bool i) { iline = i; } |
| inline bool isInline() const { return iline; } |
| |
| inline void setReturnType(const QString &type) { rtype = type; } |
| inline QString returnType() const { return rtype; } |
| |
| inline void addBody(const QString &_body) { body += _body; } |
| inline void addBody(const CodeBlock &block) { body += block.toString(); } |
| inline bool hasBody() const { return !body.isEmpty(); } |
| |
| inline void setConst(bool konst) { cnst = konst; } |
| inline bool isConst() const { return cnst; } |
| |
| void printDeclaration(CodeBlock &block, const QString &funcNamePrefix = QString()) const; |
| QString definition() const; |
| |
| private: |
| QString signature(const QString &funcNamePrefix = QString()) const; |
| |
| QString rtype; |
| QString fname; |
| QString body; |
| bool iline; |
| bool cnst; |
| }; |
| |
| class Class |
| { |
| public: |
| enum Access { PublicMember, ProtectedMember, PrivateMember }; |
| |
| inline Class(const QString &name) : cname(name) {} |
| |
| inline void setName(const QString &name) { cname = name; } |
| inline QString name() const { return cname; } |
| |
| inline void addMember(Access access, const QString &name) |
| { sections[access].variables.append(name); } |
| inline void addMember(Access access, const Function &func) |
| { sections[access].functions.append(func); } |
| |
| void addConstructor(Access access, const QString &body, const QString &args = QString()); |
| inline void addConstructor(Access access, const CodeBlock &body, const QString &args = QString()) |
| { addConstructor(access, body.toString(), args); } |
| |
| QString declaration() const; |
| QString definition() const; |
| |
| private: |
| QString cname; |
| struct Section |
| { |
| QVector<Function> functions; |
| QStringList variables; |
| QVector<Function> constructors; |
| |
| inline bool isEmpty() const |
| { return functions.isEmpty() && variables.isEmpty() && constructors.isEmpty(); } |
| |
| void printDeclaration(const Class *klass, CodeBlock &block) const; |
| QString definition(const Class *klass) const; |
| }; |
| |
| Section sections[3]; |
| }; |
| |
| class Generator |
| { |
| public: |
| Generator(const DFA &dfa, const Config &config); |
| |
| QString generate(); |
| |
| private: |
| void generateTransitions(CodeBlock &body, const TransitionMap &transitions); |
| bool isSingleReferencedFinalState(int i) const; |
| |
| DFA dfa; |
| Config cfg; |
| InputType minInput; |
| InputType maxInput; |
| QHash<int, int> backReferenceMap; |
| QString headerFileName; |
| public: |
| struct TransitionSequence |
| { |
| inline TransitionSequence() : first(-1), last(-1), transition(-1) {} |
| InputType first; |
| InputType last; |
| int transition; |
| QString testFunction; |
| }; |
| private: |
| QVector<TransitionSequence> charFunctionRanges; |
| }; |
| |
| #endif |