File indexing completed on 2024-04-14 04:31:33

0001 /* This file is part of kdev-pg-qt
0002    Copyright (C) 2005 Roberto Raggi <roberto@kdevelop.org>
0003    Copyright (C) 2006 Jakob Petsovits <jpetso@gmx.at>
0004    Copyright (C) 2010 Jonathan Schmidt-Dominé <devel@the-user.org>
0005 
0006    This library is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU Library General Public
0008    License as published by the Free Software Foundation; either
0009    version 2 of the License, or (at your option) any later version.
0010 
0011    This library is distributed in the hope that it will be useful,
0012    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014    Library General Public License for more details.
0015 
0016    You should have received a copy of the GNU Library General Public License
0017    along with this library; see the file COPYING.LIB.  If not, write to
0018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019    Boston, MA 02110-1301, USA.
0020 */
0021 
0022 #include "kdev-pg-code-gen.h"
0023 
0024 #include <QList>
0025 #include <QDebug>
0026 #include <QStack>
0027 #include <QStringList>
0028 #include "kdev-pg-pretty-printer.h"
0029 
0030 namespace KDevPG
0031 {
0032   extern QTextStream checkOut;
0033   
0034   void generateConditionFromStrings(QStringList &tokens, bool zerop, QTextStream& out)
0035   {
0036     tokens.sort();
0037     bool initial = true;
0038     foreach (const QString &token, tokens)
0039       {
0040         if (!initial)
0041           out << Qt::endl << "|| ";
0042 
0043         out << "yytoken == Token_" << token;
0044         initial = false;
0045       }
0046 
0047 
0048     if (initial && zerop)
0049       out << "true /*epsilon*/";
0050   }
0051 
0052   void generateCondition(const World::NodeSet& s, QTextStream& out)
0053   {
0054     if(s.size() == 0 || (s.size() == 1 && nodeCast<Model::ZeroItem*>(*s.begin()) != nullptr))
0055     {
0056       out << "true /*epsilon*/";
0057       return;
0058     }
0059     
0060     Model::Node *item = globalSystem.zero();
0061     
0062     QStringList tokens;
0063     World::NodeSet::const_iterator it = s.begin();
0064     while (it != s.end())
0065     {
0066       item = *it;
0067       ++it;
0068       
0069       if (Model::TerminalItem *t = nodeCast<Model::TerminalItem*>(item))
0070         tokens << t->mName;
0071     }
0072     generateConditionFromStrings(tokens, false, out);
0073   }
0074 
0075   void generateTestCondition(Model::Node *node, QTextStream& out)
0076   {
0077     if(node->kind == Model::NodeKindTerminal)
0078     {
0079       QStringList tokens;
0080       tokens << ((Model::TerminalItem*)node)->mName;
0081       generateConditionFromStrings(tokens, false, out);
0082     }
0083     else
0084     {
0085       World::NodeSet& s = globalSystem.first(node);
0086       
0087       generateCondition(s, out);
0088     }
0089   }
0090 
0091   QString generateParserCall(Model::NonTerminalItem *node, int catch_id, QTextStream& out)
0092   {
0093     static int __id = 0;
0094     static char __var[1024];
0095     QString symbol_name = node->mSymbol->mName;
0096 
0097     QString capSymbolName = node->mSymbol->mCapitalizedName;
0098 
0099     if (globalSystem.generateAst)
0100       {
0101         sprintf(__var, "__node_%d", __id);
0102         ++__id;
0103 
0104         out << capSymbolName << "Ast *" << __var << " = nullptr;" << Qt::endl
0105             << "if (!parse" << capSymbolName << "(&" << __var;
0106 
0107         if (!node->mArguments.isEmpty())
0108             out << ", " << node->mArguments;
0109 
0110         out << "))" << Qt::endl;
0111       }
0112     else
0113       {
0114         out << "if (!parse" << capSymbolName << "(" << node->mArguments << "))"
0115             << Qt::endl;
0116       }
0117 
0118     if (!catch_id)
0119       {
0120         out << "{" << Qt::endl;
0121 
0122         if (globalSystem.needStateManagement)
0123           out <<   "if (!mBlockErrors) {" << Qt::endl;
0124 
0125         out << "expectedSymbol(AstNode::" << capSymbolName << "Kind"
0126             << ", QStringLiteral(\"" << symbol_name << "\")" << ");" << Qt::endl;
0127 
0128         if (globalSystem.needStateManagement)
0129           out << "}" << Qt::endl;
0130 
0131         out << "return false;" << Qt::endl
0132             << "}" << Qt::endl;
0133       }
0134     else
0135       {
0136         out << "{ goto __catch_" << catch_id << "; }" << Qt::endl;
0137       }
0138 
0139     return __var;
0140   }
0141 
0142   void generateTokenTest(Model::TerminalItem *node, int catch_id, QTextStream& out)
0143   {
0144     out << "if (yytoken != Token_" << node->mName << ")" << Qt::endl;
0145     if (!catch_id)
0146       {
0147         out << "{" << Qt::endl;
0148 
0149         if (globalSystem.needStateManagement)
0150           out << "if (!mBlockErrors) {" << Qt::endl;
0151 
0152         out << "expectedToken(yytoken, Token_" << node->mName
0153             << ", QStringLiteral(\"" << node->mDescription << "\"));" << Qt::endl;
0154 
0155         if (globalSystem.needStateManagement)
0156           out << "}" << Qt::endl;
0157 
0158         out << "return false;" << Qt::endl
0159             << "}" << Qt::endl;
0160       }
0161     else
0162       {
0163         out << "goto __catch_" << catch_id << ";" << Qt::endl;
0164       }
0165   }
0166 
0167   void generateRecovery(Model::Node *node, int catch_id, QTextStream& out)
0168   {
0169     World::NodeSet s = globalSystem.follow(node);
0170     Model::Node *item = globalSystem.zero();
0171 
0172     out << "if (try_startToken_" << catch_id
0173         << " == tokenStream->index() - 1  && yytoken != Token_EOF)" << Qt::endl
0174         << "yylex();" << Qt::endl
0175         << Qt::endl;
0176 
0177     out << "while (yytoken != Token_EOF";
0178 
0179     World::NodeSet::iterator it = s.begin();
0180     while (it != s.end())
0181       {
0182         item = *it;
0183         ++it;
0184 
0185         if (Model::TerminalItem *t = nodeCast<Model::TerminalItem*>(item))
0186           out << Qt::endl << "&& yytoken != Token_" << t->mName;
0187       }
0188 
0189     out << ")" << Qt::endl
0190         << "{ yylex(); }" << Qt::endl;
0191   }
0192 
0193 
0194 void CodeGenerator::operator()(Model::Node *node)
0195 {
0196   mEvolve = nodeCast<Model::EvolveItem*>(node);
0197   Q_ASSERT(mEvolve != nullptr);
0198   visitNode(node);
0199 }
0200 
0201 void CodeGenerator::visitZero(Model::ZeroItem *node)
0202 {
0203   Q_UNUSED(node);
0204   // out << " /* nothing to do */" << endl;
0205 }
0206 
0207 void CodeGenerator::visitSymbol(Model::SymbolItem *node)
0208 {
0209   Q_UNUSED(node);
0210   // out << " /* nothing to do */" << endl;
0211 }
0212 
0213 void CodeGenerator::visitNonTerminal(Model::NonTerminalItem *node)
0214 {
0215   generateParserCall(node, mCurrentCatchId, out);
0216 }
0217 
0218 void CodeGenerator::visitTerminal(Model::TerminalItem *node)
0219 {
0220   generateTokenTest(node, mCurrentCatchId, out);
0221 
0222   out << "yylex();" << Qt::endl
0223       << Qt::endl;
0224 }
0225 
0226 void CodeGenerator::visitPlus(Model::PlusItem *node)
0227 {
0228   out << "do {" << Qt::endl;
0229   visitNode(node->mItem);
0230   out << "} while (";
0231   generateTestCondition(node, out);
0232   out << ");" << Qt::endl;
0233 }
0234 
0235 void CodeGenerator::visitStar(Model::StarItem *node)
0236 {
0237   out << "while (";
0238   generateTestCondition(node, out);
0239   out << ") {" << Qt::endl;
0240   visitNode(node->mItem);
0241   out << "}" << Qt::endl;
0242 }
0243 
0244 void CodeGenerator::visitAction(Model::ActionItem *node)
0245 {
0246   DefaultVisitor::visitAction(node);
0247   out << node->mCode;
0248 }
0249 
0250 void CodeGenerator::visitCondition(Model::ConditionItem *node)
0251 {
0252   DefaultVisitor::visitCondition(node);
0253 }
0254 
0255 void CodeGenerator::visitAlternative(Model::AlternativeItem *node)
0256 {
0257   QList<Model::Node*> top_level_nodes;
0258 
0259   QStack<Model::Node*> working_list;
0260   working_list.push(node->mRight);
0261   working_list.push(node->mLeft);
0262 
0263   while (!working_list.empty())
0264     {
0265       Model::Node *n = working_list.top();
0266       working_list.pop();
0267 
0268       if (Model::AlternativeItem *a = nodeCast<Model::AlternativeItem*>(n))
0269         {
0270           working_list.push(a->mRight);
0271           working_list.push(a->mLeft);
0272         }
0273       else
0274         {
0275           top_level_nodes.push_back(n);
0276         }
0277     }
0278 
0279   QList<Model::Node*>::iterator it = top_level_nodes.begin();
0280   while (it != top_level_nodes.end())
0281     {
0282       Model::Node *n = *it;
0283       ++it;
0284       Model::ConditionItem *cond = nodeCast<Model::ConditionItem*>(n);
0285 
0286       out << "if (";
0287 
0288       if (cond)
0289         out << "(";
0290 
0291       generateTestCondition(n, out);
0292 
0293       if (cond)
0294         out << ") && (" << cond->mCode << ")";
0295 
0296       out << ") {" << Qt::endl;
0297       visitNode(n);
0298       out << "}";
0299 
0300       if (it != top_level_nodes.end())
0301         out << "else ";
0302       else
0303         {
0304           out << "else {" << Qt::endl;
0305 
0306           if (!mCurrentCatchId)
0307               out << "return false;" << Qt::endl;
0308           else
0309               out << "goto __catch_" << mCurrentCatchId << ";";
0310 
0311           out << "}" << Qt::endl;
0312         }
0313     }
0314 }
0315 
0316 void CodeGenerator::visitCons(Model::ConsItem *node)
0317 {
0318   DefaultVisitor::visitCons(node);
0319 }
0320 
0321 void CodeGenerator::visitEvolve(Model::EvolveItem *node)
0322 {
0323   out << "if (";
0324 
0325   Model::ConditionItem *cond = nodeCast<Model::ConditionItem*>(node->mItem);
0326 
0327   if (cond)
0328     out << "(";
0329 
0330   generateTestCondition(node, out);
0331 
0332   if (reducesToEpsilon(node->mItem))
0333     {
0334       out << " || ";
0335       generateCondition(globalSystem.follow(node->mSymbol), out);
0336     }
0337 
0338   if (cond)
0339     out << ") && (" << cond->mCode << ")";
0340 
0341   out << ") {" << Qt::endl;
0342 
0343   GenerateLocalDeclarations gen_locals(out, mNames);
0344   gen_locals(node->mItem);
0345 
0346   out << node->mCode;
0347 
0348   visitNode(node->mItem);
0349 
0350   if (globalSystem.start.contains(node->mSymbol))
0351     out << "if (Token_EOF != yytoken) { return false; }" << Qt::endl;
0352 
0353   out << "}" << Qt::endl;
0354 }
0355 
0356 void CodeGenerator::visitTryCatch(Model::TryCatchItem *node)
0357 {
0358   static int tryCatch_counter = 0;
0359   int previous_catch_id = setCatchId(++tryCatch_counter);
0360 
0361   if (node->mCatchItem) // node is a try/rollback block
0362     {
0363       out << "bool blockErrors_" << mCurrentCatchId
0364           << " = blockErrors(true);" << Qt::endl;
0365     }
0366 
0367   out << "qint64 try_startToken_" << mCurrentCatchId
0368       << " = tokenStream->index() - 1;" << Qt::endl;
0369 
0370   if (!node->mUnsafe)
0371     {
0372       out << "ParserState *try_startState_" << mCurrentCatchId
0373           << " = copyCurrentState();" << Qt::endl;
0374     }
0375 
0376   out << "{" << Qt::endl;
0377   visitNode(node->mTryItem);
0378   out << "}" << Qt::endl;
0379 
0380   if (node->mCatchItem)
0381     {
0382       out << "blockErrors(blockErrors_" << mCurrentCatchId << ");" << Qt::endl;
0383     }
0384 
0385   if (!node->mUnsafe)
0386     {
0387       out << "if (try_startState_" << mCurrentCatchId << ")" << Qt::endl
0388           << "delete try_startState_" <<  mCurrentCatchId << ";" << Qt::endl
0389           << Qt::endl;
0390     }
0391 
0392   out << "if (false) // the only way to enter here is using goto" << Qt::endl
0393       << "{" << Qt::endl
0394       << "__catch_" << mCurrentCatchId << ":" << Qt::endl;
0395 
0396   if (!node->mUnsafe)
0397     {
0398       out << "if (try_startState_" << mCurrentCatchId << ")" << Qt::endl
0399           << "{" << Qt::endl
0400           << "restoreState(try_startState_" <<  mCurrentCatchId << ");" << Qt::endl
0401           << "delete try_startState_" <<  mCurrentCatchId << ";" << Qt::endl
0402           << "}" << Qt::endl;
0403     }
0404 
0405   if (!node->mCatchItem)
0406     {
0407       generateRecovery(node, mCurrentCatchId, out);
0408       setCatchId(previous_catch_id);
0409     }
0410   else
0411     {
0412       out << "blockErrors(blockErrors_" << mCurrentCatchId << ");" << Qt::endl
0413           << "rewind(try_startToken_" << mCurrentCatchId << ");" << Qt::endl
0414           << Qt::endl;
0415 
0416       setCatchId(previous_catch_id);
0417       visitNode(node->mCatchItem);
0418     }
0419 
0420   out << "}" << Qt::endl
0421       << Qt::endl;
0422 }
0423 
0424 int CodeGenerator::setCatchId(int catch_id)
0425 {
0426   int previous = mCurrentCatchId;
0427   mCurrentCatchId = catch_id;
0428   return previous;
0429 }
0430 
0431 void CodeGenerator::visitAlias(Model::AliasItem *node)
0432 {
0433   Q_UNUSED(node);
0434   Q_ASSERT(0); // ### not implemented yet
0435 }
0436 
0437 void CodeGenerator::visitAnnotation(Model::AnnotationItem *node)
0438 {
0439   if (!globalSystem.generateAst)
0440     {
0441       // checkOut << "** WARNING annotation ignored" << endl;
0442       visitNode(node->mItem);
0443       return;
0444     }
0445 
0446   if (Model::TerminalItem *t = nodeCast<Model::TerminalItem*>(node->mItem))
0447     {
0448       generateTokenTest(t, mCurrentCatchId, out);
0449 
0450       if (node->mDeclaration->mIsSequence)
0451         {
0452           QString target;
0453 
0454           if (node->mDeclaration->mStorageType == Model::VariableDeclarationItem::StorageAstMember)
0455             target += "(*yynode)->";
0456 
0457           target += node->mDeclaration->mName;
0458           target += "Sequence";
0459 
0460           out << target << " = snoc(" << target << ", "
0461               << "tokenStream->index() - 1, memoryPool);" << Qt::endl
0462               << "yylex();" << Qt::endl
0463               << Qt::endl;
0464         }
0465       else
0466         {
0467           if (node->mDeclaration->mStorageType == Model::VariableDeclarationItem::StorageAstMember)
0468             out << "(*yynode)->";
0469 
0470           out << node->mDeclaration->mName
0471               << " = tokenStream->index() - 1;" << Qt::endl
0472               << "yylex();" << Qt::endl
0473               << Qt::endl;
0474         }
0475     }
0476   else if (Model::NonTerminalItem *nt = nodeCast<Model::NonTerminalItem*>(node->mItem))
0477     {
0478       QString __var = generateParserCall(nt, mCurrentCatchId, out);
0479 
0480       bool check_startToken = false;
0481       World::Environment::iterator it = globalSystem.env.find(nt->mSymbol);
0482       while (it != globalSystem.env.end())
0483         {
0484           Model::EvolveItem *e = (*it);
0485           if (it.key() != nt->mSymbol)
0486             break;
0487 
0488           ++it;
0489 
0490           Model::VariableDeclarationItem *current_decl = e->mDeclarations;
0491           while (current_decl)
0492             {
0493               if ((current_decl->mDeclarationType
0494                    == Model::VariableDeclarationItem::DeclarationArgument)
0495                   &&
0496                   (current_decl->mVariableType
0497                    != Model::VariableDeclarationItem::TypeVariable))
0498                 {
0499                   check_startToken = true;
0500                   break;
0501                 }
0502 
0503               current_decl = current_decl->mNext;
0504             }
0505         }
0506 
0507       if (check_startToken == true)
0508         {
0509           check_startToken = false;
0510           Model::VariableDeclarationItem *current_decl = mEvolve->mDeclarations;
0511           while (current_decl)
0512             {
0513               if ((current_decl->mStorageType
0514                    == Model::VariableDeclarationItem::StorageTemporary)
0515                   &&
0516                   (current_decl->mVariableType
0517                    != Model::VariableDeclarationItem::TypeVariable)
0518                   &&
0519                   (current_decl->mDeclarationType
0520                    == Model::VariableDeclarationItem::DeclarationArgument))
0521                 {
0522                   check_startToken = true;
0523                   break;
0524                 }
0525 
0526               current_decl = current_decl->mNext;
0527             }
0528         }
0529 
0530       if (check_startToken == true)
0531         {
0532           out << "if (" << __var << "->startToken < (*yynode)->startToken)" << Qt::endl
0533               << "(*yynode)->startToken = " << __var << "->startToken;" << Qt::endl;
0534         }
0535 
0536       QString target;
0537       if (node->mDeclaration->mStorageType == Model::VariableDeclarationItem::StorageAstMember)
0538         target += "(*yynode)->";
0539 
0540       target += node->mDeclaration->mName;
0541 
0542       if (node->mDeclaration->mIsSequence)
0543         {
0544           target += "Sequence";
0545 
0546           out << target << " = " << "snoc(" << target << ", "
0547               << __var << ", memoryPool);" << Qt::endl
0548               << Qt::endl;
0549         }
0550       else
0551         {
0552           out << target << " = " << __var << ";" << Qt::endl
0553               << Qt::endl;
0554         }
0555     }
0556   else
0557     Q_ASSERT(0); // ### not supported
0558 }
0559 
0560 void CodeGenerator::visitOperator(Model::OperatorItem *node)
0561 {
0562   out << "bool expectOperator = false;"
0563       << "while(true) {"
0564       << "if(expectOperator) {"
0565       << " ";
0566   const QString capNode = capitalized(node->mName);
0567   const QString nodeType = capNode + "Ast";
0568   const QString baseNameC = node->mBase->mSymbol->mCapitalizedName;
0569   const QString baseType = baseNameC + "Ast";
0570   Model::NonTerminalItem ntItem;
0571   ntItem.mSymbol = mSym;
0572   ntItem.kind = Model::NodeKindNonTerminal;
0573   {
0574     QTextStream argStr(&ntItem.mArguments);
0575     GenerateRecursiveDelegation del(argStr);
0576   }
0577   bool printElse = false;
0578   for(auto i = node->mPost.begin(); i != node->mPost.end(); ++i)
0579   {
0580     if(printElse)
0581       out << "else ";
0582     printElse = true;
0583     out << "if(";
0584     generateTestCondition(i->op.mTok, out);
0585     if(i->op.mCond.size() != 0)
0586       out << " && " << i->op.mCond;
0587     out << ") { const unsigned int priority = " << i->priority << ";";
0588     out << i->op.mCode;
0589     out << "AstNode *last = nullptr; bool br = false;";
0590     out << "while(priority < opStack.last().p + " << i->left << ") {";
0591     out << "if(opStack.size() == 1) {"
0592            "if(last)\n"
0593            "opStack.last().n->endToken = last->endToken;"
0594            "last = opStack.last().n;"
0595            "opStack.pop_back();"
0596            "opStack.push_front(OperatorStackItem((*yynode) = create<Postfix"<< nodeType << ">(last), -2));"
0597            "(*yynode)->endToken = last->endToken + 1;"
0598            "(*yynode)->startToken = last->startToken;"
0599            "br = true; break; } else {"
0600            "AstNode *olast = last;"
0601            "last = opStack.last().n;\n"
0602            "if(olast)\nlast->endToken = olast->endToken;"
0603            "opStack.pop_back(); }}";
0604     out << "if(!br) { "
0605            "opStack.last().n->endToken = last->endToken;"
0606         << "AstNode*& ref = opStack.last().n->kind == AstNode::Binary" << capNode << "Kind && ((Binary" << nodeType << "*)opStack.last().n)->second ? ((Binary" << nodeType << "*)opStack.last().n)->second : ((Binary" << nodeType << "*)opStack.last().n)->first;\n"
0607         << "opStack.push_back(OperatorStackItem(ref = create<Postfix" << nodeType << ">(last), -2));"
0608           "ref->endToken = last->endToken + 1;"
0609           "ref->startToken = last->startToken;"
0610           "} yylex(); }";
0611   }
0612   for(auto i = node->mBin.begin(); i != node->mBin.end(); ++i)
0613   {
0614     if(printElse)
0615       out << "else ";
0616     printElse = true;
0617     out << "if(";
0618     generateTestCondition(i->op.mTok, out);
0619     if(i->op.mCond.size() != 0)
0620       out << " && " << i->op.mCond;
0621     out << ") { const unsigned int priority = " << i->priority << ";";
0622     out << i->op.mCode;
0623     out << "AstNode *last = nullptr; bool br = false;";
0624     out << "while(priority < opStack.last().p + " << i->left << ") {";
0625     out << "if(opStack.size() == 1) {"
0626            "if(last)\n"
0627            "opStack.last().n->endToken = last->endToken;"
0628            "last = opStack.last().n;\n"
0629            "opStack.pop_back();"
0630            "opStack.push_front(OperatorStackItem((*yynode) = create<Binary" << nodeType << ">(last), priority));"
0631            "(*yynode)->startToken = last->startToken;"
0632            "br = true; break; } else {"
0633            "AstNode *olast = last;"
0634            "last = opStack.last().n;\n"
0635            "if(olast)\nlast->endToken = olast->endToken;"
0636            "opStack.pop_back(); }}";
0637     out << "if(!br) { "
0638            "opStack.last().n->endToken = last->endToken;"
0639         << "AstNode*& ref = "
0640            "opStack.last().n->kind == AstNode::Ternary" << capNode << "Kind"
0641            "  ? (((Ternary" << nodeType << "*)opStack.last().n)->third"
0642            "   ? ((Ternary" << nodeType << "*)opStack.last().n)->third"
0643            "   : (((Ternary" << nodeType << "*)opStack.last().n)->second"
0644            "    ? ((Ternary" << nodeType << "*)opStack.last().n)->second"
0645            "    : ((Ternary" << nodeType << "*)opStack.last().n)->first ))"
0646            "  : opStack.last().n->kind == AstNode::Binary" << capNode << "Kind"
0647            " && ((Binary" << nodeType << "*)opStack.last().n)->second"
0648            "  ? ((Binary" << nodeType << "*)opStack.last().n)->second"
0649            "  : ((Binary" << nodeType << "*)opStack.last().n)->first;\n"
0650         << "opStack.push_back(OperatorStackItem(ref = create<Binary" << nodeType << ">(last), priority)); ref->startToken = last->startToken; } expectOperator = false; yylex(); }";
0651   }
0652   for(auto i = node->mTern.begin(); i != node->mTern.end(); ++i)
0653   {
0654     if(printElse)
0655       out << "else ";
0656     printElse = true;
0657     out << "if(";
0658     generateTestCondition(i->first.mTok, out);
0659     if(i->first.mCond.size() != 0)
0660       out << " && " << i->first.mCond;
0661         out << ") { const unsigned int priority = " << i->priority << ";";
0662     out << i->first.mCode;
0663     out << "AstNode *last = nullptr; bool br = false;";
0664     out << "while(priority < opStack.last().p + " << i->left << ") {";
0665     out << "if(opStack.size() == 1) {"
0666            "if(last)\n"
0667            "opStack.last().n->endToken = last->endToken;"
0668            "last = opStack.last().n;\n"
0669            "opStack.pop_back();"
0670            "opStack.push_front(OperatorStackItem((*yynode) = create<Ternary" << nodeType << ">(last), priority));"
0671            "(*yynode)->startToken = last->startToken;"
0672            "yylex();";
0673     QString __var = generateParserCall(&ntItem, mCurrentCatchId, out);
0674     out << "if(!(";
0675     generateTestCondition(i->second.mTok, out);
0676     if(i->second.mCond.size() != 0)
0677       out << " && " << i->second.mCond;
0678     out << ")) return false;"
0679            "((Ternary" << nodeType << "*)*yynode)->second = "
0680         << __var
0681         << ";br = true; break; } else {"
0682            "AstNode *olast = last;"
0683            "last = opStack.last().n;\n"
0684            "if(olast)\nlast->endToken = olast->endToken;"
0685            "opStack.pop_back(); }}";
0686     out << "if(!br) { "
0687            "opStack.last().n->endToken = last->endToken;"
0688         << "AstNode*& ref = "
0689            "opStack.last().n->kind == AstNode::Ternary" << capNode << "Kind"
0690            "  ? (((Ternary" << nodeType << "*)opStack.last().n)->third"
0691            "   ? ((Ternary" << nodeType << "*)opStack.last().n)->third"
0692            "   : (((Ternary" << nodeType << "*)opStack.last().n)->second"
0693            "    ? ((Ternary" << nodeType << "*)opStack.last().n)->second"
0694            "    : ((Ternary" << nodeType << "*)opStack.last().n)->first ))"
0695            "  : opStack.last().n->kind == AstNode::Binary" << capNode << "Kind"
0696            " && ((Binary" << nodeType << "*)opStack.last().n)->second"
0697            "  ? ((Binary" << nodeType << "*)opStack.last().n)->second"
0698            "  : ((Binary" << nodeType << "*)opStack.last().n)->first;\n"
0699         << "opStack.push_back(OperatorStackItem(ref = create<Ternary" << nodeType << ">(last), priority)); ref->startToken = last->startToken; } expectOperator = false; yylex(); }";
0700   }
0701   out << "else ";
0702   out << "break;";
0703   out << "} else {";
0704   printElse = false;
0705   for(auto i = node->mPre.begin(); i != node->mPre.end(); ++i)
0706   {
0707     if(printElse)
0708       out << "else ";
0709     printElse = true;
0710     out << "if(";
0711     generateTestCondition(i->op.mTok, out);
0712     if(i->op.mCond.size() != 0)
0713       out << " && " << i->op.mCond;
0714     out << ") { const unsigned int priority = " << i->priority << ";";
0715     out << i->op.mCode
0716         << "Prefix" << nodeType << " *node = create<Prefix" << nodeType << ">();"
0717            "if(opStack.empty())\n"
0718            "(*yynode) = node;"
0719            "else"
0720            "{\n"
0721            "void *last = opStack.last().n;"
0722            "if(reinterpret_cast<Prefix" << nodeType << "*>(last)->first == nullptr)\n"
0723            "reinterpret_cast<Prefix" << nodeType << "*>(last)->first = node;"
0724            "else if(reinterpret_cast<Binary" << nodeType << "*>(last)->second == nullptr)\n"
0725            "reinterpret_cast<Binary" << nodeType << "*>(last)->second = node;"
0726            "else\n"
0727            "reinterpret_cast<Ternary" << nodeType << "*>(last)->third = node;"
0728            "}"
0729            "opStack.push_back(OperatorStackItem(node, priority));"
0730            "node->startToken = tokenStream->index() - 1;"
0731            "yylex();"
0732            "}" << Qt::endl;
0733   }
0734   for(auto i = node->mParen.begin(); i != node->mParen.end(); ++i)
0735   {
0736     if(printElse)
0737       out << "else ";
0738     printElse = true;
0739     out << "if(";
0740     generateTestCondition(i->first.mTok, out);
0741     if(i->first.mCond.size() != 0)
0742       out << " && " << i->first.mCond;
0743     out << ") { yylex();"
0744            "if(";
0745     generateTestCondition(mSym, out);
0746     out << ") {";
0747     QString __var = generateParserCall(&ntItem, mCurrentCatchId, out);
0748     out << "if(!(";
0749     generateTestCondition(i->second.mTok, out);
0750     if(i->second.mCond.size() != 0)
0751       out << " && " << i->second.mCond;
0752     out << ")) {"
0753            "return false;"
0754            "}"
0755            "--" << __var << "->startToken;"
0756            "++" << __var << "->endToken;"
0757            "yylex();";
0758     #define PUSH_UNARY \
0759         out << "\
0760 if(!opStack.isEmpty())\
0761 {\
0762   void *last = opStack.last().n;\
0763   if(reinterpret_cast<Prefix" << nodeType << "*>(last)->first == nullptr)\n\
0764     reinterpret_cast<Prefix" << nodeType << "*>(last)->first = " << __var << ";" << Qt::endl; \
0765   out << "else if(reinterpret_cast<Binary" << nodeType << "*>(last)->second == nullptr)\n\
0766   reinterpret_cast<Binary" << nodeType << "*>(last)->second = " << __var << ";\
0767   else\nreinterpret_cast<Ternary" << nodeType << "*>(last)->third = " << __var << ";}\
0768 else\n\
0769 (*yynode) = " << __var << ";\
0770 opStack.push_back(OperatorStackItem(" << __var << ", -2));";
0771     PUSH_UNARY
0772     out << "expectOperator = true; } else\nreturn false; }";
0773   }
0774   if(printElse)
0775     out << "else ";
0776   out << "if(";
0777   generateTestCondition(node->mBase->mSymbol, out);
0778   out << ") { ";
0779   QString __var = generateParserCall(node->mBase, mCurrentCatchId, out);
0780   PUSH_UNARY
0781   #undef PUSH_UNARY
0782   out << "expectOperator = true; }";
0783   out << "else"
0784          "{"
0785          "expectedSymbol(AstNode::" << capNode << "Kind"
0786          ", \"" << node->mName << "\");return false;"
0787          "} } }";
0788   /// @TODO Further: empty binary operator
0789 }
0790 
0791 
0792 void GenerateForwardParserRule::operator()(QPair<QString, Model::SymbolItem*> const &__it)
0793 {
0794   Model::SymbolItem *sym = __it.second;
0795   out << "bool" << " " << "parse" << sym->mCapitalizedName << "(";
0796 
0797   GenerateParseMethodSignature gen_signature(out, nullptr);
0798   gen_signature(sym);
0799 
0800   out << ");" << Qt::endl;
0801 }
0802 
0803 void GenerateParserRule::operator()(QPair<QString, Model::SymbolItem*> const &__it)
0804 {
0805   mNames.clear();
0806   Model::SymbolItem *sym = __it.second;
0807   CodeGenerator cg(out, &mNames, sym);
0808 
0809   out << "bool Parser::parse" << sym->mCapitalizedName << "(";
0810 
0811   GenerateParseMethodSignature gen_signature(out, &mNames);
0812   gen_signature(sym);
0813 
0814   out << ")" << Qt::endl
0815       << "{" << Qt::endl;
0816 
0817   if (globalSystem.generateAst)
0818     {
0819       if(isOperatorSymbol(sym))
0820         out << "QVector<OperatorStackItem> opStack;" << Qt::endl;
0821       else
0822       {
0823         out << "*yynode = create<" << sym->mCapitalizedName << "Ast" << ">();" << Qt::endl << Qt::endl
0824             << "(*yynode)->startToken = tokenStream->index() - 1;" << Qt::endl;
0825         //Generate initialization for this ast nodes token-members using -1 as invalid value
0826         GenerateTokenVariableInitialization gentokenvar( out );
0827         gentokenvar(sym);
0828         out << Qt::endl;
0829       }
0830     }
0831 
0832   World::Environment::iterator it = globalSystem.env.find(sym);
0833   GenerateLocalDeclarations gen_locals(out, &mNames);
0834   while (it != globalSystem.env.end())
0835     {
0836       Model::EvolveItem *e = (*it);
0837       if (it.key() != sym)
0838         break;
0839 
0840       ++it;
0841       gen_locals(e->mDeclarations);
0842     }
0843 
0844   it = globalSystem.env.find(sym);
0845   bool initial = true;
0846   while (it != globalSystem.env.end())
0847     {
0848       Model::EvolveItem *e = (*it);
0849       if (it.key() != sym)
0850         break;
0851 
0852       ++it;
0853 
0854       if (!initial)
0855         out << "else ";
0856 
0857       cg(e);
0858       initial = false;
0859     }
0860 
0861   out << "else" << Qt::endl << "{ return false; }" << Qt::endl
0862       << Qt::endl;
0863 
0864 
0865   if (globalSystem.generateAst)
0866     {
0867       if(isOperatorSymbol(sym))
0868       {
0869         out << "AstNode *olast, *last = nullptr;"
0870                "while(!opStack.empty())\n"
0871                "{"
0872                "olast = last;"
0873                "last = opStack.last().n;"
0874                "if(olast)\n"
0875                "last->endToken = olast->endToken;"
0876                "opStack.pop_back();"
0877                "}" << Qt::endl;
0878       }
0879       else
0880       {
0881         out << "(*yynode)->endToken = tokenStream->index() - 2;" << Qt::endl
0882             << Qt::endl;
0883       }
0884     }
0885 
0886   out << "return true;" << Qt::endl
0887       << "}" << Qt::endl
0888       << Qt::endl;
0889 }
0890 
0891 void GenerateLocalDeclarations::operator()(Model::Node *node)
0892 {
0893   visitNode(node);
0894 }
0895 
0896 void GenerateLocalDeclarations::visitVariableDeclaration(Model::VariableDeclarationItem *node)
0897 {
0898   // normal declarations for local variables
0899   if (node->mStorageType == Model::VariableDeclarationItem::StorageTemporary
0900       && node->mDeclarationType == Model::VariableDeclarationItem::DeclarationLocal)
0901     {
0902       if ((mNames == nullptr) || mNames->find(node->mName) == mNames->end())
0903         {
0904           GenerateVariableDeclaration<true, true> gen_var_decl(out);
0905           gen_var_decl(node);
0906 
0907           if (node->mVariableType == Model::VariableDeclarationItem::TypeToken
0908               || node->mVariableType == Model::VariableDeclarationItem::TypeNode
0909               || node->mIsSequence)
0910             {
0911               out << " = 0";
0912             }
0913 
0914           out << ";" << Qt::endl << Qt::endl;
0915 
0916           if (mNames != nullptr)
0917             mNames->insert(node->mName);
0918         }
0919     }
0920 
0921   // for argument member nodes and tokens, check if their index precedes the current one
0922   else if (node->mStorageType == Model::VariableDeclarationItem::StorageAstMember
0923            && node->mDeclarationType == Model::VariableDeclarationItem::DeclarationArgument
0924            && globalSystem.generateAst)
0925     {
0926       QString sequence_suffix = (node->mIsSequence) ? "Sequence" : "";
0927 
0928       out << "(*yynode)->" << node->mName << sequence_suffix << " = "
0929           << node->mName << sequence_suffix << ";" << Qt::endl;
0930 
0931       if (node->mVariableType != Model::VariableDeclarationItem::TypeVariable)
0932         {
0933           QString argument_startToken = node->mName;
0934           if (node->mIsSequence)
0935             argument_startToken += "Sequence->front()->element";
0936 
0937           if (node->mVariableType == Model::VariableDeclarationItem::TypeNode)
0938             argument_startToken += "->startToken";
0939 
0940           out << "if (";
0941 
0942           // check that the variable is not null
0943           if (node->mVariableType == Model::VariableDeclarationItem::TypeNode
0944               || node->mIsSequence)
0945             {
0946               out << node->mName << sequence_suffix << " && ";
0947             }
0948 
0949           out << argument_startToken << " < (*yynode)->startToken)" << Qt::endl
0950               << "(*yynode)->startToken = " << argument_startToken << ";"
0951             << Qt::endl << Qt::endl;
0952         }
0953     }
0954 
0955   DefaultVisitor::visitVariableDeclaration(node);
0956 }
0957 
0958 void GenerateParseMethodSignature::operator()(Model::SymbolItem* sym)
0959 {
0960   if (globalSystem.generateAst)
0961     {
0962       out << sym->mCapitalizedName << "Ast **yynode";
0963       firstParameter = false;
0964     }
0965 
0966   World::Environment::iterator it = globalSystem.env.find(sym);
0967   if (it != globalSystem.env.end())
0968     {
0969       // this creates the method signature using just the first of
0970       // possibly multiple rules with the same name.
0971       Model::EvolveItem *e = (*it);
0972       if (e->mDeclarations)
0973         visitNode(e->mDeclarations);
0974     }
0975 }
0976 
0977 void GenerateRecursiveDelegation::operator()(Model::SymbolItem* node)
0978 {
0979   World::Environment::iterator it = globalSystem.env.find(node);
0980   if (it != globalSystem.env.end())
0981   {
0982     // this creates the method signature using just the first of
0983     // possibly multiple rules with the same name.
0984     Model::EvolveItem *e = (*it);
0985     Model::VariableDeclarationItem *decl = e->mDeclarations;
0986     GenerateVariableDeclaration<false, true> vd(out);
0987     while(decl)
0988     {
0989       vd(decl);
0990       decl = decl->mNext;
0991     }
0992   }
0993 }
0994 
0995 void GenerateParseMethodSignature::visitVariableDeclaration(Model::VariableDeclarationItem *node)
0996 {
0997   if (node->mDeclarationType == Model::VariableDeclarationItem::DeclarationArgument)
0998     {
0999       if (globalSystem.generateAst || (node->mStorageType != Model::VariableDeclarationItem::StorageAstMember))
1000         {
1001           if (firstParameter)
1002             firstParameter = false;
1003           else
1004             out << ", ";
1005 
1006           GenerateVariableDeclaration<true, true> gen_var_decl(out);
1007           gen_var_decl(node);
1008 
1009           if (mNames != nullptr)
1010             mNames->insert(node->mName);
1011         }
1012     }
1013 
1014   DefaultVisitor::visitVariableDeclaration(node);
1015 }
1016 
1017 namespace GenerateVariableDeclarationImpl
1018 {
1019 void printType(QTextStream &out, Model::VariableDeclarationItem *node)
1020 {
1021   if (node->mIsSequence)
1022     out << "const KDevPG::ListNode<";
1023 
1024   if (node->mVariableType == Model::VariableDeclarationItem::TypeToken)
1025     out << "qint64 ";
1026   else if (node->mVariableType == Model::VariableDeclarationItem::TypeNode)
1027   {
1028     out << node->mCapitalizedType << "Ast *";
1029   }else if (node->mVariableType == Model::VariableDeclarationItem::TypeVariable)
1030     out << node->mType << " ";
1031   else
1032     Q_ASSERT(0); // ### not supported
1033 
1034   if (node->mIsSequence)
1035     out << "> *";
1036 }
1037 
1038 void printName(QTextStream &out, Model::VariableDeclarationItem *node)
1039 {
1040   out << node->mName;
1041 
1042   if (node->mIsSequence)
1043     out << "Sequence";
1044 }
1045 }
1046 
1047 void GenerateMemberCode::operator()(Settings::MemberItem* m)
1048 {
1049   if ((mKindMask & m->mMemberKind) != 0)
1050     {
1051       if (m->mMemberKind == Settings::MemberItem::PublicDeclaration)
1052         out << "public:" << Qt::endl;
1053       else if (m->mMemberKind == Settings::MemberItem::ProtectedDeclaration)
1054         out << "protected:" << Qt::endl;
1055       else if (m->mMemberKind == Settings::MemberItem::PrivateDeclaration)
1056         out << "private:" << Qt::endl;
1057 
1058       out << m->mCode << Qt::endl;
1059     }
1060 }
1061 
1062 void GenerateParserDeclarations::operator()()
1063 {
1064   out << "class " << globalSystem.exportMacro << " Parser : ";
1065   if(!globalSystem.parserBaseClass.isEmpty())
1066     out << "public " << globalSystem.parserBaseClass << ", ";
1067   out << "public TokenTypeWrapper\n{"
1068       << "public:" << Qt::endl
1069       << "typedef " << globalSystem.tokenStream << "::Token Token;" << Qt::endl
1070       << globalSystem.tokenStream << " *tokenStream;" << Qt::endl
1071       << "int yytoken;" << Qt::endl;
1072   if(globalSystem.needOperatorStack)
1073     out << "struct OperatorStackItem{AstNode *n; int unsigned p;"
1074            "inline OperatorStackItem(AstNode *n, int unsigned p)\n"
1075            ": n(n), p(p)\n{}\n"
1076            "inline OperatorStackItem()\n{}\n"
1077            "inline OperatorStackItem(const OperatorStackItem& o)\n"
1078            ": n(o.n), p(o.p)\n"
1079            "{}\n};" << Qt::endl;
1080   out << Qt::endl
1081       << "inline Token LA(qint64 k = 1) const" << Qt::endl
1082       << "{ qint64 idx = tokenStream->index() - 1 + k - 1; qint64 oldidx = tokenStream->index(); tokenStream->rewind(tokenStream->size()); while(idx >= tokenStream->size()) tokenStream->read(); tokenStream->rewind(oldidx); return tokenStream->at(idx); }"
1083       << Qt::endl
1084       << "inline int yylex() {" << Qt::endl
1085       << "yytoken = tokenStream->read().kind; return yytoken;" << Qt::endl
1086       << "}" << Qt::endl
1087       << "inline void rewind(qint64 index) {" << Qt::endl
1088       << "tokenStream->rewind(index);" << Qt::endl
1089       << "yylex();" << Qt::endl
1090       << "}" << Qt::endl
1091       << Qt::endl;
1092 
1093   out << "// token stream" << Qt::endl
1094       << "void setTokenStream(" << globalSystem.tokenStream << " *s)" << Qt::endl
1095       << "{ tokenStream = s; }" << Qt::endl
1096       << Qt::endl;
1097 
1098   out << "// error handling" << Qt::endl
1099       << "void expectedSymbol(int kind, const QString& name);" << Qt::endl
1100       << "void expectedToken(int kind, qint64 token, const QString& name);" << Qt::endl
1101       << Qt::endl
1102       << "bool mBlockErrors;" << Qt::endl
1103       << "inline bool blockErrors(bool block) {" << Qt::endl
1104       << "bool previous = mBlockErrors;" << Qt::endl
1105       << "mBlockErrors = block;" << Qt::endl
1106       << "return previous;" << Qt::endl
1107       << "}" << Qt::endl;
1108 
1109   out << Qt::endl;
1110 
1111     if (globalSystem.generateAst)
1112       {
1113         out << "// memory pool" << Qt::endl
1114             << "typedef KDevPG::MemoryPool memoryPoolType;" << Qt::endl
1115             << Qt::endl
1116             << "KDevPG::MemoryPool *memoryPool;" << Qt::endl
1117             << "void setMemoryPool(KDevPG::MemoryPool *p)" << Qt::endl
1118             << "{ memoryPool = p; }" << Qt::endl
1119             << "template <class T>" << Qt::endl
1120             << "inline T *create()" << Qt::endl
1121             << "{" << Qt::endl
1122             << "T *node = new (memoryPool->allocate(sizeof(T))) T();" << Qt::endl
1123             << "node->kind = T::KIND;" << Qt::endl
1124             << "return node;" << Qt::endl
1125             << "}" << Qt::endl
1126             << "template <class T>" << Qt::endl
1127             << "inline T *create(AstNode *u)" << Qt::endl
1128             << "{" << Qt::endl
1129             << "T *node = new (memoryPool->allocate(sizeof(T))) T(u);" << Qt::endl
1130             << "node->kind = T::KIND;" << Qt::endl
1131             << "return node;" << Qt::endl
1132             << "}" << Qt::endl
1133             << Qt::endl;
1134       }
1135 
1136   if (globalSystem.parserclassMembers.declarations.empty() == false)
1137     {
1138       out << "// user defined declarations:" << Qt::endl;
1139       GenerateMemberCode gen(out, Settings::MemberItem::PublicDeclaration
1140                             | Settings::MemberItem::ProtectedDeclaration
1141                             | Settings::MemberItem::PrivateDeclaration);
1142       for( QList<Settings::MemberItem*>::iterator it = globalSystem.parserclassMembers.declarations.begin();
1143                     it != globalSystem.parserclassMembers.declarations.end(); ++it )
1144       {
1145                     gen(*it);
1146       }
1147       out << Qt::endl << "public:" << Qt::endl;
1148     }
1149 
1150   if (globalSystem.needStateManagement)
1151     {
1152       out << "// The copyCurrentState() and restoreState() methods are only declared" << Qt::endl
1153           << "// if you are using try blocks in your grammar, and have to be" << Qt::endl
1154           << "// implemented by yourself, and you also have to define a" << Qt::endl
1155           << "// \"struct ParserState\" inside a %parserclass directive." << Qt::endl
1156           << Qt::endl
1157           << "// This method should create a new ParserState object and return it," << Qt::endl
1158           << "// or return 0 if no state variables need to be saved." << Qt::endl
1159           << "ParserState *copyCurrentState();" << Qt::endl
1160           << Qt::endl
1161           << "// This method is only called for ParserState objects != 0" << Qt::endl
1162           << "// and should restore the parser state given as argument." << Qt::endl
1163           << "void restoreState(ParserState *state);" << Qt::endl;
1164     }
1165 
1166   out << "Parser() {" << Qt::endl;
1167   if (globalSystem.generateAst)
1168     {
1169       out << "memoryPool = nullptr;" << Qt::endl;
1170     }
1171 
1172   out << "tokenStream = nullptr;" << Qt::endl
1173       << "yytoken = Token_EOF;" << Qt::endl
1174       << "mBlockErrors = false;" << Qt::endl;
1175 
1176   if (globalSystem.parserclassMembers.constructorCode.empty() == false)
1177     {
1178       out << Qt::endl << "// user defined constructor code:" << Qt::endl;
1179       GenerateMemberCode gen(out, Settings::MemberItem::ConstructorCode);
1180       for(QList<Settings::MemberItem*>::iterator it =
1181             globalSystem.parserclassMembers.constructorCode.begin();
1182             it != globalSystem.parserclassMembers.constructorCode.end(); ++it )
1183       {
1184         gen(*it);
1185       }
1186     }
1187 
1188   out << "}" << Qt::endl << Qt::endl;
1189 
1190   out << "virtual ~Parser() {";
1191 
1192   if (globalSystem.parserclassMembers.destructorCode.empty() == false)
1193     {
1194       out << Qt::endl
1195           << "// user defined destructor code:" << Qt::endl;
1196 
1197       GenerateMemberCode gen(out, Settings::MemberItem::DestructorCode);
1198       for(QList<Settings::MemberItem*>::iterator it = globalSystem.parserclassMembers.destructorCode.begin();
1199                     it != globalSystem.parserclassMembers.destructorCode.end(); ++it )
1200       {
1201         gen(*it);
1202       }
1203     }
1204 
1205   out << "}" << Qt::endl << Qt::endl;
1206 
1207   GenerateForwardParserRule genfwdparserrule(out);
1208   for( World::SymbolSet::iterator it = globalSystem.symbols.begin();
1209        it != globalSystem.symbols.end(); ++it )
1210   {
1211     genfwdparserrule(qMakePair(it.key(), *it));
1212   }
1213 
1214   out << "};" << Qt::endl;
1215 }
1216 
1217 void GenerateParserBits::operator()()
1218 {
1219   GenerateParserRule gen(out);
1220   for( World::SymbolSet::iterator it = globalSystem.symbols.begin();
1221        it != globalSystem.symbols.end(); ++it )
1222   {
1223     gen(qMakePair(it.key(), *it));
1224   }
1225 }
1226 
1227 void GenerateTokenVariableInitialization::operator()(Model::SymbolItem* sym)
1228 {
1229 
1230   World::Environment::iterator it = globalSystem.env.find(sym);
1231   if (it != globalSystem.env.end())
1232     {
1233       // this creates the method signature using just the first of
1234       // possibly multiple rules with the same name.
1235       Model::EvolveItem *e = (*it);
1236       if (e->mItem)
1237         visitNode(e->mItem);
1238     }
1239 }
1240 
1241 void GenerateTokenVariableInitialization::visitVariableDeclaration(Model::VariableDeclarationItem *node)
1242 {
1243   if( node->mVariableType == Model::VariableDeclarationItem::TypeToken )
1244   {
1245     if( !node->mIsSequence )
1246       out << "(*yynode)->" << node->mName << " = -1;" << Qt::endl;
1247   }
1248 }
1249 
1250 
1251 void GenerateTokenTexts::operator()()
1252 {
1253   out << "switch (token) {" << Qt::endl;
1254   for(World::TerminalSet::iterator it = globalSystem.terminals.begin(); it != globalSystem.terminals.end(); ++it )
1255   {
1256     Model::TerminalItem* t = *it;
1257     out << "    case TokenTypeWrapper::Token_" << t->mName << ":" << Qt::endl;
1258     QString text = t->mDescription;
1259     text.replace('\\', "\\\\").replace('"', "\\\"");
1260     out << "        return QStringLiteral(\"" <<  text << "\");" << Qt::endl;
1261   }
1262   out << "    default:" << Qt::endl;
1263   out << "        return QStringLiteral(\"unknown token\");" << Qt::endl;
1264   out << "}" << Qt::endl;
1265 }
1266 
1267 
1268 } // namespace KDevPG