File indexing completed on 2024-04-28 05:49:16

0001 /***************************************************************************
0002                       fortran_parser.cpp  -  description
0003                              -------------------
0004     begin                : jul 10 2005
0005     author               : 2005 Roberto Quitiliani
0006     email                : roby(dot)q(AT)tiscali(dot)it
0007  ***************************************************************************/
0008 /***************************************************************************
0009  *                                                                         *
0010  *   SPDX-License-Identifier: GPL-2.0-or-later
0011  *                                                                         *
0012  ***************************************************************************/
0013 
0014 #include "plugin_katesymbolviewer.h"
0015 
0016 void KatePluginSymbolViewerView::parseFortranSymbols(void)
0017 {
0018     if (!m_mainWindow->activeView()) {
0019         return;
0020     }
0021 
0022     QString subrStr(QStringLiteral("subroutine "));
0023     QString funcStr(QStringLiteral("function "));
0024     QString modStr(QStringLiteral("module "));
0025 
0026     QString stripped;
0027     int fnd, block = 0, blockend = 0, paro = 0, parc = 0;
0028     bool mainprog;
0029 
0030     QTreeWidgetItem *node = nullptr;
0031     QTreeWidgetItem *subrNode = nullptr, *funcNode = nullptr, *modNode = nullptr;
0032     QTreeWidgetItem *lastSubrNode = nullptr, *lastFuncNode = nullptr, *lastModNode = nullptr;
0033 
0034     // It is necessary to change names
0035     m_macro->setText(i18n("Show Subroutines"));
0036     m_struct->setText(i18n("Show Modules"));
0037     m_func->setText(i18n("Show Functions"));
0038 
0039     if (m_treeOn->isChecked()) {
0040         funcNode = new QTreeWidgetItem(m_symbols, QStringList(i18n("Functions")));
0041         subrNode = new QTreeWidgetItem(m_symbols, QStringList(i18n("Subroutines")));
0042         modNode = new QTreeWidgetItem(m_symbols, QStringList(i18n("Modules")));
0043         funcNode->setIcon(0, m_icon_function);
0044         modNode->setIcon(0, m_icon_block);
0045         subrNode->setIcon(0, m_icon_context);
0046 
0047         if (m_expandOn->isChecked()) {
0048             m_symbols->expandItem(funcNode);
0049             m_symbols->expandItem(subrNode);
0050             m_symbols->expandItem(modNode);
0051         }
0052 
0053         lastSubrNode = subrNode;
0054         lastFuncNode = funcNode;
0055         lastModNode = modNode;
0056         m_symbols->setRootIsDecorated(1);
0057     } else {
0058         m_symbols->setRootIsDecorated(0);
0059     }
0060 
0061     KTextEditor::Document *kDoc = m_mainWindow->activeView()->document();
0062 
0063     for (int i = 0; i < kDoc->lines(); i++) {
0064         QString currline = kDoc->line(i);
0065         currline = currline.trimmed();
0066         // currline = currline.simplified(); is this really needed ?
0067         // Fortran is case insensitive
0068         currline = currline.toLower();
0069         bool comment = false;
0070         // kdDebug(13000)<<currline<<endl;
0071         if (currline.isEmpty()) {
0072             continue;
0073         }
0074         if (currline.at(0) == QLatin1Char('!') || currline.at(0) == QLatin1Char('c')) {
0075             comment = true;
0076         }
0077         // block=0;
0078 
0079         mainprog = false;
0080 
0081         if (!comment) {
0082             // Subroutines
0083             if (currline.startsWith(subrStr) || currline.startsWith(QLatin1String("program "))) {
0084                 block = 1;
0085                 stripped.clear();
0086             }
0087             // Modules
0088             else if (currline.startsWith(modStr)) {
0089                 block = 2;
0090                 stripped.clear();
0091             }
0092             // Functions
0093             else if ((((currline.startsWith(QLatin1String("real")) || currline.startsWith(QLatin1String("double"))
0094                         || currline.startsWith(QLatin1String("integer")) || currline.startsWith(QLatin1String("character")))
0095                        || currline.startsWith(QLatin1String("logical")) || currline.startsWith(QLatin1String("pure"))
0096                        || currline.startsWith(QLatin1String("elemental")) || currline.startsWith(QLatin1String("recursive"))
0097                        || currline.startsWith(QLatin1String("type")))
0098                       && currline.indexOf(funcStr) > 0)
0099                      || currline.startsWith(funcStr)) {
0100                 block = 3;
0101                 stripped.clear();
0102             }
0103 
0104             // Subroutines
0105             if (block == 1) {
0106                 if (currline.startsWith(QLatin1String("program "))) {
0107                     mainprog = true;
0108                 }
0109                 if (m_macro->isChecked()) // not really a macro, but a subroutines
0110                 {
0111                     stripped += QStringView(currline).right(currline.length());
0112                     stripped = stripped.simplified();
0113                     stripped.remove(QLatin1Char('*'));
0114                     stripped.remove(QLatin1Char('+'));
0115                     stripped.remove(QLatin1Char('$'));
0116                     if (blockend == 0) {
0117                         fnd = stripped.indexOf(QLatin1Char(' '));
0118                         stripped = currline.right(currline.length() - fnd - 1);
0119                     }
0120                     stripped.remove(QLatin1Char(' '));
0121                     fnd = stripped.indexOf(QLatin1Char('!'));
0122                     if (fnd > 0) {
0123                         stripped.truncate(fnd);
0124                     }
0125                     paro += currline.count(QLatin1Char(')'), Qt::CaseSensitive);
0126                     parc += currline.count(QLatin1Char('('), Qt::CaseSensitive);
0127 
0128                     if ((paro == parc || mainprog) && stripped.endsWith(QLatin1Char('&'), Qt::CaseInsensitive) == false) {
0129                         stripped.remove(QLatin1Char('&'));
0130                         if (mainprog && stripped.indexOf(QLatin1Char('(')) < 0 && stripped.indexOf(QLatin1Char(')')) < 0) {
0131                             stripped.prepend(QLatin1String("Main: "));
0132                         }
0133                         if (stripped.indexOf(QLatin1Char('=')) == -1) {
0134                             if (m_treeOn->isChecked()) {
0135                                 node = new QTreeWidgetItem(subrNode, lastSubrNode);
0136                                 lastSubrNode = node;
0137                             } else {
0138                                 node = new QTreeWidgetItem(m_symbols);
0139                             }
0140                             node->setText(0, stripped);
0141                             node->setIcon(0, m_icon_context);
0142                             node->setText(1, QString::number(i, 10));
0143                         }
0144                         stripped.clear();
0145                         block = 0;
0146                         blockend = 0;
0147                         paro = 0;
0148                         parc = 0;
0149                     } else {
0150                         blockend = 1;
0151                     }
0152                 }
0153             }
0154 
0155             // Modules
0156             else if (block == 2) {
0157                 if (m_struct->isChecked()) // not really a struct, but a module
0158                 {
0159                     stripped = currline.right(currline.length());
0160                     stripped = stripped.simplified();
0161                     fnd = stripped.indexOf(QLatin1Char(' '));
0162                     stripped = currline.right(currline.length() - fnd - 1);
0163                     fnd = stripped.indexOf(QLatin1Char('!'));
0164                     if (fnd > 0) {
0165                         stripped.truncate(fnd);
0166                     }
0167                     if (stripped.indexOf(QLatin1Char('=')) == -1) {
0168                         if (m_treeOn->isChecked()) {
0169                             node = new QTreeWidgetItem(modNode, lastModNode);
0170                             lastModNode = node;
0171                         } else {
0172                             node = new QTreeWidgetItem(m_symbols);
0173                         }
0174                         node->setText(0, stripped);
0175                         node->setIcon(0, m_icon_context);
0176                         node->setText(1, QString::number(i, 10));
0177                     }
0178                     stripped.clear();
0179                 }
0180                 block = 0;
0181                 blockend = 0;
0182             }
0183 
0184             // Functions
0185             else if (block == 3) {
0186                 if (m_func->isChecked()) {
0187                     stripped += QStringView(currline).right(currline.length());
0188                     stripped = stripped.trimmed();
0189                     stripped.remove(QLatin1String("function"));
0190                     stripped.remove(QLatin1Char('*'));
0191                     stripped.remove(QLatin1Char('+'));
0192                     stripped.remove(QLatin1Char('$'));
0193                     stripped = stripped.simplified();
0194                     fnd = stripped.indexOf(QLatin1Char('!'));
0195                     if (fnd > 0) {
0196                         stripped.truncate(fnd);
0197                     }
0198                     stripped = stripped.trimmed();
0199                     paro += currline.count(QLatin1Char(')'), Qt::CaseSensitive);
0200                     parc += currline.count(QLatin1Char('('), Qt::CaseSensitive);
0201 
0202                     if (paro == parc && stripped.endsWith(QLatin1Char('&')) == false) {
0203                         stripped.remove(QLatin1Char('&'));
0204                         if (m_treeOn->isChecked()) {
0205                             node = new QTreeWidgetItem(funcNode, lastFuncNode);
0206                             lastFuncNode = node;
0207                         } else {
0208                             node = new QTreeWidgetItem(m_symbols);
0209                         }
0210                         node->setText(0, stripped);
0211                         node->setIcon(0, m_icon_function);
0212                         node->setText(1, QString::number(i, 10));
0213                         stripped.clear();
0214                         block = 0;
0215                         paro = 0;
0216                         parc = 0;
0217                     }
0218                     blockend = 0;
0219                 }
0220             }
0221         }
0222     } // for i loop
0223 }