00001
00002
00003 #ifndef JOBOPTIONSSVC_PARSERGRAMMAR_H
00004 #define JOBOPTIONSSVC_PARSERGRAMMAR_H 1
00005
00006
00007
00008
00009
00010 #include <string>
00011 #include <vector>
00012
00013
00014
00015 #include <boost/version.hpp>
00016 #if BOOST_VERSION >= 103800
00017
00018 #if !defined(BOOST_SPIRIT_USE_OLD_NAMESPACE)
00019 #define BOOST_SPIRIT_USE_OLD_NAMESPACE
00020 #endif
00021 #include <boost/spirit/include/classic.hpp>
00022 #else
00023 #include <boost/spirit.hpp>
00024 #endif
00025 #include <boost/bind.hpp>
00026 #include <boost/tuple/tuple.hpp>
00027
00028
00029
00030 #include "GaudiKernel/Grammars.h"
00031 #include "GaudiKernel/ToStream.h"
00032
00033
00034
00035 #include "ParserUtils.h"
00036 #include "ParserActions.h"
00037
00038 namespace Gaudi
00039 {
00040 namespace Parsers
00041 {
00042
00043 using namespace boost::spirit ;
00044 using namespace phoenix;
00045
00046 typedef boost::spirit::position_iterator<std::string::const_iterator>
00047 IteratorT;
00048
00057 class IdentifierGrammar : public grammar
00058 <
00059 IdentifierGrammar, ClosureGrammar<std::string>::context_t
00060 >
00061 {
00062 public:
00063 typedef std::string ResultT;
00064 public:
00065 template <typename ScannerT>
00066 struct definition
00067 {
00068 definition( IdentifierGrammar const &self )
00069 {
00070
00071
00072
00073 keywords =
00074 "#include" ,
00075 "#units" ,
00076 "#ifdef" ,
00077 "#ifndef" ,
00078 "#endif" ,
00079 "#else" ,
00080 "WIN32" ;
00081 identifier
00082 = (lexeme_d[ (alpha_p >> *(alnum_p | '_'))
00083 - (keywords >>
00084 (anychar_p - (alnum_p | '_')))])
00085 [self.val = construct_<std::string>(arg1,arg2)];
00086 }
00087 symbols<> keywords;
00088 rule<ScannerT> const& start() const
00089 { return identifier; }
00090 rule<ScannerT> identifier;
00091 };
00092 };
00093
00102 class PropertyGrammar: public grammar
00103 <
00104 PropertyGrammar,
00105 ClosureGrammar<std::vector<std::string> >::context_t
00106 >
00107 {
00108 public:
00109 typedef std::vector<std::string> ResultT;
00110 public:
00111 template <typename ScannerT>
00112 struct definition
00113 {
00114 definition(PropertyGrammar const &self )
00115 {
00116 ns = (ident >> *("::">>ident))[ns.val = construct_<std::string>(arg1,arg2)]>>".";
00117 property = +(ns[PushBack(self.val)]) >> ident[PushBack(self.val)];
00118
00119 }
00120 IdentifierGrammar ident;
00121 rule<ScannerT> const& start() const
00122 { return property; }
00123 rule<ScannerT,ClosureGrammar<std::string>::context_t> ns;
00124 rule<ScannerT> property;
00125 };
00126 };
00127
00137 class RealUnitsGrammar : public boost::spirit::grammar
00138 < RealUnitsGrammar,AttributesClosureGrammar<std::string,
00139 boost::tuple<IteratorT, long double> >::context_t >
00140 {
00141 public:
00142 typedef long double ResultT;
00143 RealUnitsGrammar():m_parser(NULL){}
00144 public:
00145 template <typename ScannerT>
00146 struct definition
00147 {
00148 definition(RealUnitsGrammar const &self)
00149 {
00150 real_literal
00151 = (
00152 longest_d[grInt[boost::bind(&RealUnitsGrammar::matchReal,&self,_1)]
00153 |grReal[boost::bind(&RealUnitsGrammar::matchReal,&self,_1)]]
00154 >> eps_p[boost::bind(&RealUnitsGrammar::matchPosition,&self,_2)]
00155 >>!(!ch_p('*')
00156 >>grUnit
00157 [boost::bind(&RealUnitsGrammar::matchUnit,&self,_1)]
00158 )) [boost::bind(&RealUnitsGrammar::matchRealUnits,&self)];
00159 }
00160 RealGrammar<long double> grReal;
00161 IntGrammar<int> grInt;
00162 IdentifierGrammar grUnit;
00163 boost::spirit::rule<ScannerT> const& start() const
00164 { return real_literal; }
00165 boost::spirit::rule<ScannerT> real_literal;
00166 };
00167
00168 void matchRealUnits() const
00169 {
00170 val() = Gaudi::Utils::toString ( attrs().get<1>() );
00171 }
00172
00173
00174 void matchReal(ResultT value) const
00175 { attrs().get<1>()=value; }
00176
00177
00178 void matchPosition(IteratorT value) const
00179 { attrs().get<0>()=value; }
00180
00181
00182 void matchUnit(const std::string& unit) const
00183 {
00184 if (NULL == m_parser) return;
00185 file_position fpos = attrs().get<0>().get_position();
00186 Position pos(fpos.file,fpos.line,fpos.column);
00187
00188 attrs().get<1>() *= m_parser->matchUnit(unit,pos);
00189 }
00190
00194 void setParser(Parser* parser){m_parser = parser;}
00195 private:
00196 Parser* m_parser;
00197 };
00198
00214 class UnitsFileGrammar : public boost::spirit::grammar
00215 <
00216 UnitsFileGrammar, AttributesClosureGrammar<IteratorT,
00217 boost::tuple<std::string,double> >::context_t >
00218 {
00219 public:
00224 UnitsFileGrammar(Parser* parser)
00225 : m_parser(parser) {}
00226 public:
00228 void matchUnit() const
00229 {
00230 file_position fpos = val().get_position();
00231 m_parser->matchUnitEntry
00232 (attrs().get<0>(),attrs().get<1>(),
00233 Position(fpos.file,fpos.line,fpos.column));
00234 attrs().get<1>() = 1;
00235 }
00240 void matchLeftReal(double real) const
00241 { attrs().get<1>() = real; }
00242
00247 void matchLeftUnit(std::string newunit) const
00248 { attrs().get<0>() = newunit; }
00249
00254 void matchRight(std::string value) const
00255 { attrs().get<1>() =
00256 boost::lexical_cast<double>(value)/attrs().get<1>(); }
00257 public:
00258 template <typename ScannerT>
00259 struct definition
00260 {
00261 definition(UnitsFileGrammar const &self)
00262 {
00263 boost::tuples::get<1>(self.attrs()) = 1;
00264 grUnit.setParser(self.parser());
00265 units_file = *(unit[boost::bind(&UnitsFileGrammar::matchUnit,&self)]);
00266 unit =
00267 (real_p[boost::bind(&UnitsFileGrammar::matchLeftReal,&self,_1)]
00268 >> eps_p)[self.val=arg1] >> !ch_p('*')
00269 >>grNewUnit[boost::bind(&UnitsFileGrammar::matchLeftUnit,&self,_1)]
00270 >>"=">>grUnit[boost::bind(&UnitsFileGrammar::matchRight,&self,_1)];
00271 }
00272 RealUnitsGrammar grUnit;
00273 IdentifierGrammar grNewUnit;
00274 boost::spirit::rule<ScannerT> const& start() const
00275 { return units_file;}
00276 boost::spirit::rule<ScannerT> units_file,unit;
00277 };
00278 public:
00280 Parser* parser() const{ return m_parser;}
00281 private:
00282 Parser* m_parser;
00283 };
00284
00285 typedef AttributesClosureGrammar
00286 <boost::tuple<std::string,std::vector<std::string> > ,
00287 boost::tuple<int> > ValueClosureT;
00288
00321 class ValueGrammar : public boost::spirit::grammar
00322 <ValueGrammar, ValueClosureT::context_t>
00323 {
00324 public:
00325 ValueGrammar() : m_parser(NULL){}
00326 public:
00331 void matchBrace(bool isopen) const
00332 {
00333 if ( isopen ){ attrs().get<0>()++; }
00334 else { attrs().get<0>()--; }
00335 }
00340 void matchVectorValue(std::string value) const
00341 { if(attrs().get<0>()==1){val().get<1>().push_back(value); } }
00342
00347 void matchValue(std::string value) const{ val().get<0>() = value; }
00348
00350 Parser* parser() const { return m_parser;}
00351
00353 void setParser(Parser* parser){ m_parser = parser; }
00354
00355 public:
00356
00357 template <typename ScannerT>
00358 struct definition
00359 {
00360 definition(ValueGrammar const &self)
00361 {
00362 realunits_grammar.setParser(self.parser());
00363
00364
00365
00366 chlit<> O_DOT('.');
00367 chlit<> O_COMMA(',');
00368 value_rule = value[boost::bind(&ValueGrammar::matchValue,&self,_1)];
00369 value =
00370 vectorvalue[value.val=arg1]
00371 | vector_type[value.val="["+arg1+"]"]
00372 | property_link[value.val=arg1]
00373 ;
00374
00375 vectorvalue_list
00376 = !(
00377 value[vectorvalue_list.val=arg1][boost::bind(&ValueGrammar::matchVectorValue,&self,_1)]
00378 >> *(',' >>value[vectorvalue_list.val+=","+arg1][boost::bind(&ValueGrammar::matchVectorValue,&self,_1)])
00379 );
00380
00381 vector_type =
00382 (
00383 ch_p('{')[boost::bind(&ValueGrammar::matchBrace,&self,true)]
00384 >> vectorvalue_list
00385 [vector_type.val=arg1]
00386 >> ch_p('}')[boost::bind(&ValueGrammar::matchBrace,&self,false)]
00387 )
00388 |
00389 (ch_p('[') [boost::bind(&ValueGrammar::matchBrace,&self,true)]
00390 >> vectorvalue_list
00391 [vector_type.val=arg1]
00392 >> ch_p(']')[boost::bind(&ValueGrammar::matchBrace,&self,false)]
00393 );
00394
00395 vectorvalue =
00396 listvalue[vectorvalue.val=arg1]
00397 | longest_d[
00398 literalvalue[vectorvalue.val=arg1]
00399 | mapvalue[vectorvalue.val=arg1]
00400 ];
00401
00402 listvalue = '(' >> vectorvalue[listvalue.val="("+arg1]
00403 >> *(O_COMMA[listvalue.val+=","]
00404 >> vectorvalue[listvalue.val+=arg1]) >>ch_p(')')[listvalue.val+=")"];
00405
00406 mapvalue = literalvalue[mapvalue.val=arg1]
00407 >> (ch_p('=')[mapvalue.val+="="] | ch_p(':')[mapvalue.val+=":"])
00408 >> value[mapvalue.val+=arg1]
00409 ;
00410
00411 literalvalue =
00412 realunits_grammar[literalvalue.val = arg1]
00413 |
00414 boolean_grammar[AssignBoolToString(literalvalue.val)]
00415 |
00416 string_grammar[literalvalue.val = std::string("\"")+arg1+std::string("\"")];
00417
00418 property_link = ('@'>>property_grammar)
00419 [property_link.val=construct_<std::string>(arg1,arg2)];
00420
00421 }
00422 PropertyGrammar property_grammar;
00423 StringGrammar string_grammar;
00424 BoolGrammar boolean_grammar;
00425 IntGrammar<long> int_grammar;
00426 RealUnitsGrammar realunits_grammar;
00427
00428 boost::spirit::rule<ScannerT> value_rule;
00429 boost::spirit::rule
00430 <ScannerT,ClosureGrammar<std::string>::context_t> value,literalvalue,
00431 vectorvalue,listvalue,mapvalue,vectorvalue_list, vector_type,
00432 property_link;
00433 boost::spirit::rule<ScannerT> const& start() const { return value_rule; }
00434 };
00435
00436 private:
00437 Parser* m_parser;
00438 };
00439
00440 typedef AttributesClosureGrammar
00441 <IteratorT,boost::tuple<bool,std::string,std::vector<std::string> > > ParserClosureT;
00442
00482 class ParserGrammar :
00483 public grammar<ParserGrammar, ParserClosureT::context_t> {
00484 public:
00489 ParserGrammar(Parser* parser){m_parser=parser;}
00490 virtual ~ParserGrammar() {}
00491
00493 Parser* parser() const {return m_parser;}
00494
00499 void matchInclude(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->matchInclude(fileName,pos);
00504 }
00508 void matchUnits(const std::string& fileName) const{
00509 if(!doActions()) return;
00510 file_position fpos = this->val().get_position();
00511 Position pos(fpos.file,fpos.line,fpos.column);
00512 m_parser->matchUnits(fileName,pos);
00513 }
00521 void matchAssign(std::vector<std::string> params) const{
00522 if(!doActions()) return;
00523
00524
00525 file_position fpos = val().get_position();
00526 Position pos(fpos.file,fpos.line,fpos.column);
00527
00528
00529 std::string value = attrs().get<1>();
00530 std::vector<std::string> vectorValues = attrs().get<2>();
00531
00532
00533 bool isVector = false;
00534 if(vectorValues.size()>0 || value=="[]"){
00535 isVector = true;
00536 }else{
00537 vectorValues.push_back(value);
00538 }
00539
00540
00541 std::string objectName;
00542 std::string delim;
00543 std::vector< std::string >::const_iterator cur;
00544 for ( cur = params.begin();
00545 *(cur+1) != "#"; cur++ ){
00546 objectName += delim + *cur;
00547 delim = ".";
00548 }
00549
00550 std::string optionName = *cur;
00551 std::string sign = *(cur+2);
00552
00553 Parser::Sign oper;
00554 if(sign == "+="){
00555 oper = Parser::S_PLUSASSIGN;
00556 }else if(sign == "-="){
00557 oper = Parser::S_MINUSASSIGN;
00558 }else{
00559 oper = Parser::S_ASSIGN;
00560 }
00561
00562 m_parser->matchAssign
00563 (objectName, optionName, oper,
00564 vectorValues,pos,isVector);
00565 vectorValues.clear();
00566 }
00567
00572 void matchPlatform(const std::string& directive) const{
00573 bool iswin = Gaudi::Parsers::Utils::isWin();
00574 if(directive=="endif" || (directive=="ifdef" && iswin)
00575 || (directive=="ifndef" && !iswin)){
00576 attrs().get<0>() = true;
00577 } else {
00578 attrs().get<0>() = !attrs().get<0>();
00579 }
00580 }
00581
00586 void matchPrint(bool on) const{
00587 file_position fpos = this->val().get_position();
00588 Position pos(fpos.file,fpos.line,fpos.column);
00589 m_parser->setIsPrint(on,pos);
00590 }
00591
00596 void matchPrintOptions(bool on) const{
00597 file_position fpos = this->val().get_position();
00598 Position pos(fpos.file,fpos.line,fpos.column);
00599 m_parser->setIsPrintOptions(on,pos);
00600 }
00601
00606 void matchValue(boost::tuple<std::string,std::vector<std::string> > value) const{
00607 if(!doActions()) return;
00608 attrs().get<1>() = value.get<0>();
00609 attrs().get<2>() = value.get<1>();
00610 }
00611
00615 bool doActions() const{ return attrs().get<0>();}
00616
00617 template <typename ScannerT>
00618 struct definition {
00619
00620 definition(ParserGrammar const &self) {
00621 value_grammar.setParser(self.parser());
00622 boost::tuples::get<0>(self.attrs()) = true;
00623
00624
00625
00626 chlit<> O_SEMI(';');
00627 chlit<> O_DOT('.');
00628
00629 strlit<> O_ASSIGN("=");
00630 strlit<> O_PLUSASSIGN("+=");
00631 strlit<> O_MINUSASSIGN("-=");
00632
00633
00634
00635
00636 strlit<> T_SHELL("#!");
00637 strlit<> T_IFDEF("#ifdef");
00638 strlit<> T_IFNDEF("#ifndef");
00639 strlit<> T_ELSE("#else");
00640 strlit<> T_ENDIF("#endif");
00641 strlit<> T_WIN32("WIN32");
00642 strlit<> T_INCLUDE("#include");
00643 strlit<> T_UNITS("#units");
00644 strlit<> T_PRAGMA("#pragma");
00645 strlit<> T_PRINTOPTIONS("#printOptions");
00646
00647 job_options_file =
00648 !shell_statement >> *(platform_statement | platform_dependency);
00649
00650 shell_statement = comment_p(T_SHELL);
00651
00652 platform_statement = assertable_statement | pragma_statement;
00653
00654 assertable_statement =
00655 include_statement
00656 [boost::bind(&ParserGrammar::matchInclude,&self,_1)]
00657 | units_statement
00658 [boost::bind(&ParserGrammar::matchUnits,&self,_1)]
00659 | assign_statement
00660 [boost::bind(&ParserGrammar::matchAssign,&self,_1)];
00661
00662 assertion_statement =
00663 T_IFDEF
00664 [boost::bind(&ParserGrammar::matchPlatform,&self,"ifdef")]
00665 |
00666 T_IFNDEF
00667 [boost::bind(&ParserGrammar::matchPlatform,&self,"ifndef")];
00668
00669 platform_dependency =
00670 assertion_statement
00671 >> T_WIN32
00672 >> *platform_statement
00673 >> !(
00674 T_ELSE[boost::bind(&ParserGrammar::matchPlatform,&self,"else")]
00675 >> *platform_statement
00676 )
00677 >> T_ENDIF
00678 [boost::bind(&ParserGrammar::matchPlatform,&self,"endif")];
00679
00680 include_statement =
00681 T_INCLUDE
00682 >> (string_grammar[include_statement.val=arg1]>>eps_p)
00683 [self.val=arg1];
00684
00685 units_statement =
00686 T_UNITS
00687 >> (string_grammar[units_statement.val=arg1]>>eps_p)
00688 [self.val=arg1];;
00689
00690 pragma_statement = pragma | printopt_statement;
00691
00692 pragma = (T_PRAGMA>>eps_p)[self.val=arg1] >> str_p("print")
00693 >> ((str_p("on") | str_p("ON"))
00694 [boost::bind(&ParserGrammar::matchPrint,&self,true)]
00695 | (str_p("off") | str_p("OFF"))
00696 [boost::bind(&ParserGrammar::matchPrint,&self,false)]) ;
00697
00698 printopt_statement = ((T_PRINTOPTIONS>>eps_p)[self.val = arg1] >>
00699 !as_lower_d["full"])
00700 [boost::bind(&ParserGrammar::matchPrintOptions,&self,true)];
00701
00702 assign_statement =
00703 property_grammar[assign_statement.val=arg1]
00704 >> eps_p[PushBack(assign_statement.val,"#")]
00705 >> (
00706 O_ASSIGN[PushBack(assign_statement.val,"=")]
00707 |O_PLUSASSIGN[PushBack(assign_statement.val,"+=")]
00708 |O_MINUSASSIGN[PushBack(assign_statement.val,"-=")]
00709 )
00710 >> value_grammar[boost::bind(&ParserGrammar::matchValue,&self,_1)]
00711 >> O_SEMI;
00712
00713 }
00714
00715 PropertyGrammar property_grammar;
00716 IdentifierGrammar identifier_grammar;
00717 StringGrammar string_grammar;
00718 ValueGrammar value_grammar;
00719
00720 rule<ScannerT,ClosureGrammar<std::string>::context_t> include_statement,
00721 units_statement;
00722
00723 rule<ScannerT,ClosureGrammar<std::vector<std::string> >::context_t> assign_statement;
00724
00725 rule<ScannerT>
00726 job_options_file,
00727 shell_statement,
00728 platform_statement,
00729 assertable_statement,
00730 assertion_statement,
00731 platform_dependency,
00732 pragma_statement,
00733 pragma,
00734 printopt_statement;
00735
00736 rule<ScannerT> const& start() const {
00737 return job_options_file;
00738 }
00739
00740 };
00741
00742 private:
00743 Parser* m_parser;
00744 };
00745 }
00746 }
00747
00748
00749
00750 #endif // JOBOPTIONSSVC_PARSERGRAMMAR_H
00751
00752