KDevelop API Documentation

languages/perl/perlparser.cpp

Go to the documentation of this file.
00001 /*************************************************************************** 00002 perlparser.cpp - description 00003 ------------------- 00004 begin : Sun Nov 2 2003 00005 copyright : (C) 2003 by luc 00006 email : willems.luc(at)pandora.be 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include "perlparser.h" 00019 00020 #include <kdebug.h> 00021 #include <qfile.h> 00022 #include <qregexp.h> 00023 #include <qfileinfo.h> 00024 00025 perlparser::perlparser(KDevCore* core,CodeModel* model, QString interpreter) { 00026 m_core = core; 00027 m_model = model; 00028 m_interpreter=interpreter; 00029 //get INC paths for current installed perl 00030 getPerlINC(); 00031 00032 } 00033 00034 perlparser::~perlparser(){ 00035 } 00036 00037 const QStringList perlparser::UseFiles() 00038 { 00039 return m_usefiles; 00040 } 00041 00042 void perlparser::initialParse() { 00043 m_usefiles.clear(); 00044 } 00045 00046 void perlparser::parse(const QString &fileName){ 00047 QFile f(fileName); 00048 if (!f.open(IO_ReadOnly)) 00049 return; 00050 QTextStream stream(&f); 00051 QStringList list; 00052 QString rawline; 00053 while (!stream.eof()) { 00054 rawline = stream.readLine(); 00055 list.append(rawline.stripWhiteSpace().local8Bit()); 00056 } 00057 f.close(); 00058 kdDebug(9016) << "parsing " << fileName << endl; 00059 00060 m_file = m_model->create<FileModel>(); 00061 m_file->setName(fileName ); 00062 this->parseLines(&list,fileName); 00063 m_model->addFile( m_file ); 00064 } 00065 00066 void perlparser::parseLines(QStringList* lines,const QString &fileName) 00067 { 00068 QRegExp packagere("^[ \t]*package[ \t]+([+A-Za-z0-9_:]*).*\\;"); 00069 QRegExp basere("^[ \t]*use[ \t]+base[ \t]*\\(\'*\"*([A-Za-z0-9_:]*)"); 00070 QRegExp libre("^[ \t]*use[ \t]+lib[ \t]*\\(\'*\"*([A-Za-z0-9_:]*)"); 00071 QRegExp usere("^[ \t]*use[ \t]+([+A-Za-z0-9_:]*).*\\;"); 00072 QRegExp isare("^[ \t]*@ISA[ \t=qw\\(\'\"]*([A-Za-z0-9_: ]*)"); 00073 QRegExp globalre("^[ \t]*our[ \t]+\\(*([ \t,$%@*+A-Za-z0-9_]*)\\)*.*"); 00074 QRegExp myre("^[ \t]*my[ \t]+\\(*([ \t,$%@*+A-Za-z0-9_]*)\\)*.*"); 00075 QRegExp subre("^[ \t]*sub[ \t]+([A-Za-z0-9_]+)([A-Za-z0-9_]|([ \t]+[{])?)$"); 00076 QRegExp blessre("bless[ \t]*[\\( ]*([,$%@*+A-Za-z0-9_]*).*;"); 00077 QRegExp namere("^[ \t]*([$%@*])([A-Za-z0-9_]*).*$"); 00078 QRegExp privatere("^_([A-Za-z0-9_]*)"); 00079 QRegExp startpod("^=[a-z0-9]+ [a-z0-9]*"); 00080 QRegExp cutpod("^=cut"); 00081 00082 QString line; 00083 00084 //clear all "last" know things 00085 m_lastsub=""; 00086 m_lastattr=""; 00087 m_inpackage = false; 00088 m_inscript = false; 00089 m_inclass=false; 00090 00091 m_lastscript=0; 00092 m_lastpackage=0; 00093 m_lastclass=0; 00094 00095 int lineNo = -1; 00096 00097 bool inpod = false; 00098 bool endpod = false; 00099 00100 //check if we are parsing a script or module 00101 QFileInfo fi(fileName); 00102 bool inscript =(fi.extension() == "pl"); 00103 kdDebug(9016) << "inscript : " << inscript << "," << fi.extension() << endl; 00104 00105 if (inscript) { 00106 addScript(fileName,lineNo,fi.fileName()); 00107 } 00108 00109 for ( QStringList::Iterator it = lines->begin(); it != lines->end(); ++it ) { 00110 ++lineNo; 00111 line = (*it).local8Bit(); 00112 //empty line ? 00113 if (line.isEmpty()) { continue;} 00114 //some POD checking , quick and dirty but it seams to work 00115 if(inpod && endpod) { inpod=false; endpod=false;} 00116 //are we in pod documentation ? 00117 if (startpod.search(line)>=0) {inpod=true; continue;} 00118 //are we in pod documentation ? 00119 if (inpod) { endpod=( cutpod.search(line)>=0 ); continue; } 00120 00121 00122 //sub matching 00123 if (subre.search(line)>=0){ 00124 QString subname=subre.cap(1); 00125 kdDebug(9016) << "subre match [" << subname << "]" << endl; 00126 bool prive = privatere.search(subname) >= 0; 00127 kdDebug(9016) << "prive match [" << prive << "]" << endl; 00128 if (m_inscript) { addScriptSub(fileName,lineNo,subname,prive);} 00129 else { 00130 if (m_inclass) { addClassMethod(fileName,lineNo,subname,prive);} 00131 else { addPackageSub(fileName,lineNo,subname,prive);} 00132 } 00133 continue; 00134 } //sub 00135 00136 //our matching 00137 if (globalre.search(line)>=0) { 00138 //splitup multible ours 00139 QString varlist=globalre.cap(1); 00140 kdDebug(9016) << "globalre match [" << varlist <<"]" << endl; 00141 QStringList vars=QStringList::split(",",varlist); 00142 for ( QStringList::Iterator it = vars.begin(); it != vars.end(); ++it ) { 00143 if (namere.search(*it)>=0) { 00144 QString var = namere.cap(2); 00145 kdDebug(9016) << "namere match [" << var << "]" << endl; 00146 if (m_lastpackage) { addAttributetoPackage(fileName,lineNo,var); } 00147 else { addAttributetoScript(fileName,lineNo,var); } 00148 } 00149 } 00150 continue; 00151 } //globalre 00152 00153 00154 //bless matching 00155 if ((blessre.search(line)>=0) && (!m_inscript)) { 00156 kdDebug(9016) << "blessre match []" << endl; 00157 addClass(fileName,lineNo); 00158 addConstructor(fileName,lineNo,m_lastsub); 00159 continue; 00160 } //bless 00161 00162 //base matching 00163 if ((basere.search(line)>=0) && (!m_inscript)) { 00164 QString parent = basere.cap(1); 00165 //create child & parent classes 00166 kdDebug(9016) << "basere match [" << parent << "]" << endl; 00167 addClass(fileName,lineNo); 00168 addParentClass(parent); 00169 continue; 00170 } else { 00171 if (libre.search(line)>=0) { 00172 QString path = libre.cap(1); 00173 //add lib to INC path list 00174 kdDebug(9016) << "libre match [" << path << "]" << endl; 00175 m_INClist.append(path); 00176 continue; 00177 } else { 00178 if (usere.search(line)>=0) { 00179 //add lib to use list for later parsing 00180 QString lib = usere.cap(1); 00181 kdDebug(9016) << "usere match [" << lib << "]" << endl; 00182 addUseLib(lib); 00183 continue; 00184 } \ 00185 } 00186 } //base 00187 00188 if ((isare.search(line)>=0) && (!m_inscript)) { 00189 QString parent = isare.cap(1); 00190 //create child & parent classes 00191 kdDebug(9016) << "isare match [" << parent << "]" << endl; 00192 addClass(fileName,lineNo); 00193 addParentClass(parent); 00194 continue; 00195 } //isa 00196 00197 if ((packagere.search(line)>=0) && (!m_inscript)) { 00198 QString package=packagere.cap(1); 00199 kdDebug(9016) << "packagere match [" << package << "]" << endl; 00200 addPackage(fileName,lineNo,package); 00201 continue; 00202 }//package 00203 00204 } // for lines loop 00205 } 00206 00207 void perlparser::addPackage(const QString& fileName ,int lineNr , const QString& name) 00208 { 00209 kdDebug(9016) << "AddPackage [" << name << "]" << endl; 00210 NamespaceDom package = m_model->create<NamespaceModel>(); 00211 00212 package->setName(name); 00213 package->setFileName(fileName ); 00214 package->setStartPosition(lineNr, 0 ); 00215 package->setScope(name); 00216 00217 if (!m_file->hasNamespace(name)) { 00218 m_file->addNamespace(package); 00219 m_lastpackage=package; 00220 } else { 00221 kdDebug(9016) << "addPackage [" << name << " exist]" << endl; 00222 } 00223 00224 //clear all "last" know things 00225 m_lastpackagename=name; 00226 m_lastsub=""; 00227 m_lastattr=""; 00228 m_inpackage=true; 00229 m_inscript = false; 00230 m_inclass=false; 00231 00232 m_lastclass=0; 00233 m_lastscript=0; 00234 00235 } 00236 00237 void perlparser::addScript(const QString& fileName ,int lineNr ,const QString& name) 00238 { 00239 kdDebug(9016) << "addScript [" << name << "]" << endl; 00240 00241 //map name of script under /scripts 00242 //m_file->setName("/Scripts/"+name); 00243 00244 kdDebug(9016) << "addScript [" << name << "]" << endl; 00245 NamespaceDom script = m_model->create<NamespaceModel>(); 00246 00247 script->setName(name); 00248 script->setFileName(fileName ); 00249 script->setStartPosition(lineNr, 0 ); 00250 script->setScope(name); 00251 00252 if (!m_file->hasNamespace(name)) { 00253 m_file->addNamespace(script); 00254 m_lastscript=script; 00255 } else { 00256 kdDebug(9016) << "addScript [" << name << " exist]" << endl; 00257 } 00258 00259 //clear all "last" know things 00260 m_lastsub=""; 00261 m_lastattr=""; 00262 m_inpackage = false; 00263 m_inscript = true; 00264 m_inclass=false; 00265 00266 m_lastscriptname=name; 00267 m_lastpackage=0; 00268 m_lastclass=0; 00269 00270 } 00271 00272 void perlparser::addAttributetoPackage(const QString& fileName ,int lineNr ,const QString& name) 00273 { 00274 kdDebug(9016) << "addAttributetoPackage [" << name << "]" << endl; 00275 VariableDom var = m_model->create<VariableModel>(); 00276 var->setName(name); 00277 var->setFileName( fileName ); 00278 var->setStartPosition( lineNr, 0 ); 00279 if (m_lastpackage) { 00280 if (!m_lastpackage->hasVariable(var->name())) 00281 m_lastpackage->addVariable(var); 00282 } else { 00283 kdDebug(9016) << "addAttributetoPackge[ no m_file]" << endl; 00284 } 00285 00286 m_lastattr=name; 00287 } 00288 00289 void perlparser::addAttributetoScript(const QString& fileName ,int lineNr ,const QString& name) 00290 { 00291 kdDebug(9016) << "addAttributetoScript [" << name << "]" << endl; 00292 VariableDom var = m_model->create<VariableModel>(); 00293 var->setName(name); 00294 var->setFileName( fileName ); 00295 var->setStartPosition( lineNr, 0 ); 00296 if (m_lastscript) { 00297 if (!m_lastscript->hasVariable(var->name())) 00298 m_lastscript->addVariable(var); 00299 } else { 00300 kdDebug(9016) << "addAttributeScript[ no m_file]" << endl; 00301 } 00302 } 00303 00304 void perlparser::addClass(const QString& fileName ,int lineNr) 00305 { 00306 kdDebug(9016) << "addClass [ " << m_lastpackagename << " ]" << endl; 00307 if (m_lastpackage->hasClass(m_lastpackagename)) { 00308 kdDebug(9016) << "Class already defined" << endl; 00309 } else { 00310 kdDebug(9016) << "new Class" << endl; 00311 ClassDom lastClass = m_model->create<ClassModel>(); 00312 lastClass->setName(m_lastpackagename); 00313 lastClass->setFileName(fileName); 00314 lastClass->setStartPosition(lineNr, 0); 00315 m_lastpackage->addClass(lastClass); 00316 m_lastclass=lastClass; 00317 m_inclass=true; 00318 } 00319 } 00320 00321 void perlparser::addConstructor(const QString& fileName ,int lineNr ,const QString& name) 00322 { 00323 kdDebug(9016) << "set Constructor["<< name << "]" << endl; 00324 00325 FunctionDom method; 00326 00327 if (m_lastpackage->hasFunction(name)) { 00328 //remove last sub frompackage scope 00329 method = m_lastpackage->functionByName(name)[0]; 00330 method->getStartPosition(&lineNr,0); 00331 m_lastpackage->removeFunction(method); 00332 } 00333 method = m_lastclass->functionByName(name)[0]; 00334 if (!method) { 00335 kdDebug(9016) << "add new Constructor["<< name << ", " << lineNr << "]" << endl; 00336 method = m_model->create<FunctionModel>(); 00337 method->setName(name); 00338 method->setFileName( fileName ); 00339 method->setStartPosition( lineNr, 0 ); 00340 m_lastclass->addFunction(method); 00341 } 00342 method->setStatic(true); 00343 //update class position 00344 m_lastclass->setStartPosition(lineNr,0); 00345 } 00346 00347 void perlparser::addGlobalSub(const QString& fileName ,int lineNr ,const QString& name ,bool privatesub) 00348 { 00349 kdDebug(9016) << "addGlobalSub[ " << name << "]" << endl; 00350 00351 FunctionDom method = m_model->create<FunctionModel>(); 00352 method->setName(name); 00353 method->setFileName( fileName ); 00354 method->setStartPosition( lineNr, 0 ); 00355 method->setStatic(true); 00356 if (privatesub) 00357 method->setAccess(CodeModelItem::Private); 00358 if (m_lastpackage) { 00359 if (!m_lastpackage->hasFunction(method->name())) 00360 m_lastpackage->addFunction(method); 00361 } else { 00362 kdDebug(9016) << "addGlobalsub[ no m_lastpackage]" << endl; 00363 } 00364 00365 //also add seperate to namespace 00366 addPackageSub(fileName,lineNr,name,privatesub); 00367 m_lastsub=name; 00368 } 00369 00370 void perlparser::addScriptSub(const QString& fileName ,int lineNr ,const QString& name ,bool privatesub) 00371 00372 { 00373 kdDebug(9016) << "addScriptSub[ " << name << "]" << endl; 00374 FunctionDom method = m_model->create<FunctionModel>(); 00375 method->setName(name); 00376 method->setFileName( fileName ); 00377 method->setStartPosition( lineNr, 0 ); 00378 if (privatesub) 00379 method->setAccess(CodeModelItem::Private); 00380 if(m_lastscript) { 00381 m_lastscript->addFunction(method); 00382 } else { 00383 } 00384 00385 m_lastsub=name; 00386 } 00387 00388 void perlparser::addClassMethod(const QString& fileName ,int lineNr ,const QString& name ,bool privatesub) 00389 { 00390 kdDebug(9016) << "addClassMethod[ " << name << "]" << endl; 00391 FunctionDom method = m_model->create<FunctionModel>(); 00392 method->setName(name); 00393 method->setFileName( fileName ); 00394 method->setStartPosition( lineNr, 0 ); 00395 method->setVirtual(true); 00396 if (privatesub) 00397 method->setAccess(CodeModelItem::Private); 00398 if (m_lastclass) { 00399 if (!m_lastclass->hasFunction(method->name())) 00400 m_lastclass->addFunction(method); 00401 } else { 00402 kdDebug(9016) << "addClassmethod[ no m_lastclass]" << endl; 00403 } 00404 00405 // addPackageSub(fileName,lineNr,name,privatesub); 00406 m_lastsub=name; 00407 } 00408 00409 void perlparser::addPackageSub(const QString& fileName ,int lineNr ,const QString& name ,bool privatesub) 00410 { 00411 kdDebug(9016) << "addPackageSub[ " << name << "]" << endl; 00412 FunctionDom method = m_model->create<FunctionModel>(); 00413 method->setName(name); 00414 method->setFileName( fileName ); 00415 method->setStartPosition( lineNr, 0 ); 00416 if (privatesub) 00417 method->setAccess(CodeModelItem::Private); 00418 if (m_lastpackage) { 00419 if (!m_lastpackage->hasFunction(method->name())) 00420 m_lastpackage->addFunction(method); 00421 } else { 00422 kdDebug(9016) << "addPackageSub[ no m_file]" << endl; 00423 } 00424 m_lastsub=name; 00425 } 00426 00427 void perlparser::addParentClass(const QString& parent) 00428 { 00429 kdDebug(9016) << "addParentClass[ " << parent << "]" << endl; 00430 if (m_lastclass) { 00431 m_lastclass->addBaseClass(parent); 00432 } else { 00433 kdDebug(9016) << "addParentClass[ no m_lastclass]" << endl; 00434 } 00435 } 00436 00437 void perlparser::addUseLib(const QString& lib) 00438 { 00439 if (!m_model->hasFile(lib)) { 00440 if (m_usefiles.findIndex(lib) == -1) { 00441 //only add if not already parsed or in the list 00442 kdDebug(9016) << "add lib for later parsing [" << lib << "]" << endl; 00443 m_usefiles.append(lib); 00444 } 00445 } 00446 } 00447 00448 void perlparser::getPerlINC() { 00449 00450 00451 m_INClist.clear(); 00452 00453 QString cmd = "/usr/bin/perl -e\" print join('|',@INC);\""; 00454 QString result; 00455 00456 FILE *fd = popen(cmd.local8Bit().data(), "r"); 00457 char buffer[4090]; 00458 QByteArray array; 00459 00460 while (!feof(fd)) { 00461 int n = fread(buffer, 1, 2048, fd); 00462 if (n == -1) { 00463 pclose(fd); 00464 return; 00465 } 00466 array.setRawData(buffer, n); 00467 result=QString::QString(array); 00468 array.resetRawData(buffer, n); 00469 } 00470 pclose(fd); 00471 //get INC list so we can use it to parse "use" modules 00472 m_INClist = QStringList::split(QString("|"),result); 00473 kdDebug(9016) << "INC " << m_INClist.size() << " "<< result << endl; 00474 } 00475 00476 QString perlparser::findLib( const QString& lib) 00477 { 00478 QString result; 00479 00480 QString file=lib; 00481 file.replace( QRegExp("::"), QString("/")); 00482 00483 //find the correct path by using the INC list 00484 QStringList::Iterator inc = m_INClist.begin(); 00485 while((inc != m_INClist.end()) && (result.isEmpty()) ) { 00486 QFileInfo fi((*inc) + "/" + file + ".pm"); 00487 if ( fi.exists() ) { 00488 result = (*inc) + "/" + file + ".pm"; 00489 } 00490 ++inc; 00491 } 00492 return result; 00493 } 00494
KDE Logo
This file is part of the documentation for KDevelop Version 3.0.4.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Oct 6 17:39:05 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003