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 tools applications 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 CODEGENERATOR_H 29 #define CODEGENERATOR_H 30 31 #include <QByteArray> 32 #include <QString> 33 #include <QList> 34 #include <QStack> 35 36 namespace CodeGenerator 37 { 38 enum GeneratorType {NoopType, CompoundType, TextType, RepeaterType, CounterType, GroupType}; 39 class BaseGenerator; 40 typedef QStack<BaseGenerator *> GeneratorStack; 41 42 template <typename ValueType> 43 class Stacker { 44 public: Stacker(QStack<ValueType> * stack,ValueType value)45 Stacker(QStack<ValueType> *stack, ValueType value) : stack(stack) { stack->push(value); } ~Stacker()46 ~Stacker() { stack->pop();} 47 private: 48 QStack<ValueType> *stack; 49 }; 50 typedef Stacker<BaseGenerator *> GeneratorStacker; 51 52 class BaseGenerator 53 { 54 public: type(type)55 BaseGenerator(GeneratorType type = NoopType) : type(type) {} ~BaseGenerator()56 virtual ~BaseGenerator() {}; generate(GeneratorStack * stack)57 virtual QByteArray generate(GeneratorStack *stack) { Q_UNUSED(stack); return QByteArray(); }; 58 int currentCount(GeneratorStack *stack) const; 59 int repeatCount(GeneratorStack *stack) const; 60 GeneratorType type; 61 }; 62 63 class Item 64 { 65 public: Item(BaseGenerator * const base)66 Item(BaseGenerator * const base) : generator(base) {} 67 Item(const char * const text); generate()68 QByteArray generate() const 69 { GeneratorStack stack; return generator->generate(&stack); } 70 // ### TODO: Fix memory leak! 71 // QExplicitlySharedDataPointer<BaseGenerator> generator; 72 BaseGenerator * const generator; 73 }; 74 75 class CompoundGenerator : public BaseGenerator 76 { 77 public: CompoundGenerator(BaseGenerator * const a,BaseGenerator * const b)78 CompoundGenerator(BaseGenerator * const a, BaseGenerator * const b) 79 : BaseGenerator(CompoundType), a(a), b(b) {} generate(GeneratorStack * stack)80 virtual QByteArray generate(GeneratorStack *stack) 81 { return a->generate(stack) + b->generate(stack); }; 82 protected: 83 BaseGenerator * const a; 84 BaseGenerator * const b; 85 }; 86 87 class Compound : public Item 88 { 89 public: Compound(const Item & a,const Item & b)90 Compound(const Item &a, const Item &b) : Item(new CompoundGenerator(a.generator, b.generator)) {} 91 }; 92 93 class TextGenerator : public BaseGenerator 94 { 95 public: TextGenerator(const QByteArray & text)96 TextGenerator(const QByteArray &text) : BaseGenerator(TextType), text(text) {} generate(GeneratorStack *)97 virtual QByteArray generate(GeneratorStack *) { return text; }; 98 protected: 99 QByteArray text; 100 }; 101 102 class Text : public Item { 103 public: Text(const QByteArray & text)104 Text(const QByteArray &text) : Item(new TextGenerator(text)) {} Text(const char * const text)105 Text(const char * const text) : Item(new TextGenerator(QByteArray(text))) {} 106 }; 107 108 class RepeaterGenerator : public BaseGenerator 109 { 110 public: RepeaterGenerator(BaseGenerator * const childGenerator)111 RepeaterGenerator(BaseGenerator * const childGenerator) 112 : BaseGenerator(RepeaterType), repeatCount(1), repeatOffset(0), childGenerator(childGenerator) {} 113 virtual QByteArray generate(GeneratorStack *stack); 114 115 int repeatCount; 116 int repeatOffset; 117 int currentRepeat; 118 BaseGenerator * const childGenerator; 119 }; 120 121 class Repeater : public Item { 122 public: Repeater(const Item & item)123 Repeater(const Item &item) : Item(new RepeaterGenerator(item.generator)) {} setRepeatCount(int count)124 void setRepeatCount(int count) 125 { static_cast<RepeaterGenerator * const>(generator)->repeatCount = count; } setRepeatOffset(int offset)126 void setRepeatOffset(int offset) 127 { static_cast<RepeaterGenerator * const>(generator)->repeatOffset = offset; } 128 }; 129 130 class CounterGenerator : public BaseGenerator 131 { 132 public: CounterGenerator()133 CounterGenerator() : BaseGenerator(CounterType), offset(0), increment(1), reverse(false) {} generate(GeneratorStack * stack)134 QByteArray generate(GeneratorStack *stack) 135 { 136 if (reverse) 137 return QByteArray::number(repeatCount(stack) - (currentCount(stack) * increment) + offset + 1); 138 else 139 return QByteArray::number((currentCount(stack) * increment) + offset); 140 } 141 int offset; 142 int increment; 143 bool reverse; 144 }; 145 146 class Counter : public Item { 147 public: Counter()148 Counter() : Item(new CounterGenerator()) {} Counter(int offset)149 Counter(int offset) : Item(new CounterGenerator()) { setOffset(offset); } setOffset(int offset)150 void setOffset(int offset) 151 { static_cast<CounterGenerator *>(generator)->offset = offset; } setIncrement(int increment)152 void setIncrement(int increment) 153 { static_cast<CounterGenerator *>(generator)->increment = increment; } setReverse(bool reverse)154 void setReverse(bool reverse) 155 { static_cast<CounterGenerator *>(generator)->reverse = reverse; } 156 157 }; 158 159 class GroupGenerator : public BaseGenerator 160 { 161 public: GroupGenerator(BaseGenerator * const childGenerator)162 GroupGenerator(BaseGenerator * const childGenerator) 163 : BaseGenerator(GroupType), currentRepeat(0), childGenerator(childGenerator), 164 separator(new BaseGenerator()), prefix(new BaseGenerator()), postfix(new BaseGenerator()) { } 165 virtual QByteArray generate(GeneratorStack *stack); 166 int currentRepeat; 167 BaseGenerator * const childGenerator; 168 BaseGenerator *separator; 169 BaseGenerator *prefix; 170 BaseGenerator *postfix; 171 }; 172 173 class Group : public Item 174 { 175 public: Group(const Item & item)176 Group(const Item &item) : Item(new GroupGenerator(item.generator)) { setSeparator(", "); } setSeparator(const Item & separator)177 void setSeparator(const Item &separator) 178 { static_cast<GroupGenerator *>(generator)->separator = separator.generator; } setPrefix(const Item & prefix)179 void setPrefix(const Item &prefix) 180 { static_cast<GroupGenerator *>(generator)->prefix = prefix.generator; } setPostfix(const Item & postfix)181 void setPostfix(const Item &postfix) 182 { static_cast<GroupGenerator *>(generator)->postfix = postfix.generator; } 183 }; 184 185 const Compound operator+(const Item &a, const Item &b); 186 const Compound operator+(const Item &a, const char * const text); 187 const Compound operator+(const char * const text, const Item &b); 188 189 } //namespace CodeGenerator 190 191 #endif 192