44 template <
typename R >
49 template <
typename R >
55 template <
typename R ,
typename T >
61 template <
typename R ,
typename T >
64 return (
mT ) ( aNode );
67 template <
typename R ,
typename T >
73 template <
typename R ,
typename T >
76 return ( *
mT ) ( aNode );
80 template <
typename R >
83 mRequiredHash ( 0x0000000000000000 ),
84 mForbiddenHash ( 0x0000000000000000 ),
89 template <
typename R >
99 template <
typename R >
104 exception::ContradictoryParserRule lExc;
105 log ( lExc ,
"Contradictory rule for attribute ",
Quote ( aStr ) );
113 template <
typename R >
118 exception::ContradictoryParserRule lExc;
119 log ( lExc ,
"Contradictory rule for attribute ",
Quote ( aStr ) );
127 template <
typename R >
134 template <
typename R >
137 std::set<std::string>::const_iterator lIt;
138 std::stringstream lStr;
144 lStr <<
" {Require : ";
165 lStr <<
" {Forbid : ";
186 lStr <<
" {Optional : ";
206 template <
typename R >
215 exception::NoActionSpecified lExc;
216 log ( lExc ,
"No action specified!" );
222 template <
typename R >
224 mNextHash ( 0x0000000000000001 ),
230 template <
typename R >
237 template <
typename R >
238 template <
typename T >
241 mRules.push_back ( aRule );
242 Rule<R>& lRule ( mRules.back() );
244 for ( std::set<std::string>::iterator lIt = lRule.mRequired.begin() ; lIt != lRule.mRequired.end() ; ++lIt )
246 boost::unordered_map< std::string , uint64_t >::iterator lIt2 ( mHashes.find ( *lIt ) );
248 if ( lIt2 == mHashes.end() )
250 if ( mNextHash == 0x0000000000000000 )
252 exception::TooManyAttributes lExc;
253 log ( lExc ,
"Too many attributes" );
257 lRule.mRequiredHash |= mNextHash;
258 mHashes.insert ( std::make_pair ( *lIt , mNextHash ) );
263 lRule.mRequiredHash |= lIt2->second;
267 for ( std::set<std::string>::iterator lIt = lRule.mForbidden.begin() ; lIt != lRule.mForbidden.end() ; ++lIt )
269 boost::unordered_map< std::string , uint64_t >::iterator lIt2 ( mHashes.find ( *lIt ) );
271 if ( lIt2 == mHashes.end() )
273 if ( mNextHash == 0x0000000000000000 )
275 exception::TooManyAttributes lExc;
276 log ( lExc ,
"Too many attributes" );
280 lRule.mForbiddenHash |= mNextHash;
281 mHashes.insert ( std::make_pair ( *lIt , mNextHash ) );
286 lRule.mForbiddenHash |= lIt2->second;
290 for ( std::set<std::string>::iterator lIt = lRule.mOptional.begin() ; lIt != lRule.mOptional.end() ; ++lIt )
292 boost::unordered_map< std::string , uint64_t >::iterator lIt2 ( mHashes.find ( *lIt ) );
294 if ( lIt2 == mHashes.end() )
296 if ( mNextHash == 0x0000000000000000 )
298 exception::TooManyAttributes lExc;
299 log ( lExc ,
"Too many attributes" );
303 mHashes.insert ( std::make_pair ( *lIt , mNextHash ) );
308 lRule.mRuleId = ++mRuleCounter;
313 template <
typename R >
316 uint64_t lHash ( 0x0000000000000000 );
318 for ( pugi::xml_attribute lAttr = aNode.first_attribute(); lAttr; lAttr = lAttr.next_attribute() )
320 boost::unordered_map< std::string , uint64_t >::iterator lIt2 ( mHashes.find ( lAttr.name() ) );
322 if ( lIt2 == mHashes.end() )
324 exception::UnknownAttribute lExc;
325 log ( lExc ,
"Parser failed because of unknown attribute ",
Quote ( lAttr.name() ) );
329 lHash |= lIt2->second;
332 std::deque< Rule<R>* > lPassed;
333 std::deque< Rule<R>* > lFailedRequired;
334 std::deque< Rule<R>* > lFailedForbidden;
337 for (
typename std::deque<
Rule<R> >::iterator lIt = mRules.begin() ; lIt != mRules.end() ; ++lIt, ++i )
339 if ( lIt->mForbiddenHash & lHash )
341 lFailedForbidden.push_back ( & ( *lIt ) );
343 else if ( lIt->mRequiredHash & ~lHash )
345 lFailedRequired.push_back ( & ( *lIt ) );
350 lPassed.push_back ( & ( *lIt ) );
354 if ( lPassed.size() == 1 )
356 return ( *lPassed.front() ) ( aNode );
359 if ( lPassed.size() > 1 )
361 log (
Warning() ,
"Ambiguity! " ,
Integer ( lPassed.size() ) ,
" rules passed. Attempting to find the rule with the most stringent requirements." );
362 Rule<R>* lMostStringent ( NULL );
363 uint32_t lCounter ( 0 );
365 for (
typename std::deque<
Rule<R>* >::iterator lIt = lPassed.begin(); lIt != lPassed.end(); ++lIt )
367 if ( lCounter < ( **lIt ).mRequired.size() )
369 lMostStringent = ( *lIt );
372 else if ( lCounter == ( **lIt ).mRequired.size() )
374 lMostStringent = NULL;
378 if ( !lMostStringent )
380 exception::AmbiguousParserRules lExc;
381 log ( lExc ,
"Ambiguity remains! Multiple rules passed " ,
Integer ( lCounter ) ,
" requirements." );
386 return ( *lMostStringent ) ( aNode );
389 std::stringstream lStr;
391 for ( pugi::xml_attribute lAttr = aNode.first_attribute(); lAttr; lAttr = lAttr.next_attribute() )
393 lStr << lAttr.name() <<
"=\"" << lAttr.value() <<
"\", ";
396 std::string lString ( lStr.str() );
397 lString.resize ( lString.size() - 2 );
398 exception::NoRulesPassed lExc;
399 log ( lExc ,
"Node with attributes : " , lString ,
" failed all parser rules because : " );
401 for (
typename std::deque<
Rule<R>* >::iterator lIt = lFailedRequired.begin() ; lIt != lFailedRequired.end(); ++lIt )
403 std::stringstream lStr;
404 uint64_t lTemp ( ( **lIt ).mRequiredHash & ~lHash );
406 for ( boost::unordered_map< std::string , uint64_t >::iterator lIt2 = mHashes.begin() ; lIt2 != mHashes.end() ; ++lIt2 )
408 if ( ( lIt2->second ) & lTemp )
410 lStr <<
"\"" << lIt2->first <<
"\", ";
414 std::string lString ( lStr.str() );
415 lString.resize ( lString.size() - 2 );
416 log ( lExc ,
"Rule " ,
Integer ( ( **lIt ).mRuleId ) ,
" requires attributes : " , lString );
419 for (
typename std::deque<
Rule<R>* >::iterator lIt = lFailedForbidden.begin() ; lIt != lFailedForbidden.end(); ++lIt )
421 std::stringstream lStr;
422 uint64_t lTemp ( ( **lIt ).mForbiddenHash & lHash );
424 for ( boost::unordered_map< std::string , uint64_t >::iterator lIt2 = mHashes.begin() ; lIt2 != mHashes.end() ; ++lIt2 )
426 if ( ( lIt2->second ) & lTemp )
428 lStr <<
"\"" << lIt2->first <<
"\", ";
432 std::string lString ( lStr.str() );
433 lString.resize ( lString.size() - 2 );
434 log ( lExc ,
"Rule " ,
Integer ( ( **lIt ).mRuleId ) ,
" forbids attributes : " , lString );
std::set< std::string > mOptional
The optional attributes for this rule.
Rule< R > & optional(const std::string &aStr)
Add an optional attribute to the rule.
std::string description() const
A function to return a string description of the rule.
Class for wrapping bound functions and function objects as an object.
BaseFunctionObject< R > * mFuncPtr
An object wrapping the function pointer for the function to be called when the rule conditions are me...
T mT
The function object or bound function which will be called when the object is evaluated (bracket oper...
uint32_t mRuleId
The ID of the rule.
virtual ~Rule()
Destructor.
R operator()(const pugi::xml_node &aNode)
Functor which converts an XML node to an object of template type R.
_Quote< T > Quote(const T &aT)
Rule< R > & require(const std::string &aStr)
Add a required attribute to the rule.
Parser()
Default constructor.
FunctionObject(T &aT)
Constructor.
Rule for matching XML attributes.
std::set< std::string > mRequired
The required attributes for this rule.
virtual ~BaseFunctionObject()
Destructor.
Rule()
Default constructor.
BaseFunctionObject()
Default constructor.
Rule< R > & forbid(const std::string &aStr)
Add an forbidden attribute to the rule.
std::set< std::string > mForbidden
The forbidden attributes for this rule.
R operator()(const pugi::xml_node &aNode)
Functor which converts an XML node to an object of template type R (Calls the function pointer...
Forward declaration of the Parser so we can declare it friend.
_Integer< T, IntFmt<> > Integer(const T &aT)
Forward declare a function which creates an instance of the ultra-lightweight wrapper from an integer...