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 }