Gaudi Framework, version v20r4

Generated: 8 Jan 2009

ParserGrammar.h

Go to the documentation of this file.
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 

Generated at Thu Jan 8 17:44:23 2009 for Gaudi Framework, version v20r4 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004