// ParsePreprocessorDirective //------------------------------------------------------------------------------ bool BFFParser::ParsePreprocessorDirective( BFFIterator & iter ) { const BFFIterator directiveStart( iter ); // skip directive start token ASSERT( *iter == BFF_PREPROCESSOR_START ); iter++; // allow whitepace before directive name iter.SkipWhiteSpace(); // start of directive name BFFIterator directiveStartIter( iter ); // find end of directive while ( iter.IsAtValidDirectiveNameCharacter() ) { iter++; } BFFIterator directiveEndIter( iter ); iter.SkipWhiteSpace(); // determine directive AStackString< MAX_DIRECTIVE_NAME_LENGTH > directive( directiveStartIter.GetCurrent(), directiveEndIter.GetCurrent() ); if ( directive == "include" ) { return ParseIncludeDirective( iter ); } else if ( directive == "once" ) { FBuild::Get().GetDependencyGraph().SetCurrentFileAsOneUse(); return true; } else if ( directive == "define" ) { return ParseDefineDirective( iter ); } else if ( directive == "undef" ) { return ParseUndefDirective( iter ); } else if ( directive == "if" ) { return ParseIfDirective( directiveStart, iter ); } else if ( directive == "endif" ) { return ParseEndIfDirective( directiveStartIter ); } else if ( directive == "import" ) { return ParseImportDirective( directiveStart, iter ); } // unknown Error::Error_1030_UnknownDirective( directiveStartIter, directive ); return false; }
// ParseIfDirective //------------------------------------------------------------------------------ bool BFFParser::ParseIfDirective( const BFFIterator & directiveStart, BFFIterator & iter ) { if ( iter.IsAtEnd() ) { Error::Error_1012_UnexpectedEndOfFile( iter ); return false; } bool negate = false; if ( *iter == '!' ) { negate = true; // the condition will be inverted iter++; // skip '!' iter.SkipWhiteSpace(); // allow whitepace after '!' if ( iter.IsAtEnd() ) { Error::Error_1012_UnexpectedEndOfFile( iter ); return false; } } // parse out condition const BFFIterator conditionStart( iter ); iter.SkipVariableName(); if ( conditionStart.GetCurrent() == iter.GetCurrent() ) { Error::Error_1007_ExpectedVariable( directiveStart, nullptr ); return false; } const BFFIterator conditionEnd( iter ); // Evaluate the condition bool result; if ( CheckIfCondition( conditionStart, conditionEnd, result ) == false ) { return false; // CheckIfCondition will have emitted an error } // #ifndef ? if ( negate ) { result = !( result ); } if ( result ) { ++s_IfDepth; // Track that we're inside an if block return true; // continue parsing like normal } // Advance iterator past entire #if block size_t depth = 1; // handle nested ifs while ( depth > 0 ) { // did we hit the end of the file? if ( iter.IsAtEnd() ) { (void)directiveStart; // TODO: Show we're looking for matching endif to this Error::Error_1012_UnexpectedEndOfFile( iter ); // TODO:B better error for this? return false; } // find the next preprocessor directive iter.SkipWhiteSpace(); if ( *iter == BFF_PREPROCESSOR_START ) { iter++; // skip # iter.SkipWhiteSpace(); // allow whitespace between # and directive const BFFIterator directiveNameStart( iter ); while ( iter.IsAtValidDirectiveNameCharacter() ) { iter++; } const BFFIterator directiveNameEnd( iter ); AStackString<> directiveName( directiveNameStart.GetCurrent(), directiveNameEnd.GetCurrent() ); if ( directiveName == "endif" ) { --depth; } else if ( directiveName == "if" ) { ++depth; } // continue to skip rest of line.... } // skip rest of line while ( ( iter.IsAtEnd() == false ) && ( *iter != '\r' ) && ( *iter != '\n' ) ) { iter++; } } return true; }