Gaudi Framework, version v21r8

Home   Generated: 17 Mar 2010

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/version.hpp>
00016 #if BOOST_VERSION >= 103800
00017 // FIXME: Move to the new boost::spirit::classic namespace
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 // GaudiKernel
00029 // ============================================================================
00030 #include "GaudiKernel/Grammars.h"
00031 #include "GaudiKernel/ToStream.h"
00032 // ============================================================================
00033 // Local
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           // KEYWORDS
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       // Action when we recognize real with unit
00168       void matchRealUnits() const
00169       {
00170         val() = Gaudi::Utils::toString ( attrs().get<1>() );
00171       }
00172 
00173       // Action when we recognize real (without unit)
00174       void matchReal(ResultT value) const
00175       { attrs().get<1>()=value; }
00176 
00177       // Action for saving position
00178       void matchPosition(IteratorT value) const
00179       { attrs().get<0>()=value; }
00180 
00181       // Action when we recognize unit
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           // OPERATORS
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         // position where statement appears
00525         file_position fpos = val().get_position();
00526         Position pos(fpos.file,fpos.line,fpos.column);
00527 
00528         // get value representation. It's two modes string and vector of strings
00529         std::string value = attrs().get<1>();
00530         std::vector<std::string> vectorValues = attrs().get<2>();
00531 
00532         // check if value is vector
00533         bool isVector = false;
00534         if(vectorValues.size()>0 || value=="[]"){
00535           isVector = true;
00536         }else{
00537           vectorValues.push_back(value);
00538         }
00539 
00540         // extract object, option name and sign
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           // OPERATORS
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           // TOKENS
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   } // end of namespace Parsers
00746 } // end of namespace Gaudi
00747 // ============================================================================
00748 // The END
00749 // ============================================================================
00750 #endif // JOBOPTIONSSVC_PARSERGRAMMAR_H
00751 // ============================================================================
00752 

Generated at Wed Mar 17 18:06:47 2010 for Gaudi Framework, version v21r8 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004