diff options
Diffstat (limited to 'util/lexgen/generator.h')
-rw-r--r-- | util/lexgen/generator.h | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/util/lexgen/generator.h b/util/lexgen/generator.h new file mode 100644 index 0000000..047378b --- /dev/null +++ b/util/lexgen/generator.h @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the utils of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $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 |