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