File indexing completed on 2024-04-28 15:54:24
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 << 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;" << endl 0105 << "if (!parse" << capSymbolName << "(&" << __var; 0106 0107 if (!node->mArguments.isEmpty()) 0108 out << ", " << node->mArguments; 0109 0110 out << "))" << endl; 0111 } 0112 else 0113 { 0114 out << "if (!parse" << capSymbolName << "(" << node->mArguments << "))" 0115 << endl; 0116 } 0117 0118 if (!catch_id) 0119 { 0120 out << "{" << endl; 0121 0122 if (globalSystem.needStateManagement) 0123 out << "if (!mBlockErrors) {" << endl; 0124 0125 out << "expectedSymbol(AstNode::" << capSymbolName << "Kind" 0126 << ", QStringLiteral(\"" << symbol_name << "\")" << ");" << endl; 0127 0128 if (globalSystem.needStateManagement) 0129 out << "}" << endl; 0130 0131 out << "return false;" << endl 0132 << "}" << endl; 0133 } 0134 else 0135 { 0136 out << "{ goto __catch_" << catch_id << "; }" << 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 << ")" << endl; 0145 if (!catch_id) 0146 { 0147 out << "{" << endl; 0148 0149 if (globalSystem.needStateManagement) 0150 out << "if (!mBlockErrors) {" << endl; 0151 0152 out << "expectedToken(yytoken, Token_" << node->mName 0153 << ", QStringLiteral(\"" << node->mDescription << "\"));" << endl; 0154 0155 if (globalSystem.needStateManagement) 0156 out << "}" << endl; 0157 0158 out << "return false;" << endl 0159 << "}" << endl; 0160 } 0161 else 0162 { 0163 out << "goto __catch_" << catch_id << ";" << 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)" << endl 0174 << "yylex();" << endl 0175 << 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 << endl << "&& yytoken != Token_" << t->mName; 0187 } 0188 0189 out << ")" << endl 0190 << "{ yylex(); }" << 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();" << endl 0223 << endl; 0224 } 0225 0226 void CodeGenerator::visitPlus(Model::PlusItem *node) 0227 { 0228 out << "do {" << endl; 0229 visitNode(node->mItem); 0230 out << "} while ("; 0231 generateTestCondition(node, out); 0232 out << ");" << endl; 0233 } 0234 0235 void CodeGenerator::visitStar(Model::StarItem *node) 0236 { 0237 out << "while ("; 0238 generateTestCondition(node, out); 0239 out << ") {" << endl; 0240 visitNode(node->mItem); 0241 out << "}" << 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 << ") {" << endl; 0297 visitNode(n); 0298 out << "}"; 0299 0300 if (it != top_level_nodes.end()) 0301 out << "else "; 0302 else 0303 { 0304 out << "else {" << endl; 0305 0306 if (!mCurrentCatchId) 0307 out << "return false;" << endl; 0308 else 0309 out << "goto __catch_" << mCurrentCatchId << ";"; 0310 0311 out << "}" << 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 << ") {" << 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; }" << endl; 0352 0353 out << "}" << 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);" << endl; 0365 } 0366 0367 out << "qint64 try_startToken_" << mCurrentCatchId 0368 << " = tokenStream->index() - 1;" << endl; 0369 0370 if (!node->mUnsafe) 0371 { 0372 out << "ParserState *try_startState_" << mCurrentCatchId 0373 << " = copyCurrentState();" << endl; 0374 } 0375 0376 out << "{" << endl; 0377 visitNode(node->mTryItem); 0378 out << "}" << endl; 0379 0380 if (node->mCatchItem) 0381 { 0382 out << "blockErrors(blockErrors_" << mCurrentCatchId << ");" << endl; 0383 } 0384 0385 if (!node->mUnsafe) 0386 { 0387 out << "if (try_startState_" << mCurrentCatchId << ")" << endl 0388 << "delete try_startState_" << mCurrentCatchId << ";" << endl 0389 << endl; 0390 } 0391 0392 out << "if (false) // the only way to enter here is using goto" << endl 0393 << "{" << endl 0394 << "__catch_" << mCurrentCatchId << ":" << endl; 0395 0396 if (!node->mUnsafe) 0397 { 0398 out << "if (try_startState_" << mCurrentCatchId << ")" << endl 0399 << "{" << endl 0400 << "restoreState(try_startState_" << mCurrentCatchId << ");" << endl 0401 << "delete try_startState_" << mCurrentCatchId << ";" << endl 0402 << "}" << 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 << ");" << endl 0413 << "rewind(try_startToken_" << mCurrentCatchId << ");" << endl 0414 << endl; 0415 0416 setCatchId(previous_catch_id); 0417 visitNode(node->mCatchItem); 0418 } 0419 0420 out << "}" << endl 0421 << 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);" << endl 0462 << "yylex();" << endl 0463 << 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;" << endl 0472 << "yylex();" << endl 0473 << 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)" << endl 0533 << "(*yynode)->startToken = " << __var << "->startToken;" << 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);" << endl 0548 << endl; 0549 } 0550 else 0551 { 0552 out << target << " = " << __var << ";" << endl 0553 << 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 "}" << 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 << ";" << 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 << ");" << 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 << ")" << endl 0815 << "{" << endl; 0816 0817 if (globalSystem.generateAst) 0818 { 0819 if(isOperatorSymbol(sym)) 0820 out << "QVector<OperatorStackItem> opStack;" << endl; 0821 else 0822 { 0823 out << "*yynode = create<" << sym->mCapitalizedName << "Ast" << ">();" << endl << endl 0824 << "(*yynode)->startToken = tokenStream->index() - 1;" << endl; 0825 //Generate initialization for this ast nodes token-members using -1 as invalid value 0826 GenerateTokenVariableInitialization gentokenvar( out ); 0827 gentokenvar(sym); 0828 out << 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" << endl << "{ return false; }" << endl 0862 << 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 "}" << endl; 0878 } 0879 else 0880 { 0881 out << "(*yynode)->endToken = tokenStream->index() - 2;" << endl 0882 << endl; 0883 } 0884 } 0885 0886 out << "return true;" << endl 0887 << "}" << endl 0888 << 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 << ";" << endl << 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 << ";" << 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)" << endl 0950 << "(*yynode)->startToken = " << argument_startToken << ";" 0951 << endl << 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:" << endl; 1053 else if (m->mMemberKind == Settings::MemberItem::ProtectedDeclaration) 1054 out << "protected:" << endl; 1055 else if (m->mMemberKind == Settings::MemberItem::PrivateDeclaration) 1056 out << "private:" << endl; 1057 1058 out << m->mCode << 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:" << endl 1069 << "typedef " << globalSystem.tokenStream << "::Token Token;" << endl 1070 << globalSystem.tokenStream << " *tokenStream;" << endl 1071 << "int yytoken;" << 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};" << endl; 1080 out << endl 1081 << "inline Token LA(qint64 k = 1) const" << 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 << endl 1084 << "inline int yylex() {" << endl 1085 << "yytoken = tokenStream->read().kind; return yytoken;" << endl 1086 << "}" << endl 1087 << "inline void rewind(qint64 index) {" << endl 1088 << "tokenStream->rewind(index);" << endl 1089 << "yylex();" << endl 1090 << "}" << endl 1091 << endl; 1092 1093 out << "// token stream" << endl 1094 << "void setTokenStream(" << globalSystem.tokenStream << " *s)" << endl 1095 << "{ tokenStream = s; }" << endl 1096 << endl; 1097 1098 out << "// error handling" << endl 1099 << "void expectedSymbol(int kind, const QString& name);" << endl 1100 << "void expectedToken(int kind, qint64 token, const QString& name);" << endl 1101 << endl 1102 << "bool mBlockErrors;" << endl 1103 << "inline bool blockErrors(bool block) {" << endl 1104 << "bool previous = mBlockErrors;" << endl 1105 << "mBlockErrors = block;" << endl 1106 << "return previous;" << endl 1107 << "}" << endl; 1108 1109 out << endl; 1110 1111 if (globalSystem.generateAst) 1112 { 1113 out << "// memory pool" << endl 1114 << "typedef KDevPG::MemoryPool memoryPoolType;" << endl 1115 << endl 1116 << "KDevPG::MemoryPool *memoryPool;" << endl 1117 << "void setMemoryPool(KDevPG::MemoryPool *p)" << endl 1118 << "{ memoryPool = p; }" << endl 1119 << "template <class T>" << endl 1120 << "inline T *create()" << endl 1121 << "{" << endl 1122 << "T *node = new (memoryPool->allocate(sizeof(T))) T();" << endl 1123 << "node->kind = T::KIND;" << endl 1124 << "return node;" << endl 1125 << "}" << endl 1126 << "template <class T>" << endl 1127 << "inline T *create(AstNode *u)" << endl 1128 << "{" << endl 1129 << "T *node = new (memoryPool->allocate(sizeof(T))) T(u);" << endl 1130 << "node->kind = T::KIND;" << endl 1131 << "return node;" << endl 1132 << "}" << endl 1133 << endl; 1134 } 1135 1136 if (globalSystem.parserclassMembers.declarations.empty() == false) 1137 { 1138 out << "// user defined declarations:" << 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 << endl << "public:" << endl; 1148 } 1149 1150 if (globalSystem.needStateManagement) 1151 { 1152 out << "// The copyCurrentState() and restoreState() methods are only declared" << endl 1153 << "// if you are using try blocks in your grammar, and have to be" << endl 1154 << "// implemented by yourself, and you also have to define a" << endl 1155 << "// \"struct ParserState\" inside a %parserclass directive." << endl 1156 << endl 1157 << "// This method should create a new ParserState object and return it," << endl 1158 << "// or return 0 if no state variables need to be saved." << endl 1159 << "ParserState *copyCurrentState();" << endl 1160 << endl 1161 << "// This method is only called for ParserState objects != 0" << endl 1162 << "// and should restore the parser state given as argument." << endl 1163 << "void restoreState(ParserState *state);" << endl; 1164 } 1165 1166 out << "Parser() {" << endl; 1167 if (globalSystem.generateAst) 1168 { 1169 out << "memoryPool = nullptr;" << endl; 1170 } 1171 1172 out << "tokenStream = nullptr;" << endl 1173 << "yytoken = Token_EOF;" << endl 1174 << "mBlockErrors = false;" << endl; 1175 1176 if (globalSystem.parserclassMembers.constructorCode.empty() == false) 1177 { 1178 out << endl << "// user defined constructor code:" << 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 << "}" << endl << endl; 1189 1190 out << "virtual ~Parser() {"; 1191 1192 if (globalSystem.parserclassMembers.destructorCode.empty() == false) 1193 { 1194 out << endl 1195 << "// user defined destructor code:" << 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 << "}" << endl << 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 << "};" << 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;" << endl; 1247 } 1248 } 1249 1250 1251 void GenerateTokenTexts::operator()() 1252 { 1253 out << "switch (token) {" << 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 << ":" << endl; 1258 QString text = t->mDescription; 1259 text.replace('\\', "\\\\").replace('"', "\\\""); 1260 out << " return QStringLiteral(\"" << text << "\");" << endl; 1261 } 1262 out << " default:" << endl; 1263 out << " return QStringLiteral(\"unknown token\");" << endl; 1264 out << "}" << endl; 1265 } 1266 1267 1268 } // namespace KDevPG