util/lexgen/generator.h
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the utils of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 #ifndef GENERATOR_H
       
    42 #define GENERATOR_H
       
    43 
       
    44 #include <QTextStream>
       
    45 #include <QStringList>
       
    46 
       
    47 #include "nfa.h"
       
    48 
       
    49 class LineStream
       
    50 {
       
    51 private:
       
    52     struct SharedStream
       
    53     {
       
    54         int ref;
       
    55         QTextStream *stream;
       
    56     };
       
    57 
       
    58 public:
       
    59     LineStream(QTextStream *textStream)
       
    60     {
       
    61         shared = new SharedStream;
       
    62         shared->ref = 1;
       
    63         shared->stream = textStream;
       
    64     }
       
    65     LineStream(const LineStream &other)
       
    66     {
       
    67         shared = other.shared;
       
    68         shared->ref++;
       
    69     }
       
    70     LineStream &operator=(const LineStream &other)
       
    71     {
       
    72         if (this == &other)
       
    73             return *this;
       
    74         LineStream copy(other); // keep refcount up
       
    75         qSwap(*shared, *other.shared);
       
    76         return *this;
       
    77     }
       
    78     ~LineStream()
       
    79     {
       
    80         if (!--shared->ref) {
       
    81             (*shared->stream) << endl;
       
    82             delete shared;
       
    83         }
       
    84     }
       
    85     
       
    86     template <typename T>
       
    87     LineStream &operator<<(const T &value)
       
    88     { (*shared->stream) << value; return *this; }
       
    89     
       
    90     SharedStream *shared;
       
    91 };
       
    92 
       
    93 class CodeBlock
       
    94 {
       
    95 public:
       
    96     inline CodeBlock() { stream.setString(&output, QIODevice::WriteOnly); }
       
    97 
       
    98     inline void indent() { indentStr += QLatin1String("    "); }
       
    99     inline void outdent() { indentStr.remove(0, 4); }
       
   100 
       
   101     template <typename T>
       
   102     LineStream operator<<(const T &value)
       
   103     { stream << indentStr; stream << value; return LineStream(&stream); }
       
   104     
       
   105     inline void addNewLine() { stream << endl; }
       
   106     
       
   107     inline QString toString() const { stream.flush(); return output; }
       
   108     
       
   109 private:
       
   110     QString output;
       
   111     mutable QTextStream stream;
       
   112     QString indentStr;
       
   113 };
       
   114 
       
   115 class Function
       
   116 {
       
   117 public:
       
   118     inline Function(const QString &returnType, const QString &name)
       
   119         : rtype(returnType), fname(name), iline(false), cnst(false) {}
       
   120     inline Function() : iline(false), cnst(false) {}
       
   121 
       
   122     inline void setName(const QString &name) { fname = name; }
       
   123     inline QString name() const { return fname; }
       
   124     
       
   125     inline void setInline(bool i) { iline = i; }
       
   126     inline bool isInline() const { return iline; }
       
   127     
       
   128     inline void setReturnType(const QString &type) { rtype = type; }
       
   129     inline QString returnType() const { return rtype; }
       
   130     
       
   131     inline void addBody(const QString &_body) { body += _body; }
       
   132     inline void addBody(const CodeBlock &block) { body += block.toString(); }
       
   133     inline bool hasBody() const { return !body.isEmpty(); }
       
   134     
       
   135     inline void setConst(bool konst) { cnst = konst; }
       
   136     inline bool isConst() const { return cnst; }
       
   137     
       
   138     void printDeclaration(CodeBlock &block, const QString &funcNamePrefix = QString()) const;
       
   139     QString definition() const;
       
   140 
       
   141 private:
       
   142     QString signature(const QString &funcNamePrefix = QString()) const;
       
   143 
       
   144     QString rtype;
       
   145     QString fname;
       
   146     QString body;
       
   147     bool iline;
       
   148     bool cnst;
       
   149 };
       
   150 
       
   151 class Class
       
   152 {
       
   153 public:
       
   154     enum Access { PublicMember, ProtectedMember, PrivateMember };
       
   155 
       
   156     inline Class(const QString &name) : cname(name) {}
       
   157 
       
   158     inline void setName(const QString &name) { cname = name; }
       
   159     inline QString name() const { return cname; }
       
   160     
       
   161     inline void addMember(Access access, const QString &name)
       
   162     { sections[access].variables.append(name); }
       
   163     inline void addMember(Access access, const Function &func)
       
   164     { sections[access].functions.append(func); }
       
   165     
       
   166     void addConstructor(Access access, const QString &body, const QString &args = QString());
       
   167     inline void addConstructor(Access access, const CodeBlock &body, const QString &args = QString())
       
   168     { addConstructor(access, body.toString(), args); }
       
   169     
       
   170     QString declaration() const;
       
   171     QString definition() const;
       
   172     
       
   173 private:
       
   174     QString cname;
       
   175     struct Section
       
   176     {
       
   177         QVector<Function> functions;
       
   178         QStringList variables;
       
   179         QVector<Function> constructors;
       
   180         
       
   181         inline bool isEmpty() const
       
   182         { return functions.isEmpty() && variables.isEmpty() && constructors.isEmpty(); }
       
   183         
       
   184         void printDeclaration(const Class *klass, CodeBlock &block) const;
       
   185         QString definition(const Class *klass) const;
       
   186     };
       
   187 
       
   188     Section sections[3];
       
   189 };
       
   190 
       
   191 class Generator
       
   192 {
       
   193 public:
       
   194     Generator(const DFA &dfa, const Config &config);
       
   195     
       
   196     QString generate();
       
   197     
       
   198 private:
       
   199     void generateTransitions(CodeBlock &body, const TransitionMap &transitions);
       
   200     bool isSingleReferencedFinalState(int i) const;
       
   201 
       
   202     DFA dfa;
       
   203     Config cfg;
       
   204     InputType minInput;
       
   205     InputType maxInput;
       
   206     QHash<int, int> backReferenceMap;
       
   207     QString headerFileName;
       
   208 public:
       
   209     struct TransitionSequence
       
   210     {
       
   211         inline TransitionSequence() : first(-1), last(-1), transition(-1) {}
       
   212         InputType first;
       
   213         InputType last;
       
   214         int transition;
       
   215         QString testFunction;
       
   216     };
       
   217 private:
       
   218     QVector<TransitionSequence> charFunctionRanges;
       
   219 };
       
   220 
       
   221 #endif