/search.css" rel="stylesheet" type="text/css"/> /search.js">
00001 // $Id: ParserGrammar.h,v 1.11 2008/12/08 13:49:57 marcocle Exp $ 00002 // ============================================================================ 00003 #ifndef JOBOPTIONSSVC_PARSERGRAMMAR_H 00004 #define JOBOPTIONSSVC_PARSERGRAMMAR_H 1 00005 // ============================================================================ 00006 // Include files 00007 // ============================================================================ 00008 // STD & STL 00009 // ============================================================================ 00010 #include <string> 00011 #include <vector> 00012 // ============================================================================ 00013 // Boost 00014 // ============================================================================ 00015 #include <boost/spirit.hpp> 00016 #include <boost/bind.hpp> 00017 #include <boost/tuple/tuple.hpp> 00018 // ============================================================================ 00019 #include "Grammars.h" 00020 #include "ToStream.h" 00021 // ============================================================================ 00022 // Local 00023 // ============================================================================ 00024 #include "ParserUtils.h" 00025 #include "ParserActions.h" 00026 // ============================================================================ 00027 namespace Gaudi 00028 { 00029 namespace Parsers 00030 { 00031 // ======================================================================== 00032 using namespace boost::spirit ; 00033 using namespace phoenix; 00034 // ======================================================================== 00035 typedef boost::spirit::position_iterator<std::string::const_iterator> 00036 IteratorT; 00037 // ======================================================================== 00046 class IdentifierGrammar : public grammar 00047 < 00048 IdentifierGrammar, ClosureGrammar<std::string>::context_t 00049 > 00050 { 00051 public: 00052 typedef std::string ResultT; 00053 public: 00054 template <typename ScannerT> 00055 struct definition 00056 { 00057 definition( IdentifierGrammar const &self ) 00058 { 00059 //----------------------------------------------------------------- 00060 // KEYWORDS 00061 //----------------------------------------------------------------- 00062 keywords = 00063 "#include" , 00064 "#units" , 00065 "#ifdef" , 00066 "#ifndef" , 00067 "#endif" , 00068 "#else" , 00069 "WIN32" ; 00070 identifier 00071 = (lexeme_d[ (alpha_p >> *(alnum_p | '_')) 00072 - (keywords >> 00073 (anychar_p - (alnum_p | '_')))]) 00074 [self.val = construct_<std::string>(arg1,arg2)]; 00075 } 00076 symbols<> keywords; 00077 rule<ScannerT> const& start() const 00078 { return identifier; } 00079 rule<ScannerT> identifier; 00080 }; 00081 }; 00082 // ======================================================================== 00091 class PropertyGrammar: public grammar 00092 < 00093 PropertyGrammar, 00094 ClosureGrammar<std::vector<std::string> >::context_t 00095 > 00096 { 00097 public: 00098 typedef std::vector<std::string> ResultT; 00099 public: 00100 template <typename ScannerT> 00101 struct definition 00102 { 00103 definition(PropertyGrammar const &self ) 00104 { 00105 ns = (ident >> *("::">>ident))[ns.val = construct_<std::string>(arg1,arg2)]>>"."; 00106 property = +(ns[PushBack(self.val)]) >> ident[PushBack(self.val)]; 00107 00108 } 00109 IdentifierGrammar ident; 00110 rule<ScannerT> const& start() const 00111 { return property; } 00112 rule<ScannerT,ClosureGrammar<std::string>::context_t> ns; 00113 rule<ScannerT> property; 00114 }; 00115 }; 00116 // ======================================================================== 00126 class RealUnitsGrammar : public boost::spirit::grammar 00127 < RealUnitsGrammar,AttributesClosureGrammar<std::string, 00128 boost::tuple<IteratorT, long double> >::context_t > 00129 { 00130 public: 00131 typedef long double ResultT; 00132 RealUnitsGrammar():m_parser(NULL){} 00133 public: 00134 template <typename ScannerT> 00135 struct definition 00136 { 00137 definition(RealUnitsGrammar const &self) 00138 { 00139 real_literal 00140 = ( 00141 longest_d[grInt[boost::bind(&RealUnitsGrammar::matchReal,&self,_1)] 00142 |grReal[boost::bind(&RealUnitsGrammar::matchReal,&self,_1)]] 00143 >> eps_p[boost::bind(&RealUnitsGrammar::matchPosition,&self,_2)] 00144 >>!(!ch_p('*') 00145 >>grUnit 00146 [boost::bind(&RealUnitsGrammar::matchUnit,&self,_1)] 00147 )) [boost::bind(&RealUnitsGrammar::matchRealUnits,&self)]; 00148 } 00149 RealGrammar<long double> grReal; 00150 IntGrammar<int> grInt; 00151 IdentifierGrammar grUnit; 00152 boost::spirit::rule<ScannerT> const& start() const 00153 { return real_literal; } 00154 boost::spirit::rule<ScannerT> real_literal; 00155 }; 00156 // Action when we recognize real with unit 00157 void matchRealUnits() const 00158 { 00159 val() = Gaudi::Utils::toString ( attrs().get<1>() ); 00160 } 00161 00162 // Action when we recognize real (without unit) 00163 void matchReal(ResultT value) const 00164 { attrs().get<1>()=value; } 00165 00166 // Action for saving position 00167 void matchPosition(IteratorT value) const 00168 { attrs().get<0>()=value; } 00169 00170 // Action when we recognize unit 00171 void matchUnit(const std::string& /*unit*/) const 00172 { 00173 } 00174 00178 void setParser(Parser* parser){m_parser = parser;} 00179 private: 00180 Parser* m_parser; 00181 }; 00182 // ======================================================================== 00183 typedef AttributesClosureGrammar 00184 <boost::tuple<std::string,std::vector<std::string> > , 00185 boost::tuple<int> > ValueClosureT; 00186 // ======================================================================== 00219 class ValueGrammar : public boost::spirit::grammar 00220 <ValueGrammar, ValueClosureT::context_t> 00221 { 00222 public: 00223 ValueGrammar() : m_parser(NULL){} 00224 public: 00229 void matchBrace(bool isopen) const 00230 { 00231 if ( isopen ){ attrs().get<0>()++; } 00232 else { attrs().get<0>()--; } 00233 } 00238 void matchVectorValue(std::string value) const 00239 { if(attrs().get<0>()==1){val().get<1>().push_back(value); } } 00240 00245 void matchValue(std::string value) const{ val().get<0>() = value; } 00246 00248 Parser* parser() const { return m_parser;} 00249 00251 void setParser(Parser* parser){ m_parser = parser; } 00252 00253 public: 00254 00255 template <typename ScannerT> 00256 struct definition 00257 { 00258 definition(ValueGrammar const &self) 00259 { 00260 realunits_grammar.setParser(self.parser()); 00261 //----------------------------------------------------------------- 00262 // OPERATORS 00263 //----------------------------------------------------------------- 00264 chlit<> O_DOT('.'); 00265 chlit<> O_COMMA(','); 00266 value_rule = value[boost::bind(&ValueGrammar::matchValue,&self,_1)]; 00267 value = 00268 vectorvalue[value.val=arg1] 00269 | vector_type[value.val="["+arg1+"]"] 00270 | property_link[value.val=arg1] 00271 ; 00272 // ------------------------------------------------------------------ 00273 vectorvalue_list 00274 = !( 00275 value[vectorvalue_list.val=arg1][boost::bind(&ValueGrammar::matchVectorValue,&self,_1)] 00276 >> *(',' >>value[vectorvalue_list.val+=","+arg1][boost::bind(&ValueGrammar::matchVectorValue,&self,_1)]) 00277 ); 00278 // ------------------------------------------------------------------ 00279 vector_type = 00280 ( 00281 ch_p('{')[boost::bind(&ValueGrammar::matchBrace,&self,true)] 00282 >> vectorvalue_list 00283 [vector_type.val=arg1] 00284 >> ch_p('}')[boost::bind(&ValueGrammar::matchBrace,&self,false)] 00285 ) 00286 | 00287 (ch_p('[') [boost::bind(&ValueGrammar::matchBrace,&self,true)] 00288 >> vectorvalue_list 00289 [vector_type.val=arg1] 00290 >> ch_p(']')[boost::bind(&ValueGrammar::matchBrace,&self,false)] 00291 ); 00292 // ------------------------------------------------------------------ 00293 vectorvalue = 00294 listvalue[vectorvalue.val=arg1] 00295 | longest_d[ 00296 literalvalue[vectorvalue.val=arg1] 00297 | mapvalue[vectorvalue.val=arg1] 00298 ]; 00299 // ------------------------------------------------------------------ 00300 listvalue = '(' >> vectorvalue[listvalue.val="("+arg1] 00301 >> *(O_COMMA[listvalue.val+=","] 00302 >> vectorvalue[listvalue.val+=arg1]) >>ch_p(')')[listvalue.val+=")"]; 00303 // ------------------------------------------------------------------ 00304 mapvalue = literalvalue[mapvalue.val=arg1] 00305 >> (ch_p('=')[mapvalue.val+="="] | ch_p(':')[mapvalue.val+=":"]) 00306 >> value[mapvalue.val+=arg1] 00307 ; 00308 // ------------------------------------------------------------------ 00309 literalvalue = 00310 realunits_grammar[literalvalue.val = arg1] 00311 | 00312 boolean_grammar[AssignBoolToString(literalvalue.val)] 00313 | 00314 string_grammar[literalvalue.val = std::string("\"")+arg1+std::string("\"")]; 00315 // ------------------------------------------------------------------ 00316 property_link = ('@'>>property_grammar) 00317 [property_link.val=construct_<std::string>(arg1,arg2)]; 00318 // ------------------------------------------------------------------ 00319 } 00320 PropertyGrammar property_grammar; 00321 StringGrammar string_grammar; 00322 BoolGrammar boolean_grammar; 00323 IntGrammar<long> int_grammar; 00324 RealUnitsGrammar realunits_grammar; 00325 00326 boost::spirit::rule<ScannerT> value_rule; 00327 boost::spirit::rule 00328 <ScannerT,ClosureGrammar<std::string>::context_t> value,literalvalue, 00329 vectorvalue,listvalue,mapvalue,vectorvalue_list, vector_type, 00330 property_link; 00331 boost::spirit::rule<ScannerT> const& start() const { return value_rule; } 00332 }; 00333 // ============================================================================ 00334 private: 00335 Parser* m_parser; 00336 }; 00337 // ======================================================================== 00338 typedef AttributesClosureGrammar 00339 <IteratorT,boost::tuple<bool,std::string,std::vector<std::string> > > ParserClosureT; 00340 // ======================================================================== 00380 class ParserGrammar : 00381 public grammar<ParserGrammar, ParserClosureT::context_t> { 00382 public: 00387 ParserGrammar(Parser* parser){m_parser=parser;} 00388 virtual ~ParserGrammar() {} 00389 00391 Parser* parser() const {return m_parser;} 00392 00397 void matchInclude(const std::string& fileName) const{ 00398 if(!doActions()) return; 00399 file_position fpos = this->val().get_position(); 00400 Position pos(fpos.file,fpos.line,fpos.column); 00401 m_parser->matchInclude(fileName,pos); 00402 } 00406 void matchUnits(const std::string& /*fileName*/) const{ 00407 } 00415 void matchAssign(std::vector<std::string> params) const{ 00416 if(!doActions()) return; 00417 00418 // position where statement appears 00419 file_position fpos = val().get_position(); 00420 Position pos(fpos.file,fpos.line,fpos.column); 00421 00422 // get value representation. It's two modes string and vector of strings 00423 std::string value = attrs().get<1>(); 00424 std::vector<std::string> vectorValues = attrs().get<2>(); 00425 00426 // check if value is vector 00427 bool isVector = false; 00428 if(vectorValues.size()>0 || value=="[]"){ 00429 isVector = true; 00430 }else{ 00431 vectorValues.push_back(value); 00432 } 00433 00434 // extract object, option name and sign 00435 std::string objectName; 00436 std::string delim; 00437 std::vector< std::string >::const_iterator cur; 00438 for ( cur = params.begin(); 00439 *(cur+1) != "#"; cur++ ){ 00440 objectName += delim + *cur; 00441 delim = "."; 00442 } 00443 00444 std::string optionName = *cur; 00445 std::string sign = *(cur+2); 00446 00447 Parser::Sign oper; 00448 if(sign == "+="){ 00449 oper = Parser::S_PLUSASSIGN; 00450 }else if(sign == "-="){ 00451 oper = Parser::S_MINUSASSIGN; 00452 }else{ 00453 oper = Parser::S_ASSIGN; 00454 } 00455 00456 m_parser->matchAssign 00457 (objectName, optionName, oper, 00458 vectorValues,pos,isVector); 00459 vectorValues.clear(); 00460 } 00461 // ====================================================================== 00466 void matchPlatform(const std::string& directive) const{ 00467 if(directive=="endif" || directive=="ifndef"){ 00468 attrs().get<0>() = true; 00469 } else { 00470 attrs().get<0>() = !attrs().get<0>(); 00471 } 00472 } 00473 // ====================================================================== 00478 void matchPrint(bool on) const{ 00479 file_position fpos = this->val().get_position(); 00480 Position pos(fpos.file,fpos.line,fpos.column); 00481 m_parser->setIsPrint(on,pos); 00482 } 00483 // ====================================================================== 00488 void matchPrintOptions(bool on) const{ 00489 file_position fpos = this->val().get_position(); 00490 Position pos(fpos.file,fpos.line,fpos.column); 00491 m_parser->setIsPrintOptions(on,pos); 00492 } 00493 // ====================================================================== 00498 void matchValue(boost::tuple<std::string,std::vector<std::string> > value) const{ 00499 if(!doActions()) return; 00500 attrs().get<1>() = value.get<0>(); 00501 attrs().get<2>() = value.get<1>(); 00502 } 00503 // ====================================================================== 00507 bool doActions() const{ return attrs().get<0>();} 00508 // ====================================================================== 00509 template <typename ScannerT> 00510 struct definition { 00511 00512 definition(ParserGrammar const &self) { 00513 value_grammar.setParser(self.parser()); 00514 boost::tuples::get<0>(self.attrs()) = true; 00515 // ------------------------------------------------------------------ 00516 // OPERATORS 00517 // ------------------------------------------------------------------ 00518 chlit<> O_SEMI(';'); 00519 chlit<> O_DOT('.'); 00520 00521 strlit<> O_ASSIGN("="); 00522 strlit<> O_PLUSASSIGN("+="); 00523 strlit<> O_MINUSASSIGN("-="); 00524 00525 // ------------------------------------------------------------------ 00526 // TOKENS 00527 // ------------------------------------------------------------------ 00528 strlit<> T_SHELL("#!"); 00529 strlit<> T_IFDEF("#ifdef"); 00530 strlit<> T_IFNDEF("#ifndef"); 00531 strlit<> T_ELSE("#else"); 00532 strlit<> T_ENDIF("#endif"); 00533 strlit<> T_WIN32("WIN32"); 00534 strlit<> T_INCLUDE("#include"); 00535 strlit<> T_UNITS("#units"); 00536 strlit<> T_PRAGMA("#pragma"); 00537 strlit<> T_PRINTOPTIONS("#printOptions"); 00538 // ------------------------------------------------------------------ 00539 job_options_file = 00540 !shell_statement >> *(platform_statement | platform_dependency); 00541 // ------------------------------------------------------------------ 00542 shell_statement = comment_p(T_SHELL); 00543 // ------------------------------------------------------------------ 00544 platform_statement = assertable_statement | pragma_statement; 00545 // ------------------------------------------------------------------ 00546 assertable_statement = 00547 include_statement 00548 [boost::bind(&ParserGrammar::matchInclude,&self,_1)] 00549 | units_statement 00550 [boost::bind(&ParserGrammar::matchUnits,&self,_1)] 00551 | assign_statement 00552 [boost::bind(&ParserGrammar::matchAssign,&self,_1)]; 00553 // ------------------------------------------------------------------ 00554 assertion_statement = 00555 T_IFDEF 00556 [boost::bind(&ParserGrammar::matchPlatform,&self,"ifdef")] 00557 | 00558 T_IFNDEF 00559 [boost::bind(&ParserGrammar::matchPlatform,&self,"ifndef")]; 00560 // ------------------------------------------------------------------ 00561 platform_dependency = 00562 assertion_statement 00563 >> T_WIN32 00564 >> *platform_statement 00565 >> !( 00566 T_ELSE[boost::bind(&ParserGrammar::matchPlatform,&self,"else")] 00567 >> *platform_statement 00568 ) 00569 >> T_ENDIF 00570 [boost::bind(&ParserGrammar::matchPlatform,&self,"endif")]; 00571 // ------------------------------------------------------------------ 00572 include_statement = 00573 T_INCLUDE 00574 >> (string_grammar[include_statement.val=arg1]>>eps_p) 00575 [self.val=arg1]; 00576 // ------------------------------------------------------------------ 00577 units_statement = 00578 T_UNITS 00579 >> (string_grammar[units_statement.val=arg1]>>eps_p) 00580 [self.val=arg1];; 00581 // ------------------------------------------------------------------ 00582 pragma_statement = pragma | printopt_statement; 00583 // ------------------------------------------------------------------ 00584 pragma = (T_PRAGMA>>eps_p)[self.val=arg1] >> str_p("print") 00585 >> ((str_p("on") | str_p("ON")) 00586 [boost::bind(&ParserGrammar::matchPrint,&self,true)] 00587 | (str_p("off") | str_p("OFF")) 00588 [boost::bind(&ParserGrammar::matchPrint,&self,false)]) ; 00589 // ------------------------------------------------------------------ 00590 printopt_statement = ((T_PRINTOPTIONS>>eps_p)[self.val = arg1] >> 00591 !as_lower_d["full"]) 00592 [boost::bind(&ParserGrammar::matchPrintOptions,&self,true)]; 00593 // ------------------------------------------------------------------ 00594 assign_statement = 00595 property_grammar[assign_statement.val=arg1] 00596 >> eps_p[PushBack(assign_statement.val,"#")] 00597 >> ( 00598 O_ASSIGN[PushBack(assign_statement.val,"=")] 00599 |O_PLUSASSIGN[PushBack(assign_statement.val,"+=")] 00600 |O_MINUSASSIGN[PushBack(assign_statement.val,"-=")] 00601 ) 00602 >> value_grammar[boost::bind(&ParserGrammar::matchValue,&self,_1)] 00603 >> O_SEMI; 00604 // ------------------------------------------------------------------ 00605 } 00606 // -------------------------------------------------------------------- 00607 PropertyGrammar property_grammar; 00608 IdentifierGrammar identifier_grammar; 00609 StringGrammar string_grammar; 00610 ValueGrammar value_grammar; 00611 // -------------------------------------------------------------------- 00612 rule<ScannerT,ClosureGrammar<std::string>::context_t> include_statement, 00613 units_statement; 00614 00615 rule<ScannerT,ClosureGrammar<std::vector<std::string> >::context_t> assign_statement; 00616 00617 rule<ScannerT> 00618 job_options_file, 00619 shell_statement, 00620 platform_statement, 00621 assertable_statement, 00622 assertion_statement, 00623 platform_dependency, 00624 pragma_statement, 00625 pragma, 00626 printopt_statement; 00627 // -------------------------------------------------------------------- 00628 rule<ScannerT> const& start() const { 00629 return job_options_file; 00630 } 00631 // -------------------------------------------------------------------- 00632 }; 00633 // ====================================================================== 00634 private: 00635 Parser* m_parser; 00636 }; 00637 } // end of namespace Parsers 00638 } // end of namespace Gaudi 00639 // ============================================================================ 00640 // The END 00641 // ============================================================================ 00642 #endif // JOBOPTIONSSVC_PARSERGRAMMAR_H 00643 // ============================================================================ 00644