File indexing completed on 2024-04-21 04:36:20
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) 2006 Alexander Dymo <adymo@kdevelop.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 #ifndef KDEV_PG_H 0023 #define KDEV_PG_H 0024 0025 #include "kdev-pg-ast.h" 0026 0027 #include <QSet> 0028 #include <QMap> 0029 #include <QList> 0030 #include <QFile> 0031 #include <QString> 0032 #include <QStringList> 0033 #include <QMultiMap> 0034 #include <QtGlobal> 0035 #include <QTextStream> 0036 0037 #include <vector> 0038 #include <algorithm> 0039 0040 namespace KDevPG 0041 { 0042 class GNFA; 0043 class GDFA; 0044 void deleteNFA(GNFA*); 0045 void deleteDFA(GDFA*); 0046 Model::ZeroItem *zero(); 0047 Model::PlusItem *plus(Model::Node *item); 0048 Model::StarItem *star(Model::Node *item); 0049 Model::SymbolItem *symbol(const QString& name); 0050 Model::ActionItem *action(Model::Node *item, const QString& code); 0051 Model::AlternativeItem *alternative(Model::Node *left, Model::Node *right); 0052 Model::ConsItem *cons(Model::Node *left, Model::Node *right); 0053 Model::EvolveItem *evolve( 0054 Model::Node *item, Model::SymbolItem *symbol, 0055 Model::VariableDeclarationItem *declarations, const QString& code 0056 ); 0057 Model::TryCatchItem *tryCatch(Model::Node *try_item, Model::Node *catch_item); 0058 Model::AliasItem *alias(const QString& code, Model::SymbolItem *symbol); 0059 Model::TerminalItem *terminal(const QString& name, const QString& description); 0060 Model::NonTerminalItem *nonTerminal(Model::SymbolItem *symbol, const QString& arguments); 0061 Model::InlinedNonTerminalItem *inlinedNonTerminal(Model::SymbolItem *symbol); 0062 Model::ConditionItem *condition(const QString& code, Model::Node *item); 0063 Model::AnnotationItem *annotation( 0064 const QString& name, Model::Node *item, bool isSequence, 0065 Model::VariableDeclarationItem::StorageType storageType 0066 ); 0067 Model::VariableDeclarationItem *variableDeclaration( 0068 Model::VariableDeclarationItem::DeclarationType declarationType, 0069 Model::VariableDeclarationItem::StorageType storageType, 0070 Model::VariableDeclarationItem::VariableType variableType, 0071 bool isSequence, const QString& name, const QString& type 0072 ); 0073 bool isOperatorSymbol(Model::SymbolItem *node); 0074 Settings::MemberItem *member(Settings::MemberItem::MemberKind kind, const QString& code); 0075 0076 Model::Operator *makeOperator(Model::Node *tok, const QString& cond, const QString& code); 0077 0078 inline void capitalize(QString& str) 0079 { 0080 if(!str.isEmpty()) 0081 str.replace(0, 1, str.at(0).toUpper()); 0082 } 0083 0084 inline QString capitalized(const QString& str) 0085 { 0086 QString ret(str); 0087 capitalize(ret); 0088 return ret; 0089 } 0090 0091 QString unescaped(const QByteArray& str); 0092 0093 class World 0094 { 0095 public: 0096 struct MemberCode { 0097 QList<Settings::MemberItem*> declarations; 0098 QList<Settings::MemberItem*> constructorCode; 0099 QList<Settings::MemberItem*> destructorCode; 0100 }; 0101 typedef QSet<Model::Node*> NodeSet; 0102 typedef QMap<QString, Model::SymbolItem*> SymbolSet; 0103 typedef QMap<QString, Model::TerminalItem*> TerminalSet; 0104 typedef QMultiMap<Model::SymbolItem*, Model::EvolveItem*> Environment; 0105 typedef QMultiMap<QString, QString> NamespaceSet; 0106 0107 typedef QMap<QPair<Model::Node*, int>, NodeSet> FirstSet; 0108 typedef QMap<QPair<Model::Node*, int>, NodeSet> FollowSet; 0109 0110 /**pair: list of rules whose FIRST set is used to calculate FOLLOW, 0111 list of rules whose FOLLOW set is used to calculate FOLLOW*/ 0112 typedef QPair<NodeSet, NodeSet> FollowDep; 0113 /**key: rule whose FOLLOW set has a dependency on other rules' FIRST and FOLLOW, 0114 value: follow set dependency*/ 0115 typedef QMap<Model::Node*, FollowDep> FollowDeps; 0116 0117 typedef QMap<QString, QString> AstBaseClasses; 0118 0119 World() 0120 : tokenStream("KDevPG::TokenStream"), language(), ns(), decl(), bits(), 0121 exportMacro(""), exportMacroHeader(), astCode(""), namespaceCode(""), 0122 inputStream("KDevPG::QUtf16ToUcs4Iterator"), 0123 generateAst(true), hasLexer(false), generateSerializeVisitor(false), 0124 generateDebugVisitor(false), generateTokenText(false), 0125 needStateManagement(false), needOperatorStack(false), 0126 lineNumberPolicy(FullLineNumbers), visitorTable(false), 0127 conflictHandling(Permissive), mZero(nullptr), 0128 lexerBaseClass("KDevPG::TokenStream") 0129 {} 0130 0131 ~World() 0132 { 0133 for(auto i = regexpById.begin(); i != regexpById.end(); ++i) 0134 deleteNFA(*i); 0135 for(auto i = lexerEnvResults.begin(); i != lexerEnvResults.end(); ++i) 0136 deleteNFA(*i); 0137 for(auto i = dfaForNfa.begin(); i != dfaForNfa.end(); ++i) 0138 deleteDFA(*i); 0139 } 0140 0141 // options 0142 QString tokenStream; 0143 QString language; 0144 QString ns; 0145 QString decl; 0146 QString bits; 0147 QString lexerBits; 0148 QString exportMacro; 0149 QString exportMacroHeader; 0150 QString astCode; 0151 QString namespaceCode; 0152 QStringList parserDeclarationHeaders; 0153 QStringList parserBitsHeaders; 0154 QStringList astHeaders; 0155 QStringList lexerDeclarationHeaders; 0156 QStringList lexerBitsHeaders; 0157 QString inputStream; 0158 bool generateAst: 1; 0159 bool hasLexer: 1; 0160 bool generateSerializeVisitor: 1; 0161 bool generateDebugVisitor: 1; 0162 bool generateTokenText: 1; 0163 bool needStateManagement: 1; 0164 bool needOperatorStack: 1; 0165 enum { BeautifulCode, CompatibilityLineNumbers, FullLineNumbers } lineNumberPolicy; 0166 bool beautifulCode: 1; 0167 bool visitorTable: 1; 0168 enum { Ignore = 0, Permissive = 1, Strict = 2 } conflictHandling: 2; 0169 0170 Model::ZeroItem *zero() 0171 { 0172 if (!mZero) 0173 mZero = KDevPG::zero(); 0174 return mZero; 0175 } 0176 0177 Model::TerminalItem *terminal(QString __name) 0178 { 0179 QString name = __name; 0180 TerminalSet::iterator it = terminals.find(name); 0181 if (it == terminals.end()) 0182 return KDevPG::terminal(__name, __name); 0183 0184 return (*it); 0185 } 0186 0187 void pushRule(Model::Node *rule) 0188 { 0189 Model::EvolveItem *e = nodeCast<Model::EvolveItem*>(rule); 0190 Q_ASSERT(e != nullptr); 0191 0192 rules.push_back(e); 0193 } 0194 0195 void pushParserClassMember(Model::Node *member) 0196 { 0197 Settings::MemberItem *m = nodeCast<Settings::MemberItem*>(member); 0198 Q_ASSERT(m != nullptr); 0199 0200 if (m->mMemberKind == Settings::MemberItem::ConstructorCode) 0201 parserclassMembers.constructorCode.push_back(m); 0202 else if (m->mMemberKind == Settings::MemberItem::DestructorCode) 0203 parserclassMembers.destructorCode.push_back(m); 0204 else // public, protected or private declaration 0205 parserclassMembers.declarations.push_back(m); 0206 } 0207 0208 void pushLexerClassMember(Model::Node *member) 0209 { 0210 Settings::MemberItem *m = nodeCast<Settings::MemberItem*>(member); 0211 Q_ASSERT(m != nullptr); 0212 0213 if (m->mMemberKind == Settings::MemberItem::ConstructorCode) 0214 lexerclassMembers.constructorCode.push_back(m); 0215 else if (m->mMemberKind == Settings::MemberItem::DestructorCode) 0216 lexerclassMembers.destructorCode.push_back(m); 0217 else // public, protected or private declaration 0218 lexerclassMembers.declarations.push_back(m); 0219 } 0220 0221 Model::TerminalItem *pushTerminal(QString __name, QString __description) 0222 { 0223 QString name = __name; 0224 TerminalSet::iterator it = terminals.find(name); 0225 if (it == terminals.end()) 0226 it = terminals.insert(name, KDevPG::terminal(__name, __description)); 0227 0228 return (*it); 0229 } 0230 0231 Model::SymbolItem *pushSymbol(QString __name) 0232 { 0233 QString name = __name; 0234 SymbolSet::iterator it = symbols.find(name); 0235 0236 if (it == symbols.end()) 0237 { 0238 it = symbols.insert(name, KDevPG::symbol(__name)); 0239 start.insert(*it); 0240 } 0241 else 0242 start.remove(*it); 0243 0244 return (*it); 0245 } 0246 0247 void pushParserDeclarationHeader(QString file) 0248 { 0249 parserDeclarationHeaders << file; 0250 } 0251 0252 void pushParserBitsHeader(QString file) 0253 { 0254 parserBitsHeaders << file; 0255 } 0256 0257 void pushAstHeader(QString file) 0258 { 0259 astHeaders << file; 0260 } 0261 0262 void pushLexerBitsHeader(QString file) 0263 { 0264 lexerBitsHeaders << file; 0265 } 0266 0267 void pushLexerDeclarationHeader(QString file) 0268 { 0269 lexerDeclarationHeaders << file; 0270 } 0271 0272 inline static bool ruleComp(Model::Node *a, Model::Node *b) 0273 { 0274 if(a != nullptr && a->kind == Model::NodeKindEvolve) 0275 a = ((Model::EvolveItem*)a)->mSymbol; 0276 if(b != nullptr && b->kind == Model::NodeKindEvolve) 0277 b = ((Model::EvolveItem*)b)->mSymbol; 0278 return a < b; 0279 } 0280 0281 void finishedParsing() 0282 { 0283 std::sort(rules.begin(), rules.end(), &ruleComp); 0284 } 0285 0286 Model::EvolveItem *searchRule(Model::SymbolItem *sym) 0287 { 0288 auto i = std::lower_bound(rules.begin(), rules.end(), sym, &ruleComp); 0289 if(i == rules.end() || (*i)->mSymbol != sym) 0290 return nullptr; 0291 return *i; 0292 } 0293 0294 FirstSet::iterator firstBegin() { return firstSet.begin(); } 0295 FirstSet::iterator firstEnd() { return firstSet.end(); } 0296 0297 FollowSet::iterator followBegin() { return followSet.begin(); } 0298 FollowSet::iterator followEnd() { return followSet.end(); } 0299 0300 NodeSet &first(Model::Node *node, int K = 1) 0301 { return firstSet[qMakePair(node, K)]; } 0302 0303 NodeSet &follow(Model::Node *node, int K = 1) 0304 { return followSet[qMakePair(node, K)]; } 0305 0306 FollowDep &followDep(Model::Node *node) 0307 { return followDeps[node]; } 0308 0309 FirstSet::iterator findInFirst(Model::Node *node, int K = 1) 0310 { return firstSet.find(qMakePair(node, K)); } 0311 0312 FollowSet::iterator findInFollow(Model::Node *node, int K = 1) 0313 { return followSet.find(qMakePair(node, K)); } 0314 0315 QSet<Model::SymbolItem*> start; 0316 Model::ZeroItem *mZero; 0317 0318 SymbolSet symbols; 0319 TerminalSet terminals; 0320 QList<Model::EvolveItem*> rules; 0321 MemberCode parserclassMembers, lexerclassMembers; 0322 AstBaseClasses astBaseClasses; 0323 QString parserBaseClass, lexerBaseClass; 0324 QMap<QString, vector<GNFA*> > lexerEnvs; 0325 QMap<QString, GNFA*> lexerEnvResults; 0326 QMap<QString, vector<QString> > lexerActions; 0327 QMap<QString, GNFA*> regexpById; 0328 QMap<QString, QString> enteringCode, leavingCode; 0329 QMap<GNFA*, GDFA*> dfaForNfa; 0330 0331 Environment env; 0332 0333 private: 0334 FirstSet firstSet; 0335 FollowSet followSet; 0336 FollowDeps followDeps; 0337 }; 0338 0339 0340 bool reducesToEpsilon(Model::Node *node); 0341 bool isZero(Model::Node *node); 0342 0343 extern KDevPG::World globalSystem; 0344 extern QFile file; 0345 0346 } 0347 QTextStream& operator << (QTextStream& out, KDevPG::Model::Node const *__node); 0348 0349 0350 #endif // KDEV_PG_H