ClassAd *ClassAdXMLParser:: ParseClassAd(ClassAd *classad_in) { bool in_classad; ClassAd *classad = NULL; ClassAd *local_ad = NULL; XMLLexer::Token token; classad = NULL; in_classad = false; while (lexer.PeekToken(&token)) { if (!in_classad) { lexer.ConsumeToken(NULL); if ( token.token_type == XMLLexer::tokenType_Tag && token.tag_id == XMLLexer::tagID_ClassAd) { // We have a ClassAd tag if (token.tag_type == XMLLexer::tagType_Start) { in_classad = true; if ( classad_in ) { classad_in->Clear(); classad = classad_in; } else { local_ad = new ClassAd(); classad = local_ad; } classad->DisableDirtyTracking(); } else { // We're done, return the ClassAd we got, if any. in_classad = false; break; } } } else { if (token.token_type == XMLLexer::tokenType_Tag) { if (token.tag_id == XMLLexer::tagID_Attribute) { if (token.tag_type == XMLLexer::tagType_Invalid) { delete local_ad; return NULL; } else if( token.tag_type == XMLLexer::tagType_Start) { string attribute_name; ExprTree *tree; tree = ParseAttribute(attribute_name); if (tree != NULL) { classad->Insert(attribute_name, tree); } else { delete local_ad; return NULL; } } else { lexer.ConsumeToken(NULL); } } else if (token.tag_id == XMLLexer::tagID_ClassAd) { lexer.ConsumeToken(NULL); if (token.tag_type == XMLLexer::tagType_End) { in_classad = false; break; } else { // This is invalid, but we'll just ignore it. } } else if ( token.tag_id != XMLLexer::tagID_XML && token.tag_id != XMLLexer::tagID_XMLStylesheet && token.tag_id != XMLLexer::tagID_Doctype && token.tag_id != XMLLexer::tagID_ClassAds) { // We got a non-attribute, non-xml thingy within a // ClassAd. That must be an error, but we'll just skip // it in the hopes of recovering. lexer.ConsumeToken(NULL); break; } } else { lexer.ConsumeToken(NULL); } } } if (classad != NULL) { classad->EnableDirtyTracking(); } return classad; }
// ClassAd ::= '[' AttributeList ']' // AttributeList ::= (epsilon) // | Attribute ';' AttributeList // Attribute ::= Identifier '=' Expression bool ClassAdParser:: parseClassAd( ClassAd &ad , bool full ) { Lexer::TokenType tt; Lexer::TokenValue tv; ExprTree *tree = NULL; string s; ad.Clear( ); ad.DisableDirtyTracking(); if( ( tt = lexer.ConsumeToken() ) != Lexer::LEX_OPEN_BOX ) return false; tt = lexer.PeekToken(); while( tt != Lexer::LEX_CLOSE_BOX ) { // Get the name of the expression tt = lexer.ConsumeToken( &tv ); if( tt == Lexer::LEX_SEMICOLON ) { // We allow empty expressions, so if someone give a double semicolon, it doesn't // hurt. Technically it's not right, but we shouldn't make users pay the price for // a meaningless mistake. See condor-support #1881 for a user that was bitten by this. continue; } if( tt != Lexer::LEX_IDENTIFIER ) { CondorErrno = ERR_PARSE_ERROR; CondorErrMsg = "while parsing classad: expected LEX_IDENTIFIER " " but got " + string( Lexer::strLexToken( tt ) ); return false; } // consume the intermediate '=' if( ( tt = lexer.ConsumeToken() ) != Lexer::LEX_BOUND_TO ) { CondorErrno = ERR_PARSE_ERROR; CondorErrMsg = "while parsing classad: expected LEX_BOUND_TO " " but got " + string( Lexer::strLexToken( tt ) ); return false; } // parse the expression parseExpression( tree ); if( tree == NULL ) { return false; } // insert the attribute into the classad tv.GetStringValue( s ); if( !ad.Insert( s, tree ) ) { delete tree; return false; } // the next token must be a ';' or a ']' tt = lexer.PeekToken(); if( tt != Lexer::LEX_SEMICOLON && tt != Lexer::LEX_CLOSE_BOX ) { CondorErrno = ERR_PARSE_ERROR; CondorErrMsg = "while parsing classad: expected LEX_SEMICOLON or " "LEX_CLOSE_BOX but got " + string( Lexer::strLexToken( tt ) ); return( false ); } // Slurp up any extra semicolons. This does not duplicate the work at the top of the loop // because it accounts for the case where the last expression has extra semicolons, // while the first case accounts for optional beginning semicolons. while( tt == Lexer::LEX_SEMICOLON ) { lexer.ConsumeToken(); tt = lexer.PeekToken(); } } lexer.ConsumeToken(); // if a full parse was requested, ensure that input is exhausted if( full && ( lexer.ConsumeToken() != Lexer::LEX_END_OF_INPUT ) ) { CondorErrno = ERR_PARSE_ERROR; CondorErrMsg = "while parsing classad: expected LEX_END_OF_INPUT for " "full parse but got " + string( Lexer::strLexToken( tt ) ); return false; } ad.EnableDirtyTracking(); return true; }