Пример #1
0
// StoreVariableStruct
//------------------------------------------------------------------------------
bool BFFParser::StoreVariableStruct( const AString & name,
									 const BFFIterator & valueStart, const BFFIterator & valueEnd,
									 const BFFIterator & operatorIter,
									 BFFStackFrame * frame )
{
	// are we concatenating?
	if ( *operatorIter == BFF_VARIABLE_CONCATENATION )
	{
		// concatenation of structs not supported
		Error::Error_1027_CannotModify( operatorIter, name, BFFVariable::VAR_STRUCT, BFFVariable::VAR_ANY );
		return false;
	}

	// create stack frame to capture variables
	BFFStackFrame stackFrame;

	// parse all the variables in the scope
	BFFParser subParser;
	BFFIterator subIter( valueStart );
	subIter.SetMax( valueEnd.GetCurrent() ); // limit to closing token
	if ( subParser.Parse( subIter ) == false )
	{
		return false; // error will be emitted by Parse
	}

	// get variables defined in the scope
	const Array< const BFFVariable * > & structMembers = stackFrame.GetLocalVariables();

	// Register this variable
	BFFStackFrame::SetVarStruct( name, structMembers, frame ? frame : stackFrame.GetParent() );
	FLOG_INFO( "Registered <struct> variable '%s' with %u members", name.Get(), structMembers.GetSize() );

	return true;
}
Пример #2
0
// ParseUnnamedScope
//------------------------------------------------------------------------------
bool BFFParser::ParseUnnamedScope( BFFIterator & iter )
{
	// find the matching bracket
	BFFIterator scopeStart( iter );
	if ( iter.ParseToMatchingBrace( BFF_SCOPE_OPEN, BFF_SCOPE_CLOSE ) == false )
	{
		Error::Error_1025_MissingScopeCloseToken( scopeStart, nullptr );
		return false;
	}

	// create stack for scope
	BFFStackFrame stackFrame;

	// parse the scoped part
	BFFParser subParser;
	BFFIterator subIter( scopeStart );
	subIter++; // skip opening token
	subIter.SetMax( iter.GetCurrent() ); // limit to closing token
	if ( subParser.Parse( subIter ) == false )
	{
		return false;
	}

	iter++; // skip closing }

	return true;
}
Пример #3
0
// ParseFunction
//------------------------------------------------------------------------------
/*virtual*/ bool Function::ParseFunction( const BFFIterator & functionNameStart,
										  const BFFIterator * functionBodyStartToken, 
										  const BFFIterator * functionBodyStopToken,
										  const BFFIterator * functionHeaderStartToken,
										  const BFFIterator * functionHeaderStopToken ) const
{
	m_AliasForFunction.Clear();
	if ( AcceptsHeader() &&
		 functionHeaderStartToken && functionHeaderStopToken &&
		 ( functionHeaderStartToken->GetDistTo( *functionHeaderStopToken ) > 1 ) )
	{
		// find opening quote
		BFFIterator start( *functionHeaderStartToken );
		ASSERT( *start == BFFParser::BFF_FUNCTION_ARGS_OPEN );
		start++;
		start.SkipWhiteSpace();
		const char c = *start;
		if ( ( c != '"' ) && ( c != '\'' ) )
		{
			Error::Error_1001_MissingStringStartToken( start, this ); 
			return false;
		}
		BFFIterator stop( start );
		stop.SkipString( c );
		ASSERT( stop.GetCurrent() <= functionHeaderStopToken->GetCurrent() ); // should not be in this function if strings are not validly terminated
		if ( start.GetDistTo( stop ) <= 1 )
		{
			Error::Error_1003_EmptyStringNotAllowedInHeader( start, this );
			return false;
		}

		// store alias name for use in Commit
		start++; // skip past opening quote
		if ( BFFParser::PerformVariableSubstitutions( start, stop, m_AliasForFunction ) == false )
		{
			return false; // substitution will have emitted an error
		}
	}

	// parse the function body
	BFFParser subParser;
	BFFIterator subIter( *functionBodyStartToken );
	subIter++; // skip past opening body token
	subIter.SetMax( functionBodyStopToken->GetCurrent() ); // cap parsing to body end
	if ( subParser.Parse( subIter ) == false )
	{
		return false;
	}

	// complete the function
	return Commit( functionNameStart );
}
Пример #4
0
// ParseIncludeDirective
//------------------------------------------------------------------------------
bool BFFParser::ParseIncludeDirective( BFFIterator & iter )
{
	// Sanity check include depth to detect cyclic includes
	if ( s_Depth >= 128 )
	{
		Error::Error_1035_ExcessiveDepthComplexity( iter );
		return false;
	}

	// we expect a " quoted string
	if ( *iter != '"' )
	{
		Error::Error_1031_UnexpectedCharFollowingDirectiveName( iter, AStackString<>( "include" ), '"' ); 
		return false;
	}

	BFFIterator stringStart( iter );
	stringStart++; // first actual character

	// find end of string
	if ( iter.ParseToNext( '"' ) == false )
	{
		Error::Error_1012_UnexpectedEndOfFile( iter );
		return false;
	}

	// unescape and substitute variables
	AStackString<> include;
	if ( PerformVariableSubstitutions( stringStart, iter, include ) == false )
	{
		return false;
	}

	iter++; // skip closing quote before returning

	FLOG_INFO( "Including: %s\n", include.Get() );

	// open include

	// 1) Try current directory
	AStackString<> includeToUse;
	if (PathUtils::IsFullPath(include) == false)
	{
		const char * lastSlash = iter.GetFileName().FindLast( NATIVE_SLASH );
		lastSlash = lastSlash ? lastSlash : iter.GetFileName().FindLast( OTHER_SLASH );
		lastSlash = lastSlash ? ( lastSlash + 1 ): iter.GetFileName().Get(); // file only, truncate to empty
		includeToUse.Assign( iter.GetFileName().Get(), lastSlash );
	}
	includeToUse += include;
	AStackString<> includeToUseClean;
	NodeGraph::CleanPath( includeToUse, includeToUseClean );
	FileStream f;
	if ( f.Open( includeToUseClean.Get(), FileStream::READ_ONLY ) == false )
	{
		Error::Error_1032_UnableToOpenInclude( stringStart, includeToUseClean );
		return false;
	}

	// check if include uses "once" pragma
	if ( FBuild::Get().GetDependencyGraph().IsOneUseFile( includeToUseClean ) )
	{
		// already seen, and uses #once : don't include again
		return true;
	}

	uint64_t includeTimeStamp = FileIO::GetFileLastWriteTime( includeToUseClean );

	// read content of include
	const uint32_t fileSize = (uint32_t)f.GetFileSize();
	AutoPtr< char > mem( (char *)ALLOC( fileSize + 1 ) );
	if ( f.Read( mem.Get(), fileSize ) != fileSize )
	{
		Error::Error_1033_ErrorReadingInclude( stringStart, include, Env::GetLastErr() );
		return false;
	}
	mem.Get()[ fileSize ] = '\000'; // sentinel
	BFFParser parser;
	const bool pushStackFrame = false; // include is treated as if injected at this point
	return parser.Parse( mem.Get(), fileSize, includeToUseClean.Get(), includeTimeStamp, pushStackFrame ); 
}