int Set_List<DataType>::isSubsetOf(const Set_List<DataType> &set) const { // check if this set is a subset of another set ListIterator<DataType> subIter(list); ListIterator<DataType> setIter(set.list); while (!subIter.done() && !setIter.done()) { if (subIter() == setIter()) { // both are equal, increment both iterators setIter++; subIter++; } else if (subIter() > setIter()) { // increment set to match sub. setIter++; } else { // a member was not found return(0); } } if (subIter.done()) return(1); else return(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; }
// 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; }
// ParseFunction //------------------------------------------------------------------------------ /*virtual*/ bool Function::ParseFunction( NodeGraph & nodeGraph, 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( nodeGraph ); 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( nodeGraph, functionNameStart ); }
//------------------------------------------------------------------------------ /*virtual*/ bool FunctionForEach::ParseFunction( NodeGraph & nodeGraph, const BFFIterator & functionNameStart, const BFFIterator * functionBodyStartToken, const BFFIterator * functionBodyStopToken, const BFFIterator * functionHeaderStartToken, const BFFIterator * functionHeaderStopToken ) const { // build array for each pair to loop through Array< AString > localNames( 4, true ); Array< const BFFVariable * > arrayVars( 4, true ); int loopLen = -1; // parse it all out BFFIterator pos( *functionHeaderStartToken ); pos++; // skip opening token while ( pos < *functionHeaderStopToken ) { pos.SkipWhiteSpace(); if ( *pos != BFFParser::BFF_DECLARE_VAR_INTERNAL ) { Error::Error_1200_ExpectedVar( pos, this ); return false; } const BFFIterator arrayVarNameBegin = pos; AStackString< BFFParser::MAX_VARIABLE_NAME_LENGTH > localName; bool localParentScope = false; // always false thanks to the previous test if ( BFFParser::ParseVariableName( pos, localName, localParentScope ) == false ) { return false; } ASSERT( false == localParentScope ); localNames.Append( localName ); pos.SkipWhiteSpace(); // check for "in" token bool foundIn = false; if ( *pos == 'i' ) { pos++; if ( *pos == 'n' ) { foundIn = true; } } if ( foundIn == false ) { Error::Error_1201_MissingIn( pos, this ); return false; } pos++; pos.SkipWhiteSpace(); if ( *pos != BFFParser::BFF_DECLARE_VAR_INTERNAL && *pos != BFFParser::BFF_DECLARE_VAR_PARENT /* tolerant with parent vars */ ) { Error::Error_1202_ExpectedVarFollowingIn( pos, this ); return false; } const BFFIterator arrayNameStart( pos ); AStackString< BFFParser::MAX_VARIABLE_NAME_LENGTH > arrayVarName; bool arrayParentScope = false; if ( BFFParser::ParseVariableName( pos, arrayVarName, arrayParentScope ) == false ) { return false; } const BFFVariable * var = nullptr; BFFStackFrame * const arrayFrame = ( arrayParentScope ) ? BFFStackFrame::GetParentDeclaration( arrayVarName, BFFStackFrame::GetCurrent()->GetParent(), var ) : nullptr; if ( false == arrayParentScope ) { var = BFFStackFrame::GetVar( arrayVarName, nullptr ); } if ( ( arrayParentScope && ( nullptr == arrayFrame ) ) || ( var == nullptr ) ) { Error::Error_1009_UnknownVariable( arrayNameStart, this, arrayVarName ); return false; } // it can be of any supported type if ( ( var->IsArrayOfStrings() == false ) && ( var->IsArrayOfStructs() == false ) ) { Error::Error_1050_PropertyMustBeOfType( arrayVarNameBegin, this, arrayVarName.Get(), var->GetType(), BFFVariable::VAR_ARRAY_OF_STRINGS, BFFVariable::VAR_ARRAY_OF_STRUCTS ); return false; } // is this the first variable? int thisArrayLen( -1 ); if ( var->GetType() == BFFVariable::VAR_ARRAY_OF_STRINGS ) { thisArrayLen = (int)var->GetArrayOfStrings().GetSize(); } else if ( var->GetType() == BFFVariable::VAR_ARRAY_OF_STRUCTS ) { thisArrayLen = (int)var->GetArrayOfStructs().GetSize(); } else { ASSERT( false ); } if ( loopLen == -1 ) { // it will set the length of looping loopLen = thisArrayLen; } else { // variables after the first must match length of the first if ( loopLen != thisArrayLen ) { Error::Error_1204_LoopVariableLengthsDiffer( arrayVarNameBegin, this, arrayVarName.Get(), (uint32_t)thisArrayLen, (uint32_t)loopLen ); return false; } } arrayVars.Append( var ); // skip optional separator pos.SkipWhiteSpace(); if ( *pos == ',' ) { pos++; } } ASSERT( localNames.GetSize() == arrayVars.GetSize() ); // gracefully allow empty loops if ( loopLen < 1 ) { return true; } // freeze the variable to avoid modifications while looping for ( uint32_t j=0; j<arrayVars.GetSize(); ++j ) { arrayVars[ j ]->Freeze(); FLOG_INFO( "Freezing loop array '%s' of type <%s>", arrayVars[j]->GetName().Get(), BFFVariable::GetTypeName( arrayVars[j]->GetType() ) ); } bool succeed = true; for ( uint32_t i=0; i<(uint32_t)loopLen; ++i ) { // create local loop variables BFFStackFrame loopStackFrame; for ( uint32_t j=0; j<localNames.GetSize(); ++j ) { if ( arrayVars[ j ]->GetType() == BFFVariable::VAR_ARRAY_OF_STRINGS ) { BFFStackFrame::SetVarString( localNames[ j ], arrayVars[ j ]->GetArrayOfStrings()[ i ], &loopStackFrame ); } else if ( arrayVars[ j ]->GetType() == BFFVariable::VAR_ARRAY_OF_STRUCTS ) { BFFStackFrame::SetVarStruct( localNames[ j ], arrayVars[ j ]->GetArrayOfStructs()[ i ]->GetStructMembers(), &loopStackFrame ); } else { ASSERT( false ); } } // parse the function body BFFParser subParser( nodeGraph ); BFFIterator subIter( *functionBodyStartToken ); subIter++; // skip opening token subIter.SetMax( functionBodyStopToken->GetCurrent() ); // limit to closing token if ( subParser.Parse( subIter ) == false ) { succeed = false; break; } // complete the function if ( Commit( nodeGraph, functionNameStart ) == false ) { succeed = false; break; } } // unfreeze all array variables for ( uint32_t j=0; j<arrayVars.GetSize(); ++j ) { arrayVars[ j ]->Unfreeze(); FLOG_INFO( "Unfreezing loop array '%s' of type <%s>", arrayVars[j]->GetName().Get(), BFFVariable::GetTypeName( arrayVars[j]->GetType() ) ); } return succeed; }