File indexing completed on 2024-04-14 04:31:38
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.h" 0022 #include "kdev-pg-ast.h" 0023 0024 namespace KDevPG 0025 { 0026 0027 Model::ZeroItem *zero() 0028 { 0029 Model::ZeroItem *node = createNode<Model::ZeroItem>(); 0030 return node; 0031 } 0032 0033 Model::PlusItem *plus(Model::Node *item) 0034 { 0035 Model::PlusItem *node = createNode<Model::PlusItem>(); 0036 node->mItem = item; 0037 return node; 0038 } 0039 0040 Model::StarItem *star(Model::Node *item) 0041 { 0042 Model::StarItem *node = createNode<Model::StarItem>(); 0043 node->mItem = item; 0044 return node; 0045 } 0046 0047 Model::SymbolItem *symbol(const QString& name) 0048 { 0049 Model::SymbolItem *node = createNode<Model::SymbolItem>(); 0050 node->mName = name; 0051 node->mCapitalizedName = name; 0052 capitalize(node->mCapitalizedName); 0053 return node; 0054 } 0055 0056 Model::ActionItem *action(Model::Node *item, const QString& code) 0057 { 0058 Model::ActionItem *node = createNode<Model::ActionItem>(); 0059 node->mItem = item; 0060 node->mCode = code; 0061 return node; 0062 } 0063 0064 Model::AlternativeItem *alternative(Model::Node *left, Model::Node *right) 0065 { 0066 Model::AlternativeItem *node = createNode<Model::AlternativeItem>(); 0067 node->mLeft = left; 0068 node->mRight = right; 0069 return node; 0070 } 0071 0072 Model::ConsItem *cons(Model::Node *left, Model::Node *right) 0073 { 0074 Model::ConsItem *node = createNode<Model::ConsItem>(); 0075 node->mLeft = left; 0076 node->mRight = right; 0077 return node; 0078 } 0079 0080 Model::EvolveItem *evolve( 0081 Model::Node *item, Model::SymbolItem *symbol, 0082 Model::VariableDeclarationItem *declarations, const QString& code) 0083 { 0084 Model::EvolveItem *node = createNode<Model::EvolveItem>(); 0085 node->mItem = item; 0086 node->mSymbol = symbol; 0087 node->mDeclarations = declarations; 0088 node->mCode = code; 0089 return node; 0090 } 0091 0092 Model::TryCatchItem *tryCatch(Model::Node *try_item, Model::Node *catch_item) 0093 { 0094 Model::TryCatchItem *node = createNode<Model::TryCatchItem>(); 0095 node->mTryItem = try_item; 0096 node->mCatchItem = catch_item; 0097 node->mUnsafe = false; 0098 return node; 0099 } 0100 0101 Model::AliasItem *alias(const QString& code, Model::SymbolItem *symbol) 0102 { 0103 Model::AliasItem *node = createNode<Model::AliasItem>(); 0104 node->mCode = code; 0105 node->mSymbol = symbol; 0106 return node; 0107 } 0108 0109 Model::TerminalItem *terminal(const QString& name, const QString& description) 0110 { 0111 Model::TerminalItem *node = createNode<Model::TerminalItem>(); 0112 node->mName = name; 0113 node->mDescription = description; 0114 return node; 0115 } 0116 0117 Model::NonTerminalItem *nonTerminal(Model::SymbolItem *symbol, const QString& arguments) 0118 { 0119 Model::NonTerminalItem *node = createNode<Model::NonTerminalItem>(); 0120 node->mSymbol = symbol; 0121 node->mArguments = arguments; 0122 return node; 0123 } 0124 0125 Model::InlinedNonTerminalItem* inlinedNonTerminal(Model::SymbolItem* symbol) 0126 { 0127 Model::InlinedNonTerminalItem *node = createNode<Model::InlinedNonTerminalItem>(); 0128 node->mSymbol = symbol; 0129 return node; 0130 } 0131 0132 Model::AnnotationItem *annotation( 0133 const QString& name, Model::Node *item, bool isSequence, 0134 Model::VariableDeclarationItem::StorageType storageType) 0135 { 0136 Model::AnnotationItem *node = createNode<Model::AnnotationItem>(); 0137 node->mItem = item; 0138 0139 Model::VariableDeclarationItem::VariableType variableType; 0140 QString type; 0141 0142 if (Model::TerminalItem *t = nodeCast<Model::TerminalItem*>(item)) 0143 { 0144 variableType = Model::VariableDeclarationItem::TypeToken; 0145 type = t->mName; 0146 } 0147 else if (Model::NonTerminalItem *nt = nodeCast<Model::NonTerminalItem*>(item)) 0148 { 0149 variableType = Model::VariableDeclarationItem::TypeNode; 0150 type = nt->mSymbol->mName; 0151 } 0152 else 0153 { 0154 variableType = Model::VariableDeclarationItem::TypeVariable; // has to be set to something, or compiler gives a warning 0155 qFatal("Item must either be a terminal or a non-terminal"); 0156 Q_ASSERT(0); // ### item must either be a terminal or a nonTerminal 0157 } 0158 0159 node->mDeclaration = 0160 variableDeclaration(Model::VariableDeclarationItem::DeclarationLocal, 0161 storageType, variableType, isSequence, name, type); 0162 return node; 0163 } 0164 0165 Model::ConditionItem *condition(const QString& code, Model::Node *item) 0166 { 0167 Model::ConditionItem *node = createNode<Model::ConditionItem>(); 0168 node->mCode = code; 0169 node->mItem = item; 0170 return node; 0171 } 0172 0173 Model::VariableDeclarationItem *variableDeclaration( 0174 Model::VariableDeclarationItem::DeclarationType declarationType, 0175 Model::VariableDeclarationItem::StorageType storageType, 0176 Model::VariableDeclarationItem::VariableType variableType, 0177 bool isSequence, const QString& name, const QString& type) 0178 { 0179 Model::VariableDeclarationItem *node = createNode<Model::VariableDeclarationItem>(); 0180 node->mName = name; 0181 node->mType = type; 0182 node->mCapitalizedType = type; 0183 capitalize(node->mCapitalizedType); 0184 node->mDeclarationType = declarationType; 0185 node->mStorageType = storageType; 0186 node->mVariableType = variableType; 0187 node->mIsSequence = isSequence; 0188 node->mNext = nullptr; 0189 return node; 0190 } 0191 0192 Settings::MemberItem *member(Settings::MemberItem::MemberKind kind, const QString& code) 0193 { 0194 Settings::MemberItem *node = createNode<Settings::MemberItem>(); 0195 node->mMemberKind = kind; 0196 node->mCode = code; 0197 return node; 0198 } 0199 0200 QString unescaped(const QByteArray& str) 0201 { 0202 QString ret; 0203 int cnt = 0; 0204 for(auto i = str.begin(); i < str.end(); ++i) 0205 { 0206 if(cnt++ != 0) 0207 { 0208 } 0209 if(*i == '\\') 0210 { 0211 char nxt = *++i; 0212 if(nxt == 'n') 0213 ret += '\n'; 0214 else if(nxt == 't') 0215 ret += '\t'; 0216 else if(nxt == 'f') 0217 ret += '\f'; 0218 else if(nxt == 'v') 0219 ret += '\v'; 0220 else if(nxt == 'r') 0221 ret += '\r'; 0222 else if(nxt == '0') 0223 ret += '\0'; 0224 else if(nxt == 'b') 0225 ret += '\b'; 0226 else if(nxt == 'a') 0227 ret += '\a'; 0228 else if(nxt == 'x' || nxt == 'X' || nxt == 'u' || nxt == 'U') 0229 { 0230 quint32 x = 0; 0231 for(++i; ; ++i) 0232 { 0233 x *= 16; 0234 if(i == str.end()) 0235 break; 0236 else if(*i >= 'a' && *i <= 'f') 0237 x += (*i - 'a' + 10); 0238 else if(*i >= 'A' && *i <= 'F') 0239 x += (*i - 'A' + 10); 0240 else if(*i >= '0' && *i <= '9') 0241 x += (*i - '0'); 0242 else 0243 break; 0244 } 0245 --i; 0246 x /= 16; 0247 ret += QString::fromUcs4(&x, 1); 0248 } 0249 else if(nxt == 'd' || nxt == 'D') 0250 { 0251 quint32 x = 0; 0252 for(++i; ; ++i) 0253 { 0254 x *= 10; 0255 if(i == str.end()) 0256 break; 0257 else if(*i >= '0' && *i <= '9') 0258 x += (*i - '0'); 0259 else 0260 break; 0261 } 0262 --i; 0263 x /= 10; 0264 ret += QString::fromUcs4(&x, 1); 0265 } 0266 else if(nxt == 'o' || nxt == 'O') 0267 { 0268 quint32 x = 0; 0269 for(++i; ; ++i) 0270 { 0271 x *= 8; 0272 if(i == str.end()) 0273 break; 0274 else if(*i >= '0' && *i <= '7') 0275 x += (*i - '0'); 0276 else 0277 break; 0278 } 0279 --i; 0280 x /= 8; 0281 ret += QString::fromUcs4(&x, 1); 0282 } 0283 else if(nxt == 'y' || nxt == 'Y') 0284 { 0285 quint32 x = 0; 0286 for(++i; ; ++i) 0287 { 0288 x *= 2; 0289 if(i == str.end()) 0290 break; 0291 else if(*i >= '0' && *i <= '1') 0292 x += (*i - '0'); 0293 else 0294 break; 0295 } 0296 --i; 0297 x /= 2; 0298 ret += QString::fromUcs4(&x, 1); 0299 } 0300 else 0301 ret += nxt; 0302 } 0303 else 0304 ret += *i; 0305 } 0306 return ret; 0307 } 0308 0309 bool isOperatorSymbol(Model::SymbolItem *sym) 0310 { 0311 Model::EvolveItem *e = globalSystem.searchRule(sym); 0312 return e && e->mItem->kind == Model::OperatorItem::NodeKind; 0313 } 0314 0315 bool reducesToEpsilon(Model::Node *node, QSet<Model::Node*>& v) 0316 { 0317 if (node == nullptr) 0318 return true; 0319 if (v.contains(node)) 0320 return true; 0321 v.insert(node); 0322 if (Model::ConsItem *c = nodeCast<Model::ConsItem*>(node)) 0323 { 0324 return reducesToEpsilon(c->mLeft, v) && reducesToEpsilon(c->mRight, v); 0325 } 0326 else if (nodeCast<Model::OperatorItem*>(node)) 0327 { 0328 return false; 0329 } 0330 else if (Model::AlternativeItem *a = nodeCast<Model::AlternativeItem*>(node)) 0331 { 0332 return reducesToEpsilon(a->mLeft, v) || reducesToEpsilon(a->mRight, v); 0333 } 0334 else if (Model::ActionItem *a = nodeCast<Model::ActionItem*>(node)) 0335 { 0336 if(a->mItem) 0337 return reducesToEpsilon(a->mItem, v); 0338 else 0339 return true; 0340 } 0341 else if (Model::ConditionItem *c = nodeCast<Model::ConditionItem*>(node)) 0342 { 0343 return reducesToEpsilon(c->mItem, v); 0344 } 0345 else if (Model::TryCatchItem *t = nodeCast<Model::TryCatchItem*>(node)) 0346 { 0347 return reducesToEpsilon(t->mTryItem, v) 0348 || (t->mCatchItem && reducesToEpsilon(t->mCatchItem, v)); 0349 } 0350 else if (Model::AnnotationItem *a = nodeCast<Model::AnnotationItem*>(node)) 0351 { 0352 return reducesToEpsilon(a->mItem, v); 0353 } 0354 else if (Model::NonTerminalItem *n = nodeCast<Model::NonTerminalItem*>(node)) 0355 { 0356 return reducesToEpsilon(n->mSymbol, v); 0357 } 0358 else if (Model::InlinedNonTerminalItem *n = nodeCast<Model::InlinedNonTerminalItem*>(node)) 0359 { 0360 return reducesToEpsilon(n->mSymbol, v); 0361 } 0362 else if (Model::SymbolItem *s = nodeCast<Model::SymbolItem*>(node)) 0363 { 0364 return globalSystem.first(s).find(globalSystem.zero()) != globalSystem.first(s).end(); // hmm 0365 } 0366 else if (Model::PlusItem *p = nodeCast<Model::PlusItem*>(node)) 0367 { 0368 return reducesToEpsilon(p->mItem, v); 0369 } 0370 else if (nodeCast<Model::StarItem*>(node)) 0371 { 0372 return true; 0373 } 0374 else if (nodeCast<Model::ZeroItem*>(node)) 0375 { 0376 return true; 0377 } 0378 0379 return false; 0380 } 0381 0382 bool reducesToEpsilon(Model::Node *node) 0383 { 0384 QSet<Model::Node*> v; 0385 return reducesToEpsilon(node, v); 0386 } 0387 0388 bool isZero(Model::Node *node) 0389 { 0390 if (Model::ActionItem *a = nodeCast<Model::ActionItem*>(node)) 0391 { 0392 return isZero(a->mItem); 0393 } 0394 else if (Model::ConditionItem *c = nodeCast<Model::ConditionItem*>(node)) 0395 { 0396 return isZero(c->mItem); 0397 } 0398 else if (Model::AnnotationItem *a = nodeCast<Model::AnnotationItem*>(node)) 0399 { 0400 return isZero(a->mItem); 0401 } 0402 else if (Model::PlusItem *p = nodeCast<Model::PlusItem*>(node)) 0403 { 0404 return isZero(p->mItem); 0405 } 0406 else if (Model::StarItem *s = nodeCast<Model::StarItem*>(node)) 0407 { 0408 return isZero(s->mItem); 0409 } 0410 else if (nodeCast<Model::ZeroItem*>(node)) 0411 { 0412 return true; 0413 } 0414 0415 return false; 0416 } 0417 0418 0419 Model::Operator *makeOperator(Model::Node *tok, const QString& cond, const QString& code) 0420 { 0421 Model::Operator *op = new Model::Operator; 0422 op->mTok = tok; 0423 op->mCond = cond; 0424 op->mCode = code; 0425 return op; 0426 } 0427 0428 } 0429 0430 QTextStream& operator << (QTextStream& out, KDevPG::Model::Node const *__node) 0431 { 0432 KDevPG::Model::Node *node = const_cast<KDevPG::Model::Node*>(__node); 0433 0434 if (KDevPG::nodeCast<KDevPG::Model::ZeroItem*>(node)) 0435 return (out << "0"); 0436 else if (KDevPG::Model::SymbolItem *s = KDevPG::nodeCast<KDevPG::Model::SymbolItem *>(node)) 0437 return (out << s->mName); 0438 else if (KDevPG::Model::TerminalItem *t = KDevPG::nodeCast<KDevPG::Model::TerminalItem *>(node)) 0439 return (out << t->mName); 0440 else if (KDevPG::Model::AnnotationItem *a = KDevPG::nodeCast<KDevPG::Model::AnnotationItem *>(node)) 0441 return (out << ((a->mDeclaration->mIsSequence) ? "#" : "") 0442 << a->mDeclaration->mName 0443 << ((a->mDeclaration->mStorageType 0444 == KDevPG::Model::VariableDeclarationItem::StorageTemporary) ? ":" : "=") 0445 << a->mItem); 0446 #if 0 0447 0448 else 0449 if (Model::EvolveItem *e = nodeCast<Model::EvolveItem *>(node)) 0450 return (out << "evolve:" << e->mSymbol->mName); 0451 #endif 0452 0453 Q_ASSERT(0); 0454 return out; 0455 } 0456