00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
#include "lexer.h"
00021
#include "lookup.h"
00022
#include "keywords.lut.h"
00023
00024
#include <kdebug.h>
00025
#include <klocale.h>
00026
00027
#include <qregexp.h>
00028
#include <qmap.h>
00029
#include <qvaluelist.h>
00030
00031
#if defined( KDEVELOP_BGPARSER )
00032
#include <qthread.h>
00033
00034
class KDevTread:
public QThread
00035 {
00036
public:
00037
static void yield()
00038 {
00039 msleep( 0 );
00040 }
00041 };
00042
00043
inline void qthread_yield()
00044 {
00045 KDevTread::yield();
00046 }
00047
00048
#endif
00049
00050 #define CREATE_TOKEN(type, start, len) Token( (type), (start), (len), m_source )
00051 #define ADD_TOKEN(tk) m_tokens.insert( m_size++, new Token(tk) );
00052
00053
using namespace std;
00054
00055 struct LexerData
00056 {
00057 typedef QMap<QString, QString> Scope;
00058 typedef QValueList<Scope> StaticChain;
00059
00060 StaticChain staticChain;
00061
00062 void beginScope()
00063 {
00064
Scope scope;
00065
staticChain.push_front( scope );
00066 }
00067
00068 void endScope()
00069 {
00070
staticChain.pop_front();
00071 }
00072
00073 void bind(
const QString& name,
const QString& value )
00074 {
00075 Q_ASSERT(
staticChain.size() > 0 );
00076
staticChain.front().insert( name, value );
00077 }
00078
00079 bool hasBind(
const QString& name )
const
00080
{
00081 StaticChain::ConstIterator it =
staticChain.begin();
00082
while( it !=
staticChain.end() ){
00083
const Scope& scope = *it;
00084 ++it;
00085
00086
if( scope.contains(name) )
00087
return true;
00088 }
00089
00090
return false;
00091 }
00092
00093 QString apply(
const QString& name )
const
00094
{
00095 StaticChain::ConstIterator it =
staticChain.begin();
00096
while( it !=
staticChain.end() ){
00097
const Scope& scope = *it;
00098 ++it;
00099
00100
if( scope.contains(name) )
00101
return scope[ name ];
00102 }
00103
00104
return QString::null;
00105 }
00106
00107 };
00108
00109 Lexer::Lexer(
Driver* driver )
00110 : d( new
LexerData),
00111 m_driver( driver ),
00112 m_recordComments( false ),
00113 m_recordWhiteSpaces( false ),
00114 m_skipWordsEnabled( true ),
00115 m_preprocessorEnabled( true ),
00116 m_reportWarnings( false ),
00117 m_reportMessages( false )
00118 {
00119
m_tokens.setAutoDelete(
true );
00120
reset();
00121
d->
beginScope();
00122 }
00123
00124 Lexer::~Lexer()
00125 {
00126
d->
endScope();
00127
delete(
d );
00128 }
00129
00130 void Lexer::setSource(
const QString& source )
00131 {
00132
reset();
00133
m_source = source;
00134
m_ptr = 0;
00135
m_endPtr =
m_source.length();
00136
m_inPreproc =
false;
00137
00138
tokenize();
00139 }
00140
00141 void Lexer::reset()
00142 {
00143
m_index = 0;
00144
m_size = 0;
00145
m_tokens.clear();
00146
m_source = QString::null;
00147
m_ptr = 0;
00148
m_endPtr = 0;
00149
m_startLine =
false;
00150
m_ifLevel = 0;
00151
m_skipping.resize( 200 );
00152
m_skipping.fill( 0 );
00153
m_trueTest.resize( 200 );
00154
m_trueTest.fill( 0 );
00155
00156
m_currentLine = 0;
00157
m_currentColumn = 0;
00158 }
00159
00160
00161 int Lexer::toInt(
const Token& token )
00162 {
00163
QString s = token.
text();
00164
if( token.
type() ==
Token_number_literal ){
00165
00166
if( s[0] ==
'0' && (s[1] ==
'x' || s[1] ==
'X'))
00167
return s.mid( 2 ).toInt( 0, 16 );
00168
QString n;
00169
int i = 0;
00170
while( i < int(s.length()) && s[i].isDigit() )
00171 n += s[i++];
00172
00173
return n.toInt();
00174 }
else if( token.
type() ==
Token_char_literal ){
00175
int i = s[0] ==
'L' ? 2 : 1;
00176
if( s[i] ==
'\\' ){
00177
00178
int c = s[i+1].unicode();
00179
switch( c ) {
00180
case '0':
00181
return 0;
00182
case 'n':
00183
return '\n';
00184
00185
default:
00186
return c;
00187 }
00188 }
else {
00189
return s[i].unicode();
00190 }
00191 }
else {
00192
return 0;
00193 }
00194 }
00195
00196 void Lexer::getTokenPosition(
const Token& token,
int* line,
int* col )
00197 {
00198 token.
getStartPosition( line, col );
00199 }
00200
00201 void Lexer::nextToken(
Token& tk,
bool stopOnNewline )
00202 {
00203
int op = 0;
00204
00205
if(
m_size == (
int)
m_tokens.size() ){
00206
m_tokens.resize(
m_tokens.size() + 5000 );
00207 }
00208
00209
readWhiteSpaces( !stopOnNewline );
00210
00211
int startLine =
m_currentLine;
00212
int startColumn =
m_currentColumn;
00213
00214
QChar ch =
currentChar();
00215
QChar ch1 =
peekChar();
00216
00217
if( ch.isNull() || ch.isSpace() ){
00218
00219 }
else if(
m_startLine && ch ==
'#' ){
00220
00221
nextChar();
00222
readWhiteSpaces(
false );
00223
m_startLine =
false;
00224
00225
int start =
currentPosition();
00226
readIdentifier();
00227
QString directive =
m_source.mid( start,
currentPosition() - start );
00228
00229
handleDirective( directive );
00230 }
else if(
m_startLine &&
m_skipping[
m_ifLevel ] ){
00231
00232
m_startLine =
false;
00233
int ppe =
preprocessorEnabled();
00234
setPreprocessorEnabled(
false );
00235
while(
currentChar() &&
currentChar() !=
'\n' ){
00236
Token tok;
00237
nextToken( tok,
true );
00238 }
00239
m_startLine =
true;
00240
setPreprocessorEnabled( ppe );
00241
return;
00242 }
else if( ch ==
'/' && ch1 ==
'/' ){
00243
int start =
currentPosition();
00244
readLineComment();
00245
if(
recordComments() ){
00246 tk =
CREATE_TOKEN(
Token_comment, start,
currentPosition() - start );
00247 tk.
setStartPosition( startLine, startColumn );
00248 tk.
setEndPosition( m_currentLine, m_currentColumn );
00249 }
00250 }
else if( ch ==
'/' && ch1 ==
'*' ){
00251
int start =
currentPosition();
00252
nextChar( 2 );
00253
readMultiLineComment();
00254
00255
if(
recordComments() ){
00256 tk =
CREATE_TOKEN(
Token_comment, start,
currentPosition() - start );
00257 tk.
setStartPosition( startLine, startColumn );
00258 tk.
setEndPosition( m_currentLine, m_currentColumn );
00259 }
00260 }
else if( ch ==
'\'' || (ch ==
'L' && ch1 ==
'\'') ){
00261
int start =
currentPosition();
00262
readCharLiteral();
00263 tk =
CREATE_TOKEN(
Token_char_literal, start,
currentPosition() - start );
00264 tk.
setStartPosition( startLine, startColumn );
00265 tk.
setEndPosition( m_currentLine, m_currentColumn );
00266 }
else if( ch ==
'"' ){
00267
int start =
currentPosition();
00268
readStringLiteral();
00269 tk =
CREATE_TOKEN(
Token_string_literal, start,
currentPosition() - start );
00270 tk.
setStartPosition( startLine, startColumn );
00271 tk.
setEndPosition( m_currentLine, m_currentColumn );
00272 }
else if( ch.isLetter() || ch ==
'_' ){
00273
int start =
currentPosition();
00274
readIdentifier();
00275
QString ide =
m_source.mid( start,
currentPosition() - start );
00276
int k = Lookup::find( &keyword, ide );
00277
if(
m_preprocessorEnabled &&
m_driver->
hasMacro(ide) &&
00278 (k == -1 || !
m_driver->
macro(ide).
body().isEmpty()) ){
00279
00280
00281
bool preproc =
m_preprocessorEnabled;
00282 m_preprocessorEnabled =
false;
00283
00284
d->
beginScope();
00285
00286
int svLine =
currentLine();
00287
int svColumn =
currentColumn();
00288
00289
00290
Macro m =
m_driver->
macro( ide );
00291
00292
00293
QString ellipsisArg;
00294
00295
if( m.
hasArguments() ){
00296
int endIde =
currentPosition();
00297
00298
readWhiteSpaces();
00299
if(
currentChar() ==
'(' ){
00300
nextChar();
00301
int argIdx = 0;
00302
int argCount = m.
argumentList().size();
00303
while(
currentChar() && argIdx<argCount ){
00304
readWhiteSpaces();
00305
00306
QString argName = m.
argumentList()[ argIdx ];
00307
00308
bool ellipsis = argName ==
"...";
00309
00310
QString arg =
readArgument();
00311
00312
if( !ellipsis )
00313
d->
bind( argName, arg );
00314
else
00315 ellipsisArg += arg;
00316
00317
if(
currentChar() ==
',' ){
00318
nextChar();
00319
if( !ellipsis ){
00320 ++argIdx;
00321 }
else {
00322 ellipsisArg +=
", ";
00323 }
00324 }
else if(
currentChar() ==
')' ){
00325
break;
00326 }
00327 }
00328
if(
currentChar() ==
')' ){
00329
00330
nextChar();
00331 }
00332 }
else {
00333 tk =
CREATE_TOKEN(
Token_identifier, start, endIde - start );
00334 tk.
setStartPosition( svLine, svColumn );
00335 tk.
setEndPosition( svLine, svColumn + (endIde - start) );
00336
00337
m_startLine =
false;
00338
00339
d->
endScope();
00340 m_preprocessorEnabled = preproc;
00341
return;
00342 }
00343 }
00344
00345
int argsEndAtLine =
currentLine();
00346
int argsEndAtColumn =
currentColumn();
00347
00348
#if defined( KDEVELOP_BGPARSER )
00349
qthread_yield();
00350
#endif
00351
m_source.insert(
currentPosition(), m.
body() );
00352
00353
00354
00355
QString textToInsert;
00356
00357
m_endPtr =
currentPosition() + m.
body().length();
00358
while(
currentChar() ){
00359
00360
readWhiteSpaces();
00361
00362
Token tok;
00363
nextToken( tok );
00364
00365
bool stringify = !
m_inPreproc && tok ==
'#';
00366
bool merge = !
m_inPreproc && tok ==
Token_concat;
00367
00368
if( stringify || merge )
00369
nextToken( tok );
00370
00371
if( tok ==
Token_eof )
00372
break;
00373
00374
QString tokText = tok.text();
00375
QString str = (tok ==
Token_identifier &&
d->
hasBind(tokText)) ?
d->
apply( tokText ) : tokText;
00376
if( str == ide ){
00377
00378
00379
m_driver->
removeMacro( ide );
00380
00381 }
00382
00383
if( stringify ) {
00384 textToInsert.append( QString::fromLatin1(
"\"") + str + QString::fromLatin1(
"\" ") );
00385 }
else if( merge ){
00386 textToInsert.truncate( textToInsert.length() - 1 );
00387 textToInsert.append( str );
00388 }
else if( tok ==
Token_ellipsis &&
d->
hasBind(
"...") ){
00389 textToInsert.append( ellipsisArg );
00390 }
else {
00391 textToInsert.append( str + QString::fromLatin1(
" ") );
00392 }
00393 }
00394
00395
#if defined( KDEVELOP_BGPARSER )
00396
qthread_yield();
00397
#endif
00398
m_source.insert(
currentPosition(), textToInsert );
00399
00400
d->
endScope();
00401 m_preprocessorEnabled = preproc;
00402
00403 m_currentLine = argsEndAtLine;
00404 m_currentColumn = argsEndAtColumn;
00405
m_endPtr =
m_source.length();
00406 }
else if( k != -1 ){
00407 tk =
CREATE_TOKEN( k, start,
currentPosition() - start );
00408 tk.
setStartPosition( startLine, startColumn );
00409 tk.
setEndPosition( m_currentLine, m_currentColumn );
00410 }
else if(
m_skipWordsEnabled ){
00411
QMap< QString, QPair<SkipType, QString> >::Iterator pos =
m_words.find( ide );
00412
if( pos !=
m_words.end() ){
00413
if( (*pos).first ==
SkipWordAndArguments ){
00414
readWhiteSpaces();
00415
if(
currentChar() ==
'(' )
00416
skip(
'(',
')' );
00417 }
00418
if( !(*pos).second.isEmpty() ){
00419
#if defined( KDEVELOP_BGPARSER )
00420
qthread_yield();
00421
#endif
00422
m_source.insert(
currentPosition(),
QString(
" ") + (*pos).second +
QString(
" ") );
00423
m_endPtr =
m_source.length();
00424 }
00425 }
else if(
00426 ide.endsWith(
"EXPORT") ||
00427 (ide.startsWith(
"Q_EXPORT") && ide !=
"Q_EXPORT_INTERFACE") ||
00428 ide.startsWith(
"QM_EXPORT") ||
00429 ide.startsWith(
"QM_TEMPLATE")){
00430
00431
readWhiteSpaces();
00432
if(
currentChar() ==
'(' )
00433
skip(
'(',
')' );
00434 }
else if( ide.startsWith(
"K_TYPELIST_") || ide.startsWith(
"TYPELIST_") ){
00435 tk =
CREATE_TOKEN(
Token_identifier, start,
currentPosition() - start );
00436 tk.
setStartPosition( startLine, startColumn );
00437 tk.
setEndPosition( m_currentLine, m_currentColumn );
00438
readWhiteSpaces();
00439
if(
currentChar() ==
'(' )
00440
skip(
'(',
')' );
00441 }
else{
00442 tk =
CREATE_TOKEN(
Token_identifier, start,
currentPosition() - start );
00443 tk.
setStartPosition( startLine, startColumn );
00444 tk.
setEndPosition( m_currentLine, m_currentColumn );
00445 }
00446 }
else {
00447 tk =
CREATE_TOKEN(
Token_identifier, start,
currentPosition() - start );
00448 tk.
setStartPosition( startLine, startColumn );
00449 tk.
setEndPosition( m_currentLine, m_currentColumn );
00450 }
00451 }
else if( ch.isNumber() ){
00452
int start =
currentPosition();
00453
readNumberLiteral();
00454 tk =
CREATE_TOKEN(
Token_number_literal, start,
currentPosition() - start );
00455 tk.
setStartPosition( startLine, startColumn );
00456 tk.
setEndPosition( m_currentLine, m_currentColumn );
00457 }
else if( -1 != (op =
findOperator3()) ){
00458 tk =
CREATE_TOKEN( op,
currentPosition(), 3 );
00459
nextChar( 3 );
00460 tk.
setStartPosition( startLine, startColumn );
00461 tk.
setEndPosition( m_currentLine, m_currentColumn );
00462 }
else if( -1 != (op =
findOperator2()) ){
00463 tk =
CREATE_TOKEN( op,
currentPosition(), 2 );
00464
nextChar( 2 );
00465 tk.
setStartPosition( startLine, startColumn );
00466 tk.
setEndPosition( m_currentLine, m_currentColumn );
00467 }
else {
00468 tk =
CREATE_TOKEN( ch,
currentPosition(), 1 );
00469
nextChar();
00470 tk.
setStartPosition( startLine, startColumn );
00471 tk.
setEndPosition( m_currentLine, m_currentColumn );
00472 }
00473
00474
m_startLine =
false;
00475 }
00476
00477
00478 void Lexer::tokenize()
00479 {
00480
m_startLine =
true;
00481
m_size = 0;
00482
00483
for( ;; ) {
00484
Token tk;
00485
nextToken( tk );
00486
00487
if( tk.
type() != -1 )
00488
ADD_TOKEN( tk );
00489
00490
if(
currentChar().isNull() )
00491
break;
00492 }
00493
00494
Token tk =
CREATE_TOKEN(
Token_eof,
currentPosition(), 0 );
00495 tk.
setStartPosition(
m_currentLine,
m_currentColumn );
00496 tk.
setEndPosition(
m_currentLine,
m_currentColumn );
00497
ADD_TOKEN( tk );
00498 }
00499
00500 void Lexer::resetSkipWords()
00501 {
00502
m_words.clear();
00503 }
00504
00505 void Lexer::addSkipWord(
const QString& word, SkipType skipType,
const QString& str )
00506 {
00507
m_words[ word ] = qMakePair( skipType, str );
00508 }
00509
00510 void Lexer::skip(
int l,
int r )
00511 {
00512
int svCurrentLine =
m_currentLine;
00513
int svCurrentColumn =
m_currentColumn;
00514
00515
int count = 0;
00516
00517
while( !
eof() ){
00518
Token tk;
00519
nextToken( tk );
00520
00521
if( (
int)tk == l )
00522 ++count;
00523
else if( (
int)tk == r )
00524 --count;
00525
00526
if( count == 0 )
00527
break;
00528 }
00529
00530 m_currentLine = svCurrentLine;
00531 m_currentColumn = svCurrentColumn;
00532 }
00533
00534 QString Lexer::readArgument()
00535 {
00536
int count = 0;
00537
00538
QString arg;
00539
00540
readWhiteSpaces();
00541
while(
currentChar() ){
00542
00543
readWhiteSpaces();
00544
QChar ch =
currentChar();
00545
00546
if( ch.isNull() || (!count && (ch ==
',' || ch ==
')')) )
00547
break;
00548
00549
Token tk;
00550
nextToken( tk );
00551
00552
if( tk ==
'(' ){
00553 ++count;
00554 }
else if( tk ==
')' ){
00555 --count;
00556 }
00557
00558
if( tk != -1 )
00559 arg += tk.
text() +
" ";
00560 }
00561
00562
return arg.stripWhiteSpace();
00563 }
00564
00565 void Lexer::handleDirective(
const QString& directive )
00566 {
00567
m_inPreproc =
true;
00568
00569
bool skip =
skipWordsEnabled();
00570
bool preproc =
preprocessorEnabled();
00571
00572
setSkipWordsEnabled(
false );
00573
setPreprocessorEnabled(
false );
00574
00575
if( directive ==
"define" ){
00576
if( !
m_skipping[
m_ifLevel ] ){
00577
Macro m;
00578
processDefine( m );
00579 }
00580 }
else if( directive ==
"else" ){
00581
processElse();
00582 }
else if( directive ==
"elif" ){
00583
processElif();
00584 }
else if( directive ==
"endif" ){
00585
processEndif();
00586 }
else if( directive ==
"if" ){
00587
processIf();
00588 }
else if( directive ==
"ifdef" ){
00589
processIfdef();
00590 }
else if( directive ==
"ifndef" ){
00591
processIfndef();
00592 }
else if( directive ==
"include" ){
00593
if( !
m_skipping[
m_ifLevel ] ){
00594
processInclude();
00595 }
00596 }
else if( directive ==
"undef" ){
00597
if( !
m_skipping[
m_ifLevel ] ){
00598
processUndef();
00599 }
00600 }
00601
00602
00603
while(
currentChar() &&
currentChar() !=
'\n' ){
00604
Token tk;
00605
nextToken( tk,
true );
00606 }
00607
00608
setSkipWordsEnabled( skip );
00609
setPreprocessorEnabled( preproc );
00610
00611
m_inPreproc =
false;
00612 }
00613
00614 int Lexer::testIfLevel()
00615 {
00616
int rtn = !
m_skipping[
m_ifLevel++ ];
00617
m_skipping[
m_ifLevel ] =
m_skipping[
m_ifLevel - 1 ];
00618
return rtn;
00619 }
00620
00621 int Lexer::macroDefined()
00622 {
00623
readWhiteSpaces(
false );
00624
int startWord =
currentPosition();
00625
readIdentifier();
00626
QString word =
m_source.mid( startWord,
currentPosition() - startWord );
00627
bool r =
m_driver->
hasMacro( word );
00628
00629
return r;
00630 }
00631
00632 void Lexer::processDefine(
Macro& m )
00633 {
00634 m.
setFileName(
m_driver->
currentFileName() );
00635
readWhiteSpaces(
false );
00636
00637
int startMacroName =
currentPosition();
00638
readIdentifier();
00639
QString macroName =
m_source.mid( startMacroName,
int(
currentPosition()-startMacroName) );
00640
m_driver->
removeMacro( macroName );
00641 m.
setName( macroName );
00642
00643
if(
currentChar() ==
'(' ){
00644 m.
setHasArguments(
true );
00645
nextChar();
00646
00647
readWhiteSpaces(
false );
00648
00649
while(
currentChar() &&
currentChar() !=
')' ){
00650
readWhiteSpaces(
false );
00651
00652
int startArg =
currentPosition();
00653
00654
if(
currentChar() ==
'.' &&
peekChar() ==
'.' &&
peekChar(2) ==
'.' )
00655
nextChar( 3 );
00656
else
00657
readIdentifier();
00658
00659
QString arg =
m_source.mid( startArg,
int(
currentPosition()-startArg) );
00660
00661 m.
addArgument(
Macro::Argument(arg) );
00662
00663
readWhiteSpaces(
false );
00664
if(
currentChar() !=
',' )
00665
break;
00666
00667
nextChar();
00668 }
00669
00670
if(
currentChar() ==
')' )
00671
nextChar();
00672 }
00673
00674
setPreprocessorEnabled(
true );
00675
00676
QString body;
00677
while(
currentChar() &&
currentChar() !=
'\n' ){
00678
00679
if(
currentChar().isSpace() ){
00680
readWhiteSpaces(
false );
00681 body +=
" ";
00682 }
else {
00683
00684
Token tk;
00685
nextToken( tk,
true );
00686
00687
if( tk.
type() != -1 ){
00688
QString s = tk.
text();
00689 body += s;
00690 }
00691 }
00692 }
00693
00694 m.
setBody( body );
00695
m_driver->
addMacro( m );
00696 }
00697
00698 void Lexer::processElse()
00699 {
00700
if(
m_ifLevel == 0 )
00702
return;
00703
00704
if(
m_ifLevel > 0 &&
m_skipping[
m_ifLevel-1] )
00705 m_skipping[
m_ifLevel ] = m_skipping[
m_ifLevel - 1 ];
00706
else
00707 m_skipping[
m_ifLevel ] =
m_trueTest[
m_ifLevel ];
00708 }
00709
00710 void Lexer::processElif()
00711 {
00712
if(
m_ifLevel == 0 )
00714
return;
00715
00716
if( !
m_trueTest[
m_ifLevel] ){
00718
bool inSkip =
m_ifLevel > 0 &&
m_skipping[
m_ifLevel-1 ];
00719
m_trueTest[
m_ifLevel ] =
macroExpression() != 0;
00720 m_skipping[
m_ifLevel ] = inSkip ? inSkip : !
m_trueTest[
m_ifLevel ];
00721 }
00722
else
00723
m_skipping[
m_ifLevel ] =
true;
00724 }
00725
00726 void Lexer::processEndif()
00727 {
00728
if(
m_ifLevel == 0 )
00730
return;
00731
00732
m_skipping[
m_ifLevel ] = 0;
00733
m_trueTest[
m_ifLevel-- ] = 0;
00734 }
00735
00736 void Lexer::processIf()
00737 {
00738
bool inSkip =
m_skipping[
m_ifLevel ];
00739
00740
if(
testIfLevel() ) {
00741
#if 0
00742
int n;
00743
if( (n = testDefined()) != 0 ) {
00744
int isdef =
macroDefined();
00745
m_trueTest[
m_ifLevel ] = (n == 1 && isdef) || (n == -1 && !isdef);
00746 }
else
00747
#endif
00748
m_trueTest[
m_ifLevel ] =
macroExpression() != 0;
00749 m_skipping[
m_ifLevel ] = inSkip ? inSkip : !
m_trueTest[
m_ifLevel ];
00750 }
00751 }
00752
00753 void Lexer::processIfdef()
00754 {
00755
bool inSkip =
m_skipping[
m_ifLevel ];
00756
00757
if(
testIfLevel() ){
00758
m_trueTest[
m_ifLevel ] =
macroDefined();
00759 m_skipping[
m_ifLevel ] = inSkip ? inSkip : !
m_trueTest[
m_ifLevel ];
00760 }
00761 }
00762
00763 void Lexer::processIfndef()
00764 {
00765
bool inSkip =
m_skipping[
m_ifLevel ];
00766
00767
if(
testIfLevel() ){
00768
m_trueTest[
m_ifLevel ] = !
macroDefined();
00769 m_skipping[
m_ifLevel ] = inSkip ? inSkip : !
m_trueTest[
m_ifLevel ];
00770 }
00771 }
00772
00773 void Lexer::processInclude()
00774 {
00775
if(
m_skipping[
m_ifLevel] )
00776
return;
00777
00778
readWhiteSpaces(
false );
00779
if(
currentChar() ){
00780
QChar ch =
currentChar();
00781
if( ch ==
'"' || ch ==
'<' ){
00782
nextChar();
00783
QChar ch2 = ch ==
QChar(
'"') ? QChar(
'"') : QChar(
'>');
00784
00785
int startWord =
currentPosition();
00786
while(
currentChar() &&
currentChar() != ch2 )
00787
nextChar();
00788
if(
currentChar() ){
00789
QString word =
m_source.mid( startWord,
int(
currentPosition()-startWord) );
00790
m_driver->
addDependence(
m_driver->
currentFileName(),
00791
Dependence(word, ch ==
'"' ?
Dep_Local :
Dep_Global) );
00792
nextChar();
00793 }
00794 }
00795 }
00796 }
00797
00798 void Lexer::processUndef()
00799 {
00800
readWhiteSpaces();
00801
int startWord =
currentPosition();
00802
readIdentifier();
00803
QString word =
m_source.mid( startWord,
currentPosition() - startWord );
00804
m_driver->
removeMacro( word );
00805 }
00806
00807 int Lexer::macroPrimary()
00808 {
00809
readWhiteSpaces(
false );
00810
int result = 0;
00811
switch(
currentChar() ) {
00812
case '(':
00813
nextChar();
00814 result =
macroExpression();
00815
if(
currentChar() !=
')' ){
00817
return 0;
00818 }
00819
nextChar();
00820
return result;
00821
00822
case '+':
00823
case '-':
00824
case '!':
00825
case '~':
00826 {
00827
QChar tk =
currentChar();
00828
nextChar();
00829
int result =
macroPrimary();
00830
if( tk ==
'-' )
return -result;
00831
else if( tk ==
'!' )
return !result;
00832
else if( tk ==
'~' )
return ~result;
00833 }
00834
break;
00835
00836
default:
00837 {
00838
Token tk;
00839
nextToken( tk,
false );
00840
switch( tk.
type() ){
00841
case Token_identifier:
00842
if( tk.
text() ==
"defined" ){
00843
return macroPrimary();
00844 }
00846
return m_driver->
hasMacro( tk.
text() );
00847
case Token_number_literal:
00848
case Token_char_literal:
00849
return toInt( tk );
00850
default:
00851
break;
00852 }
00853
00854 }
00855
00856 }
00857
00858
return 0;
00859 }
00860
00861 int Lexer::macroMultiplyDivide()
00862 {
00863
int result =
macroPrimary();
00864
int iresult, op;
00865
for (;;) {
00866
readWhiteSpaces(
false );
00867
if(
currentChar() ==
'*' )
00868 op = 0;
00869
else if(
currentChar() ==
'/' && !(
peekChar() ==
'*' ||
peekChar() ==
'/') )
00870 op = 1;
00871
else if(
currentChar() ==
'%' )
00872 op = 2;
00873
else
00874
break;
00875
nextChar();
00876 iresult =
macroPrimary();
00877 result = op == 0 ? (result * iresult) :
00878 op == 1 ? (iresult == 0 ? 0 : (result / iresult)) :
00879 (iresult == 0 ? 0 : (result % iresult)) ;
00880 }
00881
return result;
00882 }
00883
00884 int Lexer::macroAddSubtract()
00885 {
00886
int result =
macroMultiplyDivide();
00887
int iresult, ad;
00888
readWhiteSpaces(
false );
00889
while(
currentChar() ==
'+' ||
currentChar() ==
'-') {
00890 ad =
currentChar() ==
'+';
00891
nextChar();
00892 iresult =
macroMultiplyDivide();
00893 result = ad ? (result+iresult) : (result-iresult);
00894 }
00895
return result;
00896 }
00897
00898 int Lexer::macroRelational()
00899 {
00900
int result =
macroAddSubtract();
00901
int iresult;
00902
readWhiteSpaces(
false );
00903
while(
currentChar() ==
'<' ||
currentChar() ==
'>') {
00904
int lt =
currentChar() ==
'<';
00905
nextChar();
00906
if(
currentChar() ==
'=') {
00907
nextChar();
00908
00909 iresult =
macroAddSubtract();
00910 result = lt ? (result <= iresult) : (result >= iresult);
00911 }
00912
else {
00913 iresult =
macroAddSubtract();
00914 result = lt ? (result < iresult) : (result > iresult);
00915 }
00916 }
00917
00918
return result;
00919 }
00920
00921 int Lexer::macroEquality()
00922 {
00923
int result =
macroRelational();
00924
int iresult,
eq;
00925
readWhiteSpaces(
false );
00926
while ((
currentChar() ==
'=' ||
currentChar() ==
'!') &&
peekChar() ==
'=') {
00927
eq =
currentChar() ==
'=';
00928
nextChar( 2 );
00929 iresult =
macroRelational();
00930 result =
eq ? (result==iresult) : (result!=iresult);
00931 }
00932
return result;
00933 }
00934
00935 int Lexer::macroBoolAnd()
00936 {
00937
int result =
macroEquality();
00938
readWhiteSpaces(
false );
00939
while(
currentChar() ==
'&' &&
peekChar() !=
'&') {
00940
nextChar();
00941 result &=
macroEquality();
00942 }
00943
return result;
00944 }
00945
00946 int Lexer::macroBoolXor()
00947 {
00948
int result =
macroBoolAnd();
00949
readWhiteSpaces(
false );
00950
while(
currentChar() ==
'^') {
00951
nextChar();
00952 result ^=
macroBoolAnd();
00953 }
00954
return result;
00955 }
00956
00957 int Lexer::macroBoolOr()
00958 {
00959
int result =
macroBoolXor();
00960
readWhiteSpaces(
false );
00961
while(
currentChar() ==
'|' &&
peekChar() !=
'|') {
00962
nextChar();
00963 result |=
macroBoolXor();
00964 }
00965
return result;
00966 }
00967
00968 int Lexer::macroLogicalAnd()
00969 {
00970
int result =
macroBoolOr();
00971
readWhiteSpaces(
false );
00972
while(
currentChar() ==
'&' &&
peekChar() ==
'&') {
00973
nextChar( 2 );
00974
int start =
currentPosition();
00975 result =
macroBoolOr() && result;
00976
QString s =
m_source.mid( start,
currentPosition() - start );
00977 }
00978
return result;
00979 }
00980
00981 int Lexer::macroLogicalOr()
00982 {
00983
int result =
macroLogicalAnd();
00984
readWhiteSpaces(
false );
00985
while(
currentChar() ==
'|' &&
peekChar() ==
'|') {
00986
nextChar( 2 );
00987 result =
macroLogicalAnd() || result;
00988 }
00989
return result;
00990 }
00991
00992 int Lexer::macroExpression()
00993 {
00994
readWhiteSpaces(
false );
00995
return macroLogicalOr();
00996 }
00997
00998
00999
01000
01001
01002