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

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 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018    Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #include "kdev-pg-ast-gen.h"
0022 #include "kdev-pg-code-gen.h"
0023 #include "kdev-pg.h"
0024 
0025 #include <QMap>
0026 
0027 namespace KDevPG
0028 {
0029 void GenerateAst::operator()()
0030 {
0031   out << globalSystem.namespaceCode << Qt::endl;
0032 
0033   out << "struct " << globalSystem.exportMacro << " AstNode";
0034 
0035   out << "{" << Qt::endl
0036       << "enum AstNodeKind {" << Qt::endl;
0037 
0038   int node_id = 1000;
0039   for (QMap<QString, Model::SymbolItem*>::iterator it = globalSystem.symbols.begin();
0040        it != globalSystem.symbols.end(); ++it)
0041     {
0042       Model::SymbolItem *sym = (*it);
0043       if(isOperatorSymbol(sym))
0044       {
0045         out << "Prefix" << sym->mCapitalizedName << "Kind" << " = " << node_id << "," << Qt::endl;
0046         ++node_id;
0047         out << "Postfix" << sym->mCapitalizedName << "Kind" << " = " << node_id << "," << Qt::endl;
0048         ++node_id;
0049         out << "Binary" << sym->mCapitalizedName << "Kind" << " = " << node_id << "," << Qt::endl;
0050         ++node_id;
0051         out << "Ternary" << sym->mCapitalizedName << "Kind" << " = " << node_id << "," << Qt::endl;
0052         ++node_id;
0053       }
0054       out << sym->mCapitalizedName << "Kind" << " = " << node_id << "," << Qt::endl;
0055       ++node_id;
0056     }
0057 
0058   out << "AST_NODE_KIND_COUNT" << Qt::endl
0059       << "};" << Qt::endl << Qt::endl
0060       << "int kind;" << Qt::endl
0061       << "qint64 startToken;" << Qt::endl
0062       << "qint64 endToken;" << Qt::endl
0063       << globalSystem.astCode << Qt::endl
0064       << "};" << Qt::endl
0065       << Qt::endl;
0066 
0067   GenerateAstRule gen(out);
0068   for( World::SymbolSet::const_iterator it = globalSystem.symbols.constBegin(); it != globalSystem.symbols.constEnd(); ++it )
0069   {
0070     gen(*it);
0071   }
0072   gen.mFirstTime = false;
0073   while(true)
0074   {
0075     int oldSize = gen.mToGenerate.size();
0076     for(auto i = gen.mToGenerate.begin(); i != gen.mToGenerate.end(); )
0077     {
0078       auto next = i;
0079       ++next;
0080       gen(*i);
0081       i = next;
0082     }
0083     if(gen.mToGenerate.size() == oldSize)
0084       break;
0085   }
0086   gen.mForce = true;
0087   for(auto i = gen.mToGenerate.begin(); i != gen.mToGenerate.end(); )
0088   {
0089     auto next = i;
0090     ++next;
0091     gen(*i);
0092     i = next;
0093   }
0094   out << Qt::endl;
0095 }
0096 
0097 void GenerateAstRule::operator()(Model::SymbolItem *sym)
0098 {
0099   if(!mForce)
0100   {
0101     QString base = globalSystem.astBaseClasses.value(sym->mName, "");
0102     if(!base.isEmpty() && !mGenerated.contains(base))
0103     {
0104       if(mFirstTime)
0105         mToGenerate.insert(sym);
0106       return;
0107     }
0108   }
0109   if(!mFirstTime)
0110     mToGenerate.remove(sym);
0111   mNames.clear();
0112   mInAlternative = false;
0113   mInCons = false;
0114 
0115   World::Environment::iterator it = globalSystem.env.find(sym);
0116   while (it != globalSystem.env.end())
0117   {
0118     Model::EvolveItem *e = *it;
0119     if (it.key() != sym)
0120       break;
0121     
0122     ++it;
0123     
0124     visitNode(e);
0125   }
0126 }
0127 
0128 void GenerateAstRule::visitEvolve(Model::EvolveItem *node)
0129 {
0130   Model::SymbolItem *sym = node->mSymbol;
0131   if (node->mItem->kind == Model::OperatorItem::NodeKind)
0132   {
0133     out << "struct " << globalSystem.exportMacro << " " << sym->mCapitalizedName << "Ast: public "
0134         << globalSystem.astBaseClasses.value(sym->mName, "AstNode")
0135         << "{ enum { KIND = " << sym->mCapitalizedName << "Kind }; };" << Qt::endl << Qt::endl;
0136     #define O(thestr) \
0137     out << "struct " << globalSystem.exportMacro << thestr << sym->mCapitalizedName << "Ast: public " \
0138         << sym->mCapitalizedName << "Ast" \
0139         << " {" << Qt::endl \
0140         << "enum { KIND =" << thestr << sym->mCapitalizedName << "Kind };" << Qt::endl \
0141         << "AstNode *first;" << Qt::endl \
0142         << thestr << sym->mCapitalizedName << "Ast(" \
0143         << ")" << Qt::endl \
0144         << "{\n}" << Qt::endl \
0145         << thestr << sym->mCapitalizedName << "Ast(" \
0146         << "AstNode *first)" << Qt::endl \
0147         << ": first(first)" << Qt::endl \
0148         << "{\n}" << Qt::endl;\
0149         mGenerated.insert(thestr);
0150         
0151     O(" Prefix")
0152 
0153     DefaultVisitor::visitEvolve(node);
0154       
0155     out << "};" << Qt::endl << Qt::endl;
0156     O(" Postfix")
0157 
0158     DefaultVisitor::visitEvolve(node);
0159       
0160     out << "};" << Qt::endl << Qt::endl;
0161     
0162     #undef O
0163     
0164     out << "struct " << globalSystem.exportMacro << " Binary" << sym->mCapitalizedName << "Ast: public "
0165         << sym->mCapitalizedName << "Ast"
0166         << " {" << Qt::endl
0167         << "enum { KIND = Binary" << sym->mCapitalizedName << "Kind };" << Qt::endl
0168         << "AstNode *first;" << Qt::endl
0169         << "AstNode *second;" << Qt::endl
0170         << "Binary" << sym->mCapitalizedName << "Ast("
0171         << "AstNode *first)" << Qt::endl
0172         << ": first(first)" << Qt::endl
0173         << "{\n}" << Qt::endl;
0174     DefaultVisitor::visitEvolve(node);
0175     out << "};" << Qt::endl << Qt::endl;
0176     
0177     out << "struct " << globalSystem.exportMacro << " Ternary" << sym->mCapitalizedName << "Ast: public "
0178         << sym->mCapitalizedName << "Ast"
0179         << " {" << Qt::endl
0180         << "enum { KIND = Ternary" << sym->mCapitalizedName << "Kind };" << Qt::endl
0181         << "AstNode *first;" << Qt::endl
0182         << "AstNode *second;" << Qt::endl
0183         << "AstNode *third;" << Qt::endl
0184         << "Ternary" << sym->mCapitalizedName << "Ast("
0185         << "AstNode *first)" << Qt::endl
0186         << ": first(first)" << Qt::endl
0187         << "{\n}" << Qt::endl;
0188     DefaultVisitor::visitEvolve(node);
0189     out << "};" << Qt::endl << Qt::endl;
0190   }
0191   else
0192   {
0193     out << "struct " << globalSystem.exportMacro << " " << sym->mCapitalizedName << "Ast: public "
0194         << globalSystem.astBaseClasses.value(sym->mName, "AstNode")
0195         << " {" << Qt::endl
0196         << "enum { KIND = " << sym->mCapitalizedName << "Kind };" << Qt::endl << Qt::endl;
0197 
0198     DefaultVisitor::visitEvolve(node);
0199 
0200     out << "};" << Qt::endl << Qt::endl;
0201   }
0202 }
0203 
0204 void GenerateAstRule::visitVariableDeclaration(Model::VariableDeclarationItem *node)
0205 {
0206   GenerateVariableDeclaration<true, true> gen_var_decl(out);
0207   if (node->mStorageType != Model::VariableDeclarationItem::StorageTemporary
0208       && mNames.find(node->mName) == mNames.end())
0209     {
0210       gen_var_decl(node);
0211 
0212       out << ";" << Qt::endl;
0213 
0214       mNames.insert(node->mName);
0215     }
0216 
0217   DefaultVisitor::visitVariableDeclaration(node);
0218 }
0219 
0220 void GenerateAstRule::visitInlinedNonTerminal(Model::InlinedNonTerminalItem* node)
0221 {
0222   KDevPG::DefaultVisitor::visitEvolve(globalSystem.searchRule(node->mSymbol));
0223 }
0224 
0225 void GenerateAstRule::visitAlternative(Model::AlternativeItem *node)
0226 {
0227   bool in_alternative = switchAlternative(true);
0228 
0229 #if defined(AST_OPT_BRANCH)
0230   if (!in_alternative)
0231     {
0232       out << "union" << Qt::endl
0233           << "{" << Qt::endl
0234           << "AstNode *__nodeCast;" << Qt::endl
0235           << "qint64 __token_cast;" << Qt::endl
0236           << Qt::endl;
0237     }
0238 #endif
0239 
0240   DefaultVisitor::visitAlternative(node);
0241 
0242 #if defined(AST_OPT_BRANCH)
0243   if (!in_alternative)
0244     out << "}; // union" << Qt::endl;
0245 #endif
0246 
0247   switchAlternative(in_alternative);
0248 }
0249 
0250 void GenerateAstRule::visitCons(Model::ConsItem *node)
0251 {
0252   bool in_cons = switchCons(true);
0253 
0254 #if defined(AST_OPT_BRANCH)
0255   if (!in_cons)
0256     {
0257       out << "struct" << Qt::endl
0258           << "{" << Qt::endl;
0259     }
0260 #endif
0261 
0262   DefaultVisitor::visitCons(node);
0263 
0264 #if defined(AST_OPT_BRANCH)
0265   if (!in_cons)
0266     {
0267       out << "}; // struct" << Qt::endl;
0268       mNames.clear();
0269     }
0270 #endif
0271 
0272   switchCons(in_cons);
0273 }
0274 
0275 bool GenerateAstRule::switchAlternative(bool alt)
0276 {
0277   bool old = mInAlternative;
0278   mInAlternative = alt;
0279   return old;
0280 }
0281 
0282 bool GenerateAstRule::switchCons(bool c)
0283 {
0284   bool old = mInCons;
0285   mInCons = c;
0286   return old;
0287 }
0288 
0289 void GenerateAstFwd::operator()()
0290 {
0291   out << "struct " << " AstNode;";
0292   
0293   for (QMap<QString, Model::SymbolItem*>::iterator it = globalSystem.symbols.begin();
0294        it != globalSystem.symbols.end(); ++it)
0295   {
0296     Model::SymbolItem *sym = *it;
0297     #define O(name) out << "struct " << name << "Ast;" << Qt::endl;
0298     O(sym->mCapitalizedName)
0299     if(isOperatorSymbol(sym))
0300     {
0301       O("Prefix" + sym->mCapitalizedName)
0302       O("Postfix" + sym->mCapitalizedName)
0303       O("Binary" + sym->mCapitalizedName)
0304       O("Ternary" + sym->mCapitalizedName)
0305     }
0306     #undef O
0307   }
0308 }
0309 
0310 }