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 }