![]() |
|
|
Generated: 24 Nov 2008 |
00001 // $Id: ParserGrammar.h,v 1.10 2007/10/02 09:42:59 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 // GaudiKernel 00020 // ============================================================================ 00021 #include "GaudiKernel/Grammars.h" 00022 #include "GaudiKernel/ToStream.h" 00023 // ============================================================================ 00024 // Local 00025 // ============================================================================ 00026 #include "ParserUtils.h" 00027 #include "ParserActions.h" 00028 // ============================================================================ 00029 namespace Gaudi 00030 { 00031 namespace Parsers 00032 { 00033 // ======================================================================== 00034 using namespace boost::spirit ; 00035 using namespace phoenix; 00036 // ======================================================================== 00037 typedef boost::spirit::position_iterator<std::string::const_iterator> 00038 IteratorT; 00039 // ======================================================================== 00048 class IdentifierGrammar : public grammar 00049 < 00050 IdentifierGrammar, ClosureGrammar<std::string>::context_t 00051 > 00052 { 00053 public: 00054 typedef std::string ResultT; 00055 public: 00056 template <typename ScannerT> 00057 struct definition 00058 { 00059 definition( IdentifierGrammar const &self ) 00060 { 00061 //----------------------------------------------------------------- 00062 // KEYWORDS 00063 //----------------------------------------------------------------- 00064 keywords = 00065 "#include" , 00066 "#units" , 00067 "#ifdef" , 00068 "#ifndef" , 00069 "#endif" , 00070 "#else" , 00071 "WIN32" ; 00072 identifier 00073 = (lexeme_d[ (alpha_p >> *(alnum_p | '_')) 00074 - (keywords >> 00075 anychar_p - (alnum_p | '_'))]) 00076 [self.val = construct_<std::string>(arg1,arg2)]; 00077 } 00078 symbols<> keywords; 00079 rule<ScannerT> const& start() const 00080 { return identifier; } 00081 rule<ScannerT> identifier; 00082 }; 00083 }; 00084 // ======================================================================== 00093 class PropertyGrammar: public grammar 00094 < 00095 PropertyGrammar, 00096 ClosureGrammar<std::vector<std::string> >::context_t 00097 > 00098 { 00099 public: 00100 typedef std::vector<std::string> ResultT; 00101 public: 00102 template <typename ScannerT> 00103 struct definition 00104 { 00105 definition(PropertyGrammar const &self ) 00106 { 00107 ns = (ident >> *("::">>ident))[ns.val = construct_<std::string>(arg1,arg2)]>>"."; 00108 property = +(ns[PushBack(self.val)]) >> ident[PushBack(self.val)]; 00109 00110 } 00111 IdentifierGrammar ident; 00112 rule<ScannerT> const& start() const 00113 { return property; } 00114 rule<ScannerT,ClosureGrammar<std::string>::context_t> ns; 00115 rule<ScannerT> property; 00116 }; 00117 }; 00118 // ======================================================================== 00128 class RealUnitsGrammar : public boost::spirit::grammar 00129 < RealUnitsGrammar,AttributesClosureGrammar<std::string, 00130 boost::tuple<IteratorT, long double> >::context_t > 00131 { 00132 public: 00133 typedef long double ResultT; 00134 RealUnitsGrammar():m_parser(NULL){} 00135 public: 00136 template <typename ScannerT> 00137 struct definition 00138 { 00139 definition(RealUnitsGrammar const &self) 00140 { 00141 real_literal 00142 = ( 00143 longest_d[grInt[boost::bind(&RealUnitsGrammar::matchReal,&self,_1)] 00144 |grReal[boost::bind(&RealUnitsGrammar::matchReal,&self,_1)]] 00145 >> eps_p[boost::bind(&RealUnitsGrammar::matchPosition,&self,_2)] 00146 >>!(!ch_p('*') 00147 >>grUnit 00148 [boost::bind(&RealUnitsGrammar::matchUnit,&self,_1)] 00149 )) [boost::bind(&RealUnitsGrammar::matchRealUnits,&self)]; 00150 } 00151 RealGrammar<long double> grReal; 00152 IntGrammar<int> grInt; 00153 IdentifierGrammar grUnit; 00154 boost::spirit::rule<ScannerT> const& start() const 00155 { return real_literal; } 00156 boost::spirit::rule<ScannerT> real_literal; 00157 }; 00158 // Action when we recognize real with unit 00159 void matchRealUnits() const 00160 { 00161 val() = Gaudi::Utils::toString ( attrs().get<1>() ); 00162 } 00163 00164 // Action when we recognize real (without unit) 00165 void matchReal(ResultT value) const 00166 { attrs().get<1>()=value; } 00167 00168 // Action for saving position 00169 void matchPosition(IteratorT value) const 00170 { attrs().get<0>()=value; } 00171 00172 // Action when we recognize unit 00173 void matchUnit(const std::string& unit) const 00174 { 00175 if (NULL == m_parser) return; 00176 file_position fpos = attrs().get<0>().get_position(); 00177 Position pos(fpos.file,fpos.line,fpos.column); 00178 00179 attrs().get<1>() *= m_parser->matchUnit(unit,pos); 00180 } 00181 00185 void setParser(Parser* parser){m_parser = parser;} 00186 private: 00187 Parser* m_parser; 00188 }; 00189 // ======================================================================== 00205 class UnitsFileGrammar : public boost::spirit::grammar 00206 < 00207 UnitsFileGrammar, AttributesClosureGrammar<IteratorT, 00208 boost::tuple<std::string,double> >::context_t > 00209 { 00210 public: 00215 UnitsFileGrammar(Parser* parser) 00216 : m_parser(parser) {} 00217 public: 00219 void matchUnit() const 00220 { 00221 file_position fpos = val().get_position(); 00222 m_parser->matchUnitEntry 00223 (attrs().get<0>(),attrs().get<1>(), 00224 Position(fpos.file,fpos.line,fpos.column)); 00225 attrs().get<1>() = 1; 00226 } 00231 void matchLeftReal(double real) const 00232 { attrs().get<1>() = real; } 00233 00238 void matchLeftUnit(std::string newunit) const 00239 { attrs().get<0>() = newunit; } 00240 00245 void matchRight(std::string value) const 00246 { attrs().get<1>() = 00247 boost::lexical_cast<double>(value)/attrs().get<1>(); } 00248 public: 00249 template <typename ScannerT> 00250 struct definition 00251 { 00252 definition(UnitsFileGrammar const &self) 00253 { 00254 boost::tuples::get<1>(self.attrs()) = 1; 00255 grUnit.setParser(self.parser()); 00256 units_file = *(unit[boost::bind(&UnitsFileGrammar::matchUnit,&self)]); 00257 unit = 00258 (real_p[boost::bind(&UnitsFileGrammar::matchLeftReal,&self,_1)] 00259 >> eps_p)[self.val=arg1] >> !ch_p('*') 00260 >>grNewUnit[boost::bind(&UnitsFileGrammar::matchLeftUnit,&self,_1)] 00261 >>"=">>grUnit[boost::bind(&UnitsFileGrammar::matchRight,&self,_1)]; 00262 } 00263 RealUnitsGrammar grUnit; 00264 IdentifierGrammar grNewUnit; 00265 boost::spirit::rule<ScannerT> const& start() const 00266 { return units_file;} 00267 boost::spirit::rule<ScannerT> units_file,unit; 00268 }; 00269 public: 00271 Parser* parser() const{ return m_parser;} 00272 private: 00273 Parser* m_parser; 00274 }; 00275 // ======================================================================== 00276 typedef AttributesClosureGrammar 00277 <boost::tuple<std::string,std::vector<std::string> > , 00278 boost::tuple<int> > ValueClosureT; 00279 // ======================================================================== 00312 class ValueGrammar : public boost::spirit::grammar 00313 <ValueGrammar, ValueClosureT::context_t> 00314 { 00315 public: 00316 ValueGrammar() : m_parser(NULL){} 00317 public: 00322 void matchBrace(bool isopen) const 00323 { 00324 if ( isopen ){ attrs().get<0>()++; } 00325 else { attrs().get<0>()--; } 00326 } 00331 void matchVectorValue(std::string value) const 00332 { if(attrs().get<0>()==1){val().get<1>().push_back(value); } } 00333 00338 void matchValue(std::string value) const{ val().get<0>() = value; } 00339 00341 Parser* parser() const { return m_parser;} 00342 00344 void setParser(Parser* parser){ m_parser = parser; } 00345 00346 public: 00347 00348 template <typename ScannerT> 00349 struct definition 00350 { 00351 definition(ValueGrammar const &self) 00352 { 00353 realunits_grammar.setParser(self.parser()); 00354 //----------------------------------------------------------------- 00355 // OPERATORS 00356 //----------------------------------------------------------------- 00357 chlit<> O_DOT('.'); 00358 chlit<> O_COMMA(','); 00359 value_rule = value[boost::bind(&ValueGrammar::matchValue,&self,_1)]; 00360 value = 00361 vectorvalue[value.val=arg1] 00362 | vector_type[value.val="["+arg1+"]"] 00363 | property_link[value.val=arg1] 00364 ; 00365 // ------------------------------------------------------------------ 00366 vectorvalue_list 00367 = !( 00368 value[vectorvalue_list.val=arg1][boost::bind(&ValueGrammar::matchVectorValue,&self,_1)] 00369 >> *(',' >>value[vectorvalue_list.val+=","+arg1][boost::bind(&ValueGrammar::matchVectorValue,&self,_1)]) 00370 ); 00371 // ------------------------------------------------------------------ 00372 vector_type = 00373 ( 00374 ch_p('{')[boost::bind(&ValueGrammar::matchBrace,&self,true)] 00375 >> vectorvalue_list 00376 [vector_type.val=arg1] 00377 >> ch_p('}')[boost::bind(&ValueGrammar::matchBrace,&self,false)] 00378 ) 00379 | 00380 (ch_p('[') [boost::bind(&ValueGrammar::matchBrace,&self,true)] 00381 >> vectorvalue_list 00382 [vector_type.val=arg1] 00383 >> ch_p(']')[boost::bind(&ValueGrammar::matchBrace,&self,false)] 00384 ); 00385 // ------------------------------------------------------------------ 00386 vectorvalue = 00387 listvalue[vectorvalue.val=arg1] 00388 | longest_d[ 00389 literalvalue[vectorvalue.val=arg1] 00390 | mapvalue[vectorvalue.val=arg1] 00391 ]; 00392 // ------------------------------------------------------------------ 00393 listvalue = '(' >> vectorvalue[listvalue.val="("+arg1] 00394 >> *(O_COMMA[listvalue.val+=","] 00395 >> vectorvalue[listvalue.val+=arg1]) >>ch_p(')')[listvalue.val+=")"]; 00396 // ------------------------------------------------------------------ 00397 mapvalue = literalvalue[mapvalue.val=arg1] 00398 >> (ch_p('=')[mapvalue.val+="="] | ch_p(':')[mapvalue.val+=":"]) 00399 >> value[mapvalue.val+=arg1] 00400 ; 00401 // ------------------------------------------------------------------ 00402 literalvalue = 00403 realunits_grammar[literalvalue.val = arg1] 00404 | 00405 boolean_grammar[AssignBoolToString(literalvalue.val)] 00406 | 00407 string_grammar[literalvalue.val = std::string("\"")+arg1+std::string("\"")]; 00408 // ------------------------------------------------------------------ 00409 property_link = ('@'>>property_grammar) 00410 [property_link.val=construct_<std::string>(arg1,arg2)]; 00411 // ------------------------------------------------------------------ 00412 } 00413 PropertyGrammar property_grammar; 00414 StringGrammar string_grammar; 00415 BoolGrammar boolean_grammar; 00416 IntGrammar<long> int_grammar; 00417 RealUnitsGrammar realunits_grammar; 00418 00419 boost::spirit::rule<ScannerT> value_rule; 00420 boost::spirit::rule 00421 <ScannerT,ClosureGrammar<std::string>::context_t> value,literalvalue, 00422 vectorvalue,listvalue,mapvalue,vectorvalue_list, vector_type, 00423 property_link; 00424 boost::spirit::rule<ScannerT> const& start() const { return value_rule; } 00425 }; 00426 // ============================================================================ 00427 private: 00428 Parser* m_parser; 00429 }; 00430 // ======================================================================== 00431 typedef AttributesClosureGrammar 00432 <IteratorT,boost::tuple<bool,std::string,std::vector<std::string> > > ParserClosureT; 00433 // ======================================================================== 00473 class ParserGrammar : 00474 public grammar<ParserGrammar, ParserClosureT::context_t> { 00475 public: 00480 ParserGrammar(Parser* parser){m_parser=parser;} 00481 virtual ~ParserGrammar() {} 00482 00484 Parser* parser() const {return m_parser;} 00485 00490 void matchInclude(const std::string& fileName) const{ 00491 if(!doActions()) return; 00492 file_position fpos = this->val().get_position(); 00493 Position pos(fpos.file,fpos.line,fpos.column); 00494 m_parser->matchInclude(fileName,pos); 00495 } 00499 void matchUnits(const std::string& fileName) const{ 00500 if(!doActions()) return; 00501 file_position fpos = this->val().get_position(); 00502 Position pos(fpos.file,fpos.line,fpos.column); 00503 m_parser->matchUnits(fileName,pos); 00504 } 00512 void matchAssign(std::vector<std::string> params) const{ 00513 if(!doActions()) return; 00514 00515 // position where statement appears 00516 file_position fpos = val().get_position(); 00517 Position pos(fpos.file,fpos.line,fpos.column); 00518 00519 // get value representation. It's two modes string and vector of strings 00520 std::string value = attrs().get<1>(); 00521 std::vector<std::string> vectorValues = attrs().get<2>(); 00522 00523 // check if value is vector 00524 bool isVector = false; 00525 if(vectorValues.size()>0 || value=="[]"){ 00526 isVector = true; 00527 }else{ 00528 vectorValues.push_back(value); 00529 } 00530 00531 // extract object, option name and sign 00532 std::string objectName; 00533 std::string delim; 00534 std::vector< std::string >::const_iterator cur; 00535 for ( cur = params.begin(); 00536 *(cur+1) != "#"; cur++ ){ 00537 objectName += delim + *cur; 00538 delim = "."; 00539 } 00540 00541 std::string optionName = *cur; 00542 std::string sign = *(cur+2); 00543 00544 Parser::Sign oper; 00545 if(sign == "+="){ 00546 oper = Parser::S_PLUSASSIGN; 00547 }else if(sign == "-="){ 00548 oper = Parser::S_MINUSASSIGN; 00549 }else{ 00550 oper = Parser::S_ASSIGN; 00551 } 00552 00553 m_parser->matchAssign 00554 (objectName, optionName, oper, 00555 vectorValues,pos,isVector); 00556 vectorValues.clear(); 00557 } 00558 // ====================================================================== 00563 void matchPlatform(const std::string& directive) const{ 00564 bool iswin = Gaudi::Parsers::Utils::isWin(); 00565 if(directive=="endif" || (directive=="ifdef" && iswin) 00566 || (directive=="ifndef" && !iswin)){ 00567 attrs().get<0>() = true; 00568 } else { 00569 attrs().get<0>() = !attrs().get<0>(); 00570 } 00571 } 00572 // ====================================================================== 00577 void matchPrint(bool on) const{ 00578 file_position fpos = this->val().get_position(); 00579 Position pos(fpos.file,fpos.line,fpos.column); 00580 m_parser->setIsPrint(on,pos); 00581 } 00582 // ====================================================================== 00587 void matchPrintOptions(bool on) const{ 00588 file_position fpos = this->val().get_position(); 00589 Position pos(fpos.file,fpos.line,fpos.column); 00590 m_parser->setIsPrintOptions(on,pos); 00591 } 00592 // ====================================================================== 00597 void matchValue(boost::tuple<std::string,std::vector<std::string> > value) const{ 00598 if(!doActions()) return; 00599 attrs().get<1>() = value.get<0>(); 00600 attrs().get<2>() = value.get<1>(); 00601 } 00602 // ====================================================================== 00606 bool doActions() const{ return attrs().get<0>();} 00607 // ====================================================================== 00608 template <typename ScannerT> 00609 struct definition { 00610 00611 definition(ParserGrammar const &self) { 00612 value_grammar.setParser(self.parser()); 00613 boost::tuples::get<0>(self.attrs()) = true; 00614 // ------------------------------------------------------------------ 00615 // OPERATORS 00616 // ------------------------------------------------------------------ 00617 chlit<> O_SEMI(';'); 00618 chlit<> O_DOT('.'); 00619 00620 strlit<> O_ASSIGN("="); 00621 strlit<> O_PLUSASSIGN("+="); 00622 strlit<> O_MINUSASSIGN("-="); 00623 00624 // ------------------------------------------------------------------ 00625 // TOKENS 00626 // ------------------------------------------------------------------ 00627 strlit<> T_SHELL("#!"); 00628 strlit<> T_IFDEF("#ifdef"); 00629 strlit<> T_IFNDEF("#ifndef"); 00630 strlit<> T_ELSE("#else"); 00631 strlit<> T_ENDIF("#endif"); 00632 strlit<> T_WIN32("WIN32"); 00633 strlit<> T_INCLUDE("#include"); 00634 strlit<> T_UNITS("#units"); 00635 strlit<> T_PRAGMA("#pragma"); 00636 strlit<> T_PRINTOPTIONS("#printOptions"); 00637 // ------------------------------------------------------------------ 00638 job_options_file = 00639 !shell_statement >> *(platform_statement | platform_dependency); 00640 // ------------------------------------------------------------------ 00641 shell_statement = comment_p(T_SHELL); 00642 // ------------------------------------------------------------------ 00643 platform_statement = assertable_statement | pragma_statement; 00644 // ------------------------------------------------------------------ 00645 assertable_statement = 00646 include_statement 00647 [boost::bind(&ParserGrammar::matchInclude,&self,_1)] 00648 | units_statement 00649 [boost::bind(&ParserGrammar::matchUnits,&self,_1)] 00650 | assign_statement 00651 [boost::bind(&ParserGrammar::matchAssign,&self,_1)]; 00652 // ------------------------------------------------------------------ 00653 assertion_statement = 00654 T_IFDEF 00655 [boost::bind(&ParserGrammar::matchPlatform,&self,"ifdef")] 00656 | 00657 T_IFNDEF 00658 [boost::bind(&ParserGrammar::matchPlatform,&self,"ifndef")]; 00659 // ------------------------------------------------------------------ 00660 platform_dependency = 00661 assertion_statement 00662 >> T_WIN32 00663 >> *platform_statement 00664 >> !( 00665 T_ELSE[boost::bind(&ParserGrammar::matchPlatform,&self,"else")] 00666 >> *platform_statement 00667 ) 00668 >> T_ENDIF 00669 [boost::bind(&ParserGrammar::matchPlatform,&self,"endif")]; 00670 // ------------------------------------------------------------------ 00671 include_statement = 00672 T_INCLUDE 00673 >> (string_grammar[include_statement.val=arg1]>>eps_p) 00674 [self.val=arg1]; 00675 // ------------------------------------------------------------------ 00676 units_statement = 00677 T_UNITS 00678 >> (string_grammar[units_statement.val=arg1]>>eps_p) 00679 [self.val=arg1];; 00680 // ------------------------------------------------------------------ 00681 pragma_statement = pragma | printopt_statement; 00682 // ------------------------------------------------------------------ 00683 pragma = (T_PRAGMA>>eps_p)[self.val=arg1] >> str_p("print") 00684 >> ((str_p("on") | str_p("ON")) 00685 [boost::bind(&ParserGrammar::matchPrint,&self,true)] 00686 | (str_p("off") | str_p("OFF")) 00687 [boost::bind(&ParserGrammar::matchPrint,&self,false)]) ; 00688 // ------------------------------------------------------------------ 00689 printopt_statement = ((T_PRINTOPTIONS>>eps_p)[self.val = arg1] >> 00690 !as_lower_d["full"]) 00691 [boost::bind(&ParserGrammar::matchPrintOptions,&self,true)]; 00692 // ------------------------------------------------------------------ 00693 assign_statement = 00694 property_grammar[assign_statement.val=arg1] 00695 >> eps_p[PushBack(assign_statement.val,"#")] 00696 >> ( 00697 O_ASSIGN[PushBack(assign_statement.val,"=")] 00698 |O_PLUSASSIGN[PushBack(assign_statement.val,"+=")] 00699 |O_MINUSASSIGN[PushBack(assign_statement.val,"-=")] 00700 ) 00701 >> value_grammar[boost::bind(&ParserGrammar::matchValue,&self,_1)] 00702 >> O_SEMI; 00703 // ------------------------------------------------------------------ 00704 } 00705 // -------------------------------------------------------------------- 00706 PropertyGrammar property_grammar; 00707 IdentifierGrammar identifier_grammar; 00708 StringGrammar string_grammar; 00709 ValueGrammar value_grammar; 00710 // -------------------------------------------------------------------- 00711 rule<ScannerT,ClosureGrammar<std::string>::context_t> include_statement, 00712 units_statement; 00713 00714 rule<ScannerT,ClosureGrammar<std::vector<std::string> >::context_t> assign_statement; 00715 00716 rule<ScannerT> 00717 job_options_file, 00718 shell_statement, 00719 platform_statement, 00720 assertable_statement, 00721 assertion_statement, 00722 platform_dependency, 00723 pragma_statement, 00724 pragma, 00725 printopt_statement; 00726 // -------------------------------------------------------------------- 00727 rule<ScannerT> const& start() const { 00728 return job_options_file; 00729 } 00730 // -------------------------------------------------------------------- 00731 }; 00732 // ====================================================================== 00733 private: 00734 Parser* m_parser; 00735 }; 00736 } // end of namespace Parsers 00737 } // end of namespace Gaudi 00738 // ============================================================================ 00739 // The END 00740 // ============================================================================ 00741 #endif // JOBOPTIONSSVC_PARSERGRAMMAR_H 00742 // ============================================================================ 00743