00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
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
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
00113
if (line.isEmpty()) {
continue;}
00114
00115
if(inpod && endpod) { inpod=
false; endpod=
false;}
00116
00117
if (startpod.search(line)>=0) {inpod=
true;
continue;}
00118
00119
if (inpod) { endpod=( cutpod.search(line)>=0 );
continue; }
00120
00121
00122
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 }
00135
00136
00137
if (globalre.search(line)>=0) {
00138
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 }
00152
00153
00154
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 }
00161
00162
00163
if ((basere.search(line)>=0) && (!
m_inscript)) {
00164
QString parent = basere.cap(1);
00165
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
00174
kdDebug(9016) <<
"libre match [" << path <<
"]" <<
endl;
00175
m_INClist.append(path);
00176
continue;
00177 }
else {
00178
if (usere.search(line)>=0) {
00179
00180
QString lib = usere.cap(1);
00181
kdDebug(9016) <<
"usere match [" << lib <<
"]" <<
endl;
00182
addUseLib(lib);
00183
continue;
00184 } \
00185 }
00186 }
00187
00188
if ((isare.search(line)>=0) && (!
m_inscript)) {
00189
QString parent = isare.cap(1);
00190
00191
kdDebug(9016) <<
"isare match [" << parent <<
"]" <<
endl;
00192
addClass(fileName,lineNo);
00193
addParentClass(parent);
00194
continue;
00195 }
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 }
00203
00204 }
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
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
00242
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
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
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
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
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
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
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
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
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