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