예제 #1
0
// 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;
}
예제 #2
0
// 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;
}