File indexing completed on 2024-04-21 04:36:15
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-generate.h" 0022 0023 #include "kdev-pg.h" 0024 #include "kdev-pg-code-gen.h" 0025 #include "kdev-pg-ast-gen.h" 0026 #include "kdev-pg-visitor-gen.h" 0027 #include "kdev-pg-visitor-bits-gen.h" 0028 #include "kdev-pg-default-visitor-gen.h" 0029 #include "kdev-pg-default-visitor-bits-gen.h" 0030 #include "kdev-pg-serialize-visitor-gen.h" 0031 #include "kdev-pg-debug-visitor-gen.h" 0032 #include "kdev-pg-new-visitor-gen.h" 0033 #include "kdev-pg-new-visitor-bits-gen.h" 0034 #include "kdev-pg-beautifier.h" 0035 #include "kdev-pg-regexp.h" 0036 0037 #include <QTextStream> 0038 #include <QFile> 0039 #include "kdev-pg-token-type-gen.h" 0040 0041 namespace KDevPG 0042 { 0043 void generateOutput() 0044 { 0045 QByteArray language = globalSystem.language.toUpper().toLatin1(); 0046 for(int i = 0; i != language.size(); ++i) 0047 { 0048 if(language[i] < '0' || (language[i] > '9' && language[i] < 'A') || language[i] > 'Z') 0049 language[i] = '_'; 0050 } 0051 0052 if (globalSystem.generateAst) 0053 { 0054 { // generate the ast 0055 QString str; 0056 QTextStream s(&str, QIODevice::WriteOnly); 0057 0058 GenerateAst _Ast(s); 0059 0060 s << "// THIS FILE IS GENERATED" << Qt::endl 0061 << "// WARNING! All changes made in this file will be lost!" << Qt::endl 0062 << Qt::endl 0063 0064 << "#ifndef " << language << "_AST_H_INCLUDED" << Qt::endl 0065 << "#define " << language << "_AST_H_INCLUDED" << Qt::endl 0066 << Qt::endl 0067 0068 << "#include \"" << globalSystem.language << "ast-fwd.h\"" << Qt::endl 0069 << Qt::endl; 0070 if (!globalSystem.exportMacroHeader.isEmpty()) 0071 s << "#include \"" << globalSystem.exportMacroHeader << "\"" 0072 << Qt::endl; 0073 0074 foreach (const QString& header, globalSystem.astHeaders) 0075 s << "#include \"" << header << "\"\n"; 0076 0077 s << "#include <QList>" << Qt::endl 0078 << "#include <kdev-pg-list.h>" << Qt::endl 0079 << Qt::endl; 0080 0081 if (!globalSystem.decl.isEmpty()) 0082 s << globalSystem.decl << Qt::endl; 0083 0084 s << "namespace " << globalSystem.ns << "{" << Qt::endl 0085 << Qt::endl; 0086 0087 _Ast(); 0088 0089 s << Qt::endl << "} // end of namespace " << globalSystem.ns << Qt::endl 0090 << Qt::endl 0091 0092 << "#endif" << Qt::endl 0093 << Qt::endl; 0094 0095 QString oname = globalSystem.language; 0096 oname += "ast.h"; 0097 0098 format(s, oname); 0099 } 0100 { // generate ast forward declarations 0101 0102 QString str; 0103 QTextStream s(&str, QIODevice::WriteOnly); 0104 0105 GenerateAstFwd _AstFwd(s); 0106 0107 s << ""// THIS FILE IS GENERATED" << Qt::endl 0108 << "// WARNING! All changes made in this file will be lost!" << Qt::endl 0109 << Qt::endl 0110 0111 << "#ifndef " << language << "_AST_FWD_INCLUDED" << Qt::endl 0112 << "#define " << language << "_AST_FWD_INCLUDED" << Qt::endl 0113 << Qt::endl; 0114 if (!globalSystem.exportMacroHeader.isEmpty()) 0115 s << "#include \"" << globalSystem.exportMacroHeader << "\"" 0116 << Qt::endl; 0117 0118 s << "namespace " << globalSystem.ns << "{" << Qt::endl 0119 << Qt::endl; 0120 0121 _AstFwd(); 0122 0123 s << Qt::endl << "} // end of namespace " << globalSystem.ns << Qt::endl 0124 << Qt::endl 0125 0126 << "#endif" << Qt::endl 0127 << Qt::endl; 0128 0129 QString oname = globalSystem.language; 0130 oname += "ast-fwd.h"; 0131 0132 format(s, oname); 0133 } 0134 } 0135 { // generate token type 0136 QString str; 0137 QTextStream s(&str, QIODevice::WriteOnly); 0138 0139 GenerateTokenType gen(s); 0140 0141 s << "// THIS FILE IS GENERATED" << Qt::endl 0142 << "// WARNING! All changes made in this file will be lost!" << Qt::endl 0143 << Qt::endl 0144 0145 << "#ifndef " << language << "_TOKEN_TYPE_H_INCLUDED" << Qt::endl 0146 << "#define " << language << "_TOKEN_TYPE_H_INCLUDED" << Qt::endl 0147 << Qt::endl; 0148 if (!globalSystem.exportMacroHeader.isEmpty()) 0149 s << "#include \"" << globalSystem.exportMacroHeader << "\"" 0150 << Qt::endl; 0151 0152 foreach (const QString& header, globalSystem.astHeaders) 0153 s << "#include \"" << header << "\"\n"; 0154 0155 if (!globalSystem.decl.isEmpty()) 0156 s << globalSystem.decl << Qt::endl; 0157 0158 s << "namespace " << globalSystem.ns << "{" << Qt::endl 0159 << Qt::endl; 0160 0161 gen(); 0162 0163 s << Qt::endl << "} // end of namespace " << globalSystem.ns << Qt::endl 0164 << Qt::endl 0165 0166 << "#endif" << Qt::endl 0167 << Qt::endl; 0168 0169 QString oname = globalSystem.language; 0170 oname += "tokentype.h"; 0171 0172 format(s, oname); 0173 } 0174 { // generate the parser decls 0175 QString str; 0176 QTextStream s(&str, QIODevice::WriteOnly); 0177 0178 GenerateParserDeclarations __decls(s); 0179 0180 s << "// THIS FILE IS GENERATED" << Qt::endl 0181 << "// WARNING! All changes made in this file will be lost!" << Qt::endl 0182 << Qt::endl 0183 0184 << "#ifndef " << language << "_H_INCLUDED" << Qt::endl 0185 << "#define " << language << "_H_INCLUDED" << Qt::endl 0186 << Qt::endl; 0187 0188 0189 s << "#include \"" << globalSystem.language << "tokentype.h\"" << Qt::endl; 0190 0191 if(globalSystem.hasLexer) 0192 s << "#include \"" << globalSystem.language << "lexer.h\"" << Qt::endl; 0193 0194 if (globalSystem.generateAst) 0195 { 0196 s << "#include \"" << globalSystem.language << "ast-fwd.h\"" << Qt::endl 0197 << "#include <kdev-pg-memory-pool.h>" << Qt::endl 0198 << "#include <kdev-pg-allocator.h>" << Qt::endl; 0199 } 0200 0201 if (globalSystem.tokenStream == "KDevPG::TokenStream") 0202 s << "#include <kdev-pg-token-stream.h>" << Qt::endl; 0203 0204 foreach (const QString& header, globalSystem.parserDeclarationHeaders) 0205 s << "#include \"" << header << "\"\n"; 0206 0207 s << Qt::endl; 0208 if (!globalSystem.exportMacroHeader.isEmpty()) 0209 s << "#include \"" << globalSystem.exportMacroHeader << "\"" 0210 << Qt::endl; 0211 0212 if (globalSystem.needOperatorStack) 0213 s << "#include <QVector>" << Qt::endl; 0214 0215 if (!globalSystem.decl.isEmpty() && !globalSystem.generateAst) 0216 s << globalSystem.decl << Qt::endl; 0217 0218 s << "namespace " << globalSystem.ns << "{" << Qt::endl 0219 << Qt::endl; 0220 0221 __decls(); 0222 0223 s << Qt::endl << "} // end of namespace " << globalSystem.ns << Qt::endl 0224 << Qt::endl 0225 0226 << "#endif" << Qt::endl 0227 << Qt::endl; 0228 0229 QString oname = globalSystem.language; 0230 oname += "parser.h"; 0231 0232 format(s, oname); 0233 } 0234 0235 if (globalSystem.generateAst) 0236 { // generate the visitor decls 0237 QString str; 0238 QTextStream s(&str, QIODevice::WriteOnly); 0239 0240 GenerateVisitor __visitor(s); 0241 0242 s << "// THIS FILE IS GENERATED" << Qt::endl 0243 << "// WARNING! All changes made in this file will be lost!" << Qt::endl 0244 << Qt::endl 0245 0246 << "#ifndef " << language << "_VISITOR_H_INCLUDED" << Qt::endl 0247 << "#define " << language << "_VISITOR_H_INCLUDED" << Qt::endl 0248 << Qt::endl 0249 0250 << "#include \"" << globalSystem.language << "ast.h\"" << Qt::endl 0251 << Qt::endl; 0252 if (!globalSystem.exportMacroHeader.isEmpty()) 0253 s << "#include \"" << globalSystem.exportMacroHeader << "\"" 0254 << Qt::endl; 0255 0256 s << "namespace " << globalSystem.ns << "{" << Qt::endl 0257 << Qt::endl; 0258 0259 __visitor(); 0260 0261 s << Qt::endl << "} // end of namespace " << globalSystem.ns << Qt::endl 0262 << Qt::endl 0263 0264 << "#endif" << Qt::endl 0265 << Qt::endl; 0266 0267 QString oname = globalSystem.language; 0268 oname += "visitor.h"; 0269 0270 format(s, oname); 0271 } 0272 0273 if (globalSystem.generateAst) 0274 { // generate the default visitor 0275 QString str; 0276 QTextStream s(&str, QIODevice::WriteOnly); 0277 0278 GenerateDefaultVisitor __DefaultVisitor(s); 0279 0280 s << "// THIS FILE IS GENERATED" << Qt::endl 0281 << "// WARNING! All changes made in this file will be lost!" << Qt::endl 0282 << Qt::endl 0283 0284 << "#ifndef " << language << "_DEFAULT_VISITOR_H_INCLUDED" << Qt::endl 0285 << "#define " << language << "_DEFAULT_VISITOR_H_INCLUDED" << Qt::endl 0286 << Qt::endl 0287 0288 << "#include \"" << globalSystem.language << "visitor.h\"" << Qt::endl 0289 << Qt::endl; 0290 if (!globalSystem.exportMacroHeader.isEmpty()) 0291 s << "#include \"" << globalSystem.exportMacroHeader << "\"" 0292 << Qt::endl; 0293 0294 s << "namespace " << globalSystem.ns << "{" << Qt::endl 0295 << Qt::endl; 0296 0297 __DefaultVisitor(); 0298 0299 s << Qt::endl << "} // end of namespace " << globalSystem.ns << Qt::endl 0300 << Qt::endl 0301 0302 << "#endif" << Qt::endl 0303 << Qt::endl; 0304 0305 QString oname = globalSystem.language; 0306 oname += "defaultvisitor.h"; 0307 0308 format(s, oname); 0309 } 0310 0311 if (globalSystem.generateSerializeVisitor) 0312 { // generate the serialization visitor 0313 QString str; 0314 QTextStream s(&str, QIODevice::WriteOnly); 0315 0316 GenerateSerializeVisitor __serialize_visitor(s); 0317 0318 s << "// THIS FILE IS GENERATED" << Qt::endl 0319 << "// WARNING! All changes made in this file will be lost!" << Qt::endl 0320 << Qt::endl 0321 0322 << "#ifndef " << language << "_SERIALIZATION_H_INCLUDED" << Qt::endl 0323 << "#define " << language << "_SERIALIZATION_H_INCLUDED" << Qt::endl 0324 << Qt::endl 0325 0326 << "#include \"" << globalSystem.language << "defaultvisitor.h\"" << Qt::endl 0327 << Qt::endl; 0328 if (!globalSystem.exportMacroHeader.isEmpty()) 0329 s << "#include \"" << globalSystem.exportMacroHeader << "\"" 0330 << Qt::endl; 0331 0332 s << "#include <QTextStream>" << Qt::endl 0333 << "#include <QFile>" << Qt::endl 0334 << Qt::endl 0335 0336 << "namespace " << globalSystem.ns << "{" << Qt::endl 0337 << Qt::endl; 0338 0339 __serialize_visitor(); 0340 0341 s << Qt::endl << "} // end of namespace " << globalSystem.ns << Qt::endl 0342 << Qt::endl; 0343 0344 s << "#endif" << Qt::endl 0345 << Qt::endl; 0346 0347 QString oname = globalSystem.language; 0348 oname += "serializevisitor.h"; 0349 0350 format(s, oname); 0351 } 0352 0353 if (globalSystem.generateDebugVisitor) 0354 { // generate the debug visitor 0355 QString str; 0356 QTextStream s(&str, QIODevice::WriteOnly); 0357 0358 GenerateDebugVisitor __debug_visitor(s); 0359 0360 s << "// THIS FILE IS GENERATED" << Qt::endl 0361 << "// WARNING! All changes made in this file will be lost!" << Qt::endl 0362 << Qt::endl 0363 0364 << "#ifndef " << language << "_DEBUG_VISITOR_H_INCLUDED" << Qt::endl 0365 << "#define " << language << "_DEBUG_VISITOR_H_INCLUDED" << Qt::endl 0366 << Qt::endl 0367 0368 << "#include \"" << globalSystem.language << "defaultvisitor.h\"" << Qt::endl 0369 << Qt::endl; 0370 if (!globalSystem.exportMacroHeader.isEmpty()) 0371 s << "#include \"" << globalSystem.exportMacroHeader << "\"" 0372 << Qt::endl; 0373 0374 s << "#include <kdev-pg-token-stream.h>" << Qt::endl; 0375 0376 s << "#include <QTextStream>" << Qt::endl 0377 << "#include <QDebug>" << Qt::endl 0378 << Qt::endl 0379 0380 << "namespace " << globalSystem.ns << "{" << Qt::endl 0381 << Qt::endl; 0382 0383 __debug_visitor(); 0384 0385 s << Qt::endl << "} // end of namespace " << globalSystem.ns << Qt::endl 0386 << Qt::endl; 0387 0388 s << "#endif" << Qt::endl 0389 << Qt::endl; 0390 0391 QString oname = globalSystem.language; 0392 oname += "debugvisitor.h"; 0393 0394 format(s, oname); 0395 } 0396 if (globalSystem.generateTokenText || globalSystem.generateDebugVisitor) 0397 { // generate the token text function 0398 QString str; 0399 QTextStream s(&str, QIODevice::WriteOnly); 0400 0401 s << "// THIS FILE IS GENERATED" << Qt::endl 0402 << "// WARNING! All changes made in this file will be lost!" << Qt::endl 0403 << Qt::endl 0404 0405 << "#ifndef " << language << "_TOKEN_TEXT_H_INCLUDED" << Qt::endl 0406 << "#define " << language << "_TOKEN_TEXT_H_INCLUDED" << Qt::endl 0407 << Qt::endl; 0408 0409 if (!globalSystem.exportMacroHeader.isEmpty()) 0410 s << "#include \"" << globalSystem.exportMacroHeader << "\"" << Qt::endl; 0411 0412 s << "#include \"" << globalSystem.language << "tokentype.h\"" << Qt::endl 0413 0414 << "namespace " << globalSystem.ns << "{" << Qt::endl 0415 << Qt::endl 0416 0417 << "QString tokenText(int token)" << Qt::endl << "{" << Qt::endl; 0418 0419 GenerateTokenTexts gen(s); 0420 gen(); 0421 0422 s << "}" 0423 << Qt::endl << "} // end of namespace " << globalSystem.ns << Qt::endl 0424 << Qt::endl; 0425 0426 s << "#endif" << Qt::endl 0427 << Qt::endl; 0428 0429 QString oname = globalSystem.language; 0430 oname += "tokentext.h"; 0431 0432 format(s, oname); 0433 } 0434 { // generate the parser bits 0435 QString str; 0436 QTextStream s(&str, QIODevice::WriteOnly); 0437 0438 GenerateParserBits __bits(s); 0439 0440 s << "// THIS FILE IS GENERATED" << Qt::endl 0441 << "// WARNING! All changes made in this file will be lost!" << Qt::endl 0442 << Qt::endl; 0443 0444 s << "#include \"" << globalSystem.language << "parser.h\"" 0445 << Qt::endl; 0446 0447 if (globalSystem.generateAst) 0448 { 0449 s << "#include \"" << globalSystem.language << "ast.h\"" << Qt::endl; 0450 } 0451 0452 foreach (const QString& header, globalSystem.parserBitsHeaders) 0453 s << "#include \"" << header << "\"\n"; 0454 0455 s << Qt::endl; 0456 0457 if (!globalSystem.bits.isEmpty()) 0458 s << globalSystem.bits << Qt::endl; 0459 0460 s << "namespace " << globalSystem.ns << "{" << Qt::endl 0461 << Qt::endl; 0462 0463 __bits(); 0464 0465 s << Qt::endl << "} // end of namespace " << globalSystem.ns << Qt::endl 0466 << Qt::endl; 0467 0468 QString oname = globalSystem.language; 0469 oname += "parser.cpp"; 0470 0471 format(s, oname); 0472 } 0473 0474 if (globalSystem.generateAst) 0475 { // generate the visitor bits 0476 QString str; 0477 QTextStream s(&str, QIODevice::WriteOnly); 0478 0479 GenerateVisitorBits __visitor_bits(s); 0480 0481 s << "// THIS FILE IS GENERATED" << Qt::endl 0482 << "// WARNING! All changes made in this file will be lost!" << Qt::endl 0483 << Qt::endl 0484 0485 << "#include \"" << globalSystem.language << "visitor.h\"" << Qt::endl 0486 0487 << Qt::endl 0488 0489 << "namespace " << globalSystem.ns << "{" << Qt::endl 0490 << Qt::endl; 0491 0492 __visitor_bits(); 0493 0494 s << Qt::endl << "} // end of namespace " << globalSystem.ns << Qt::endl 0495 << Qt::endl; 0496 0497 QString oname = globalSystem.language; 0498 oname += "visitor.cpp"; 0499 0500 format(s, oname); 0501 } 0502 0503 if (globalSystem.generateAst) 0504 { // generate the default visitor bits 0505 QString str; 0506 QTextStream s(&str, QIODevice::WriteOnly); 0507 0508 s << "// THIS FILE IS GENERATED" << Qt::endl 0509 << "// WARNING! All changes made in this file will be lost!" << Qt::endl 0510 << Qt::endl 0511 0512 << "#include \"" << globalSystem.language << "defaultvisitor.h\"" << Qt::endl 0513 << Qt::endl 0514 0515 << "namespace " << globalSystem.ns << "{" << Qt::endl 0516 0517 << Qt::endl; 0518 0519 GenerateDefaultVisitorBitsRule gen(s); 0520 for( World::SymbolSet::iterator it = globalSystem.symbols.begin(); 0521 it != globalSystem.symbols.end(); ++it ) 0522 { 0523 gen(qMakePair(it.key(), *it)); 0524 } 0525 0526 s << Qt::endl << "} // end of namespace " << globalSystem.ns << Qt::endl 0527 << Qt::endl; 0528 0529 QString oname = globalSystem.language; 0530 oname += "defaultvisitor.cpp"; 0531 0532 format(s, oname); 0533 } 0534 } 0535 0536 void generateLexer() 0537 { 0538 QByteArray language = globalSystem.language.toUpper().toLatin1(); 0539 bool hasStates = globalSystem.lexerEnvs.size() > 1; 0540 0541 { // generate the lexer header 0542 QString str; 0543 QTextStream s(&str, QIODevice::WriteOnly); 0544 0545 s << "// THIS FILE IS GENERATED" << Qt::endl 0546 << "// WARNING! All changes made in this file will be lost!" << Qt::endl 0547 << Qt::endl 0548 0549 << "#ifndef " << language << "_LEXER_H_INCLUDED" << Qt::endl 0550 << "#define " << language << "_LEXER_H_INCLUDED" << Qt::endl 0551 << Qt::endl 0552 0553 << "#include \"" << globalSystem.language << "tokentype.h\"" << Qt::endl 0554 << Qt::endl 0555 0556 << "#include <kdev-pg-char-sets.h>" << Qt::endl 0557 << "#include <kdev-pg-token-stream.h>" << Qt::endl 0558 << Qt::endl; 0559 0560 foreach (const QString& header, globalSystem.lexerDeclarationHeaders) 0561 s << "#include \"" << header << "\"\n"; 0562 0563 s << Qt::endl << "namespace " << globalSystem.ns << "{" << Qt::endl 0564 << Qt::endl 0565 0566 << "class " << globalSystem.exportMacro << " " << globalSystem.tokenStream << " : " 0567 << (globalSystem.lexerBaseClass.isEmpty() ? QString() : " public " + globalSystem.lexerBaseClass + ",") 0568 << "public " << globalSystem.inputStream << "," 0569 << "public TokenTypeWrapper" << Qt::endl 0570 << "{" << Qt::endl 0571 << "public:" << Qt::endl 0572 << "typedef " << (globalSystem.lexerBaseClass.isEmpty() ? globalSystem.tokenStream : globalSystem.lexerBaseClass) << " Base;" << Qt::endl 0573 << "typedef " << globalSystem.inputStream << " Iterator;" << Qt::endl << Qt::endl << "private:" << Qt::endl; 0574 0575 0576 if(hasStates) 0577 { 0578 foreach(QString state, globalSystem.lexerEnvs.keys()) 0579 s << "Base::Token& lex" << KDevPG::capitalized(state) << "();" << Qt::endl; 0580 s << "public:\nenum RuleSet {\n"; 0581 foreach(QString state, globalSystem.lexerEnvs.keys()) 0582 s << "State_" << state << ", /*" << globalSystem.lexerEnvs[state].size() << "*/" << Qt::endl; 0583 s << "State_COUNT\n};\n" 0584 "private:\n" 0585 "RuleSet m_ruleSet;\n" 0586 "public:\n" 0587 "inline RuleSet ruleSet()\n{\nreturn m_ruleSet;\n}\n" 0588 "void setRuleSet(RuleSet rs);\n"; 0589 foreach(QString state, globalSystem.lexerEnvs.keys()) 0590 { 0591 s << "inline void enteringRuleSet" << state << "();" << Qt::endl; 0592 s << "inline void leavingRuleSet" << state << "();" << Qt::endl; 0593 } 0594 } 0595 0596 s << "Iterator::PlainIterator spos;" << Qt::endl 0597 << "bool continueLexeme;" << Qt::endl << Qt::endl 0598 0599 << "public:" << Qt::endl << globalSystem.tokenStream << "(const Iterator& iter);" << Qt::endl 0600 // non-virtual, virtuality will be inherited 0601 << "~" << globalSystem.tokenStream << "();" 0602 << Qt::endl << "Base::Token& read();" << Qt::endl; 0603 0604 /// TODO: not good that it happens in a separate file for the parser but in this file for the lexer 0605 #define LEXER_EXTRA_CODE_GEN(name) \ 0606 if (globalSystem.lexerclassMembers.name.empty() == false) \ 0607 { \ 0608 s << "\n// user defined code:" << Qt::endl; \ 0609 GenerateMemberCode gen(s, Settings::MemberItem::PublicDeclaration \ 0610 | Settings::MemberItem::ProtectedDeclaration \ 0611 | Settings::MemberItem::PrivateDeclaration \ 0612 | Settings::MemberItem::ConstructorCode \ 0613 | Settings::MemberItem::DestructorCode); \ 0614 for( auto it = globalSystem.lexerclassMembers.name.begin(); \ 0615 it != globalSystem.lexerclassMembers.name.end(); ++it ) \ 0616 { \ 0617 gen(*it); \ 0618 } \ 0619 } 0620 0621 LEXER_EXTRA_CODE_GEN(declarations) 0622 0623 s << "};" << Qt::endl << Qt::endl << "} // end of namespace " << globalSystem.ns << Qt::endl 0624 << Qt::endl 0625 0626 << "#endif" << Qt::endl 0627 << Qt::endl; 0628 0629 QString oname = globalSystem.language; 0630 oname += "lexer.h"; 0631 0632 format(s, oname); 0633 0634 } 0635 { // generate the lexer bits 0636 QString str; 0637 QTextStream s(&str, QIODevice::WriteOnly); 0638 0639 s << "// THIS FILE IS GENERATED" << Qt::endl 0640 << "// WARNING! All changes made in this file will be lost!" << Qt::endl 0641 << Qt::endl 0642 0643 << "#include \"" << globalSystem.language << "lexer.h\"" << Qt::endl 0644 << Qt::endl; 0645 0646 foreach (const QString& header, globalSystem.lexerBitsHeaders) 0647 s << "#include \"" << header << "\"\n"; 0648 0649 s << "\n#include <cassert>\n"; 0650 0651 s << Qt::endl << "namespace " << globalSystem.ns << "{" << Qt::endl 0652 << Qt::endl << globalSystem.tokenStream << "::" << globalSystem.tokenStream 0653 << "(const " << globalSystem.tokenStream << "::Iterator& iter) : Base(), Iterator(iter), " << (hasStates ? "m_ruleSet(State_start), " : "") << "continueLexeme(false)" << Qt::endl 0654 << "{"; 0655 LEXER_EXTRA_CODE_GEN(constructorCode) 0656 s << "}" << Qt::endl << Qt::endl 0657 << globalSystem.tokenStream << "::~" << globalSystem.tokenStream 0658 << "()\n{"; 0659 LEXER_EXTRA_CODE_GEN(destructorCode) 0660 s << "}" << Qt::endl << Qt::endl 0661 0662 << "#define PP_CONCAT_IMPL(x, y) x ## y\n" // necessary, otherwise CURRENT_RULE_SET would not get resolved 0663 "#define PP_CONCAT(x, y) PP_CONCAT_IMPL(x, y)\n\n" 0664 0665 "#define lxCURR_POS (Iterator::plain())\n" 0666 "#define lxCURR_IDX (Iterator::plain() - Iterator::begin())\n" 0667 "#define lxCONTINUE {continueLexeme = true; return read();}\n" 0668 "#define lxLENGTH (Iterator::plain() - Iterator::begin())\n" 0669 "#define lxBEGIN_POS (spos)\n" 0670 "#define lxBEGIN_IDX (spos - Iterator::begin())\n" 0671 "#define lxNAMED_TOKEN(token, X) KDevPG::Token& token(Base::push()); token.kind = Token_##X; token.begin = lxBEGIN_IDX; token.end = lxCURR_IDX - 1;\n" 0672 "#define lxTOKEN(X) {lxNAMED_TOKEN(token, X);}\n" 0673 "#define lxDONE {return Base::read();}\n" 0674 "#define lxRETURN(X) {lxTOKEN(X); lxDONE}\n" 0675 "#define lxEOF {Base::Token& _t(Base::push()); _t.kind = Token_EOF;_t.begin = _t.end = Iterator::plain() - Iterator::begin();}\n" 0676 "#define lxFINISH {lxEOF lxDONE}\n" 0677 "#define yytoken (Base::back())\n" 0678 "#define lxFAIL {goto _fail;}\n" 0679 "#define lxSKIP {return read();}\n" 0680 "#define lxNEXT_CHR(chr) { if(!Iterator::hasNext()) goto _end; chr = Iterator::next(); }\n" << Qt::endl; 0681 0682 if(hasStates) 0683 { 0684 s << "#define lxSET_RULE_SET(r) {PP_CONCAT(leavingRuleSet, CURRENT_RULE_SET) (); m_ruleSet = State_##r; enteringRuleSet##r ();}\n" << Qt::endl << Qt::endl; 0685 0686 foreach(QString state, globalSystem.lexerEnvs.keys()) 0687 { 0688 s << "inline void " << globalSystem.tokenStream << "::enteringRuleSet" << state << "() { " << globalSystem.enteringCode[state] << "}" << Qt::endl; 0689 s << "inline void " << globalSystem.tokenStream << "::leavingRuleSet" << state << "() { " << globalSystem.leavingCode[state] << "}" << Qt::endl; 0690 } 0691 s << "\n" 0692 "void " << globalSystem.tokenStream << "::setRuleSet(RuleSet rs)\n" 0693 "{\n" 0694 "switch(m_ruleSet)\n" 0695 "{\n"; 0696 foreach(QString state, globalSystem.lexerEnvs.keys()) 0697 { 0698 s << "case State_" << state << ":\n" 0699 "leavingRuleSet" << state << "();\n" 0700 "break;\n"; 0701 } 0702 s << "\ndefault:\n" 0703 "assert(0 == \"Invalid rule set\");\n" 0704 "}\n\n" 0705 "m_ruleSet = rs;\n\n" 0706 "switch(m_ruleSet)\n" 0707 "{\n"; 0708 foreach(QString state, globalSystem.lexerEnvs.keys()) 0709 { 0710 s << "case State_" << state << ":\n" 0711 "enteringRuleSet" << state << "();\n" 0712 "break;\n"; 0713 } 0714 s << "\ndefault:\n" 0715 "assert(0 == \"Invalid rule set\");\n" 0716 "}\n" 0717 "}\n\n"; 0718 } 0719 0720 #define LEXER_CORE_IMPL(name, state, extra) \ 0721 s << globalSystem.tokenStream << "::Base::Token& " << globalSystem.tokenStream << "::" \ 0722 << name << "()" << Qt::endl << "{" \ 0723 << extra << "if(!Iterator::hasNext())\n{\nlxFINISH\n}" << Qt::endl \ 0724 << "if(continueLexeme) continueLexeme = false;\nelse spos = plain();\nIterator::PlainIterator lpos = Iterator::plain();\nIterator::Int chr = 0;\nint lstate = 0;\n"; \ 0725 globalSystem.dfaForNfa[globalSystem.lexerEnvResults[state]]->codegen(s); \ 0726 s << "/* assert(false);*/\nreturn Base::read();}" << Qt::endl << Qt::endl; 0727 0728 if(hasStates) 0729 { 0730 foreach(QString state, globalSystem.lexerEnvs.keys()) 0731 { 0732 s << "#define CURRENT_RULE_SET " << state << Qt::endl; 0733 LEXER_CORE_IMPL("lex" + KDevPG::capitalized(state), state, "") 0734 s << "#undef CURRENT_RULE_SET" << Qt::endl; 0735 } 0736 s << globalSystem.tokenStream << "::Base::Token& " << globalSystem.tokenStream 0737 << "::read()" << Qt::endl << "{" << Qt::endl << "if(Base::index() < Base::size())\nreturn Base::read();\nswitch(m_ruleSet)\n{" << Qt::endl; 0738 foreach(QString state, globalSystem.lexerEnvs.keys()) 0739 s << "case State_" << state << ": return lex" << capitalized(state) << "();" << Qt::endl; 0740 s << "default:\nexit(-1);\n}\n}" << Qt::endl; 0741 } 0742 else 0743 { 0744 LEXER_CORE_IMPL("read", "start", "if(Base::index() < Base::size())\nreturn Base::read();\n") 0745 } 0746 0747 s << globalSystem.lexerBits << Qt::endl; 0748 0749 if(hasStates) 0750 { 0751 s << "#undef lxSET_RULE_SET\n" << Qt::endl; 0752 } 0753 0754 s << "#undef lxNEXT_CHR\n" 0755 "#undef lxFAIl\n" 0756 "#undef lxRETURN\n" 0757 "#undef lxTOKEN\n" 0758 "#undef lxBEGIN_IDX\n" 0759 "#undef lxBEGIN_POS\n" 0760 "#undef lxLENGTH\n" 0761 "#undef lxCONTINUE\n" 0762 "#undef lxCURR_IDX\n" 0763 "#undef lxCURR_POS\n\n" 0764 0765 "#undef PP_CONCAT\n" 0766 "#undef PP_CONCAT_IMPL\n" << Qt::endl; 0767 0768 s << "} // end of namespace " << globalSystem.ns << Qt::endl << Qt::endl; 0769 0770 QString oname = globalSystem.language; 0771 oname += "lexer.cpp"; 0772 0773 format(s, oname); 0774 } 0775 } 0776 0777 void generateVisitor(const QString& name, bool inherit_default) 0778 { 0779 QByteArray language = globalSystem.language.toUpper().toLatin1(); 0780 for(int i = 0; i != language.size(); ++i) 0781 { 0782 if(language[i] < '0' || (language[i] > '9' && language[i] < 'A') || language[i] > 'Z') 0783 language[i] = '_'; 0784 } 0785 QByteArray upper_name = name.toUpper().toLatin1(); 0786 0787 { 0788 QString str; 0789 QTextStream s(&str, QIODevice::WriteOnly); 0790 0791 s << "#ifndef " << language << "_" << upper_name << "_H" << Qt::endl 0792 << "#define " << language << "_" << upper_name << "_H" << Qt::endl 0793 << Qt::endl 0794 0795 << "#include \"" << globalSystem.language << (inherit_default ? "default" : "") << "visitor.h\"" << Qt::endl 0796 << Qt::endl; 0797 0798 if (!globalSystem.exportMacroHeader.isEmpty()) 0799 s << "#include \"" << globalSystem.exportMacroHeader << "\"" 0800 << Qt::endl; 0801 0802 s << "namespace " << globalSystem.ns << "{" << Qt::endl << Qt::endl; 0803 0804 if (inherit_default) 0805 { // generate an empty visitor using the default-visitor 0806 0807 GenerateNewVisitor visitor(s, name); 0808 0809 visitor(); 0810 } 0811 else 0812 { // generate a visitor like the default visitor 0813 0814 GenerateDefaultVisitor visitor(s, name); 0815 0816 visitor(); 0817 } 0818 0819 s << Qt::endl << "} // end of namespace " << globalSystem.ns << Qt::endl 0820 << Qt::endl 0821 0822 << "#endif" << Qt::endl 0823 << Qt::endl; 0824 0825 QString oname = globalSystem.language; 0826 oname += name.toLower() + ".h"; 0827 0828 format(s, oname); 0829 } 0830 0831 { 0832 QString str; 0833 QTextStream s(&str, QIODevice::WriteOnly); 0834 0835 s << "#include \"" << globalSystem.language << "defaultvisitor.h\"" << Qt::endl 0836 << Qt::endl 0837 0838 << "namespace " << globalSystem.ns << "{" << Qt::endl 0839 0840 << Qt::endl; 0841 0842 if(inherit_default) 0843 { 0844 GenerateNewVisitorBitsRule gen(s, name); 0845 for( World::SymbolSet::iterator it = globalSystem.symbols.begin(); 0846 it != globalSystem.symbols.end(); ++it ) 0847 { 0848 gen(qMakePair(it.key(), *it)); 0849 } 0850 } 0851 else 0852 { 0853 GenerateDefaultVisitorBitsRule gen(s, name); 0854 for( World::SymbolSet::iterator it = globalSystem.symbols.begin(); 0855 it != globalSystem.symbols.end(); ++it ) 0856 { 0857 gen(qMakePair(it.key(), *it)); 0858 } 0859 } 0860 0861 s << Qt::endl << "} // end of namespace " << globalSystem.ns << Qt::endl 0862 << Qt::endl; 0863 0864 QString oname = globalSystem.language; 0865 oname += name.toLower() + ".cpp"; 0866 0867 format(s, oname); 0868 } 0869 0870 } 0871 0872 } 0873 0874