CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/CommonTools/Utils/src/Grammar.h

Go to the documentation of this file.
00001 #ifndef CommonTools_Utils_Grammar_h
00002 #define CommonTools_Utils_Grammar_h
00003 /* \class reco::parser::Grammar
00004  *
00005  * parser grammar
00006  *
00007  * \author original version: Chris Jones, Cornell, 
00008  *         extended by Luca Lista, INFN
00009  *
00010  * \version $Revision: 1.11 $
00011  *
00012  */
00013 #include "boost/spirit/include/classic_core.hpp"
00014 #include "boost/spirit/include/classic_grammar_def.hpp"
00015 #include "boost/spirit/include/classic_chset.hpp"
00016 #include <functional>
00017 #include "CommonTools/Utils/src/ExpressionNumberSetter.h"
00018 #include "CommonTools/Utils/src/ExpressionVarSetter.h"
00019 #include "CommonTools/Utils/src/ExpressionFunctionSetter.h"
00020 #include "CommonTools/Utils/src/ExpressionConditionSetter.h"
00021 #include "CommonTools/Utils/src/ComparisonSetter.h"
00022 #include "CommonTools/Utils/src/BinarySelectorSetter.h"
00023 #include "CommonTools/Utils/src/TrinarySelectorSetter.h"
00024 #include "CommonTools/Utils/src/IntSetter.h"
00025 #include "CommonTools/Utils/src/MethodStack.h"
00026 #include "CommonTools/Utils/src/MethodArgumentStack.h"
00027 #include "CommonTools/Utils/src/TypeStack.h"
00028 #include "CommonTools/Utils/src/IntStack.h"
00029 #include "CommonTools/Utils/src/FunctionSetter.h"
00030 #include "CommonTools/Utils/src/CutSetter.h"
00031 #include "CommonTools/Utils/src/BinaryCutSetter.h"
00032 #include "CommonTools/Utils/src/UnaryCutSetter.h"
00033 #include "CommonTools/Utils/src/ExpressionSetter.h"
00034 #include "CommonTools/Utils/src/ExpressionBinaryOperatorSetter.h"
00035 #include "CommonTools/Utils/src/ExpressionUnaryOperatorSetter.h"
00036 #include "CommonTools/Utils/src/ExpressionSelectorSetter.h"
00037 #include "CommonTools/Utils/src/MethodSetter.h"
00038 #include "CommonTools/Utils/src/MethodArgumentSetter.h"
00039 #include "CommonTools/Utils/interface/Exception.h"
00040 // #include "CommonTools/Utils/src/Abort.h"
00041 
00042 namespace reco {
00043   namespace parser {    
00044     struct Grammar : public boost::spirit::classic::grammar<Grammar> {
00045        
00046       SelectorPtr dummySel_;
00047       ExpressionPtr dummyExpr_;
00048       SelectorPtr * sel_; 
00049       ExpressionPtr * expr_;
00050       bool            lazy_;
00051       mutable ExpressionStack exprStack;
00052       mutable ComparisonStack cmpStack;
00053       mutable SelectorStack selStack;
00054       mutable FunctionStack funStack, finalFunStack;
00055       mutable MethodStack         methStack;
00056       mutable LazyMethodStack     lazyMethStack;
00057       mutable MethodArgumentStack methArgStack;
00058       mutable TypeStack typeStack;
00059       mutable IntStack intStack;
00060 
00061       Grammar(SelectorPtr & sel, const Reflex::Type& iType, bool lazy=false) : 
00062         sel_(& sel), expr_(& dummyExpr_), lazy_(lazy) { 
00063         typeStack.push_back(iType);
00064       }
00065 
00066       Grammar(ExpressionPtr & expr, const Reflex::Type& iType, bool lazy=false) : 
00067         sel_(& dummySel_), expr_(& expr), lazy_(lazy) { 
00068         typeStack.push_back(iType);
00069       }
00070       template <typename ScannerT>
00071       struct definition : 
00072         public boost::spirit::classic::grammar_def<boost::spirit::classic::rule<ScannerT>, 
00073                                                    boost::spirit::classic::same, 
00074                                                    boost::spirit::classic::same>{  
00075         typedef boost::spirit::classic::rule<ScannerT> rule;
00076         rule number, var, arrayAccess, metharg, method, term, power, factor, function1, function2, function4, expression, 
00077           comparison_op, binary_comp, trinary_comp,
00078           logical_combiner, logical_expression, nocond_expression, cond_expression, logical_factor, logical_term,
00079           or_op, and_op, cut, fun;
00080         definition(const Grammar & self) {
00081           using namespace boost::spirit::classic;
00082           using namespace std;
00083 
00084           ExpressionNumberSetter number_s(self.exprStack);
00085           IntSetter int_s(self.intStack);
00086           ExpressionVarSetter var_s(self.exprStack, self.methStack, self.lazyMethStack, self.typeStack);
00087           ExpressionConditionSetter cond_s(self.exprStack, self.selStack);
00088           MethodArgumentSetter methodArg_s(self.methArgStack);
00089           MethodSetter method_s(self.methStack, self.lazyMethStack, self.typeStack, self.methArgStack, self.lazy_);
00090           ComparisonSetter<less_equal<double> > less_equal_s(self.cmpStack);
00091           ComparisonSetter<less<double> > less_s(self.cmpStack);
00092           ComparisonSetter<equal_to<double> > equal_to_s(self.cmpStack);
00093           ComparisonSetter<greater_equal<double> > greater_equal_s(self.cmpStack);
00094           ComparisonSetter<greater<double> > greater_s(self.cmpStack);
00095           ComparisonSetter<not_equal_to<double> > not_equal_to_s(self.cmpStack);
00096           FunctionSetter 
00097             abs_s(kAbs, self.funStack), acos_s(kAcos, self.funStack), asin_s(kAsin, self.funStack),
00098             atan2_s(kAtan, self.funStack), atan_s(kAtan, self.funStack), 
00099             chi2prob_s(kChi2Prob, self.funStack), 
00100             cosh_s(kCosh, self.funStack), 
00101             cos_s(kCos, self.funStack), exp_s(kExp, self.funStack), hypot_s(kHypot, self.funStack), log_s(kLog, self.funStack), 
00102             log10_s(kLog10, self.funStack), max_s(kMax, self.funStack), min_s(kMin, self.funStack),
00103             pow_s(kPow, self.funStack), sinh_s(kSinh, self.funStack), 
00104             sin_s(kSin, self.funStack), sqrt_s(kSqrt, self.funStack), tanh_s(kTanh, self.funStack), 
00105             tan_s(kTan, self.funStack),
00106             deltaPhi_s(kDeltaPhi, self.funStack), deltaR_s(kDeltaR, self.funStack), 
00107             test_bit_s(kTestBit, self.funStack);
00108           FunctionSetterCommit funOk_s(self.funStack, self.finalFunStack);
00109           TrinarySelectorSetter trinary_s(self.selStack, self.cmpStack, self.exprStack);
00110           BinarySelectorSetter binary_s(self.selStack, self.cmpStack, self.exprStack);
00111           ExpressionSelectorSetter expr_sel_s(self.selStack, self.exprStack);
00112           BinaryCutSetter<logical_and<bool> > and_s(self.selStack);
00113           BinaryCutSetter<logical_or<bool> > or_s(self.selStack);
00114           UnaryCutSetter<logical_not<bool> > not_s(self.selStack);
00115           CutSetter cut_s(* self.sel_, self.selStack);
00116           ExpressionSetter expr_s(* self.expr_, self.exprStack);
00117           ExpressionBinaryOperatorSetter<plus<double> > plus_s(self.exprStack);
00118           ExpressionBinaryOperatorSetter<minus<double> > minus_s(self.exprStack);
00119           ExpressionBinaryOperatorSetter<multiplies<double> > multiplies_s(self.exprStack);
00120           ExpressionBinaryOperatorSetter<divides<double> > divides_s(self.exprStack);
00121           ExpressionBinaryOperatorSetter<power_of<double> > power_of_s(self.exprStack);
00122           ExpressionUnaryOperatorSetter<negate<double> > negate_s(self.exprStack);
00123           ExpressionFunctionSetter fun_s(self.exprStack, self.finalFunStack);
00124           //      Abort abort_s;
00125           BOOST_SPIRIT_DEBUG_RULE(var);
00126           BOOST_SPIRIT_DEBUG_RULE(arrayAccess);
00127           BOOST_SPIRIT_DEBUG_RULE(method);
00128           BOOST_SPIRIT_DEBUG_RULE(logical_expression);
00129           BOOST_SPIRIT_DEBUG_RULE(cond_expression);
00130           BOOST_SPIRIT_DEBUG_RULE(logical_term);
00131           BOOST_SPIRIT_DEBUG_RULE(logical_factor);
00132           BOOST_SPIRIT_DEBUG_RULE(number);
00133           BOOST_SPIRIT_DEBUG_RULE(metharg);
00134           BOOST_SPIRIT_DEBUG_RULE(function1);
00135           BOOST_SPIRIT_DEBUG_RULE(function2);
00136           BOOST_SPIRIT_DEBUG_RULE(function4);
00137           BOOST_SPIRIT_DEBUG_RULE(expression);
00138           BOOST_SPIRIT_DEBUG_RULE(term);
00139           BOOST_SPIRIT_DEBUG_RULE(power);
00140           BOOST_SPIRIT_DEBUG_RULE(factor);
00141           BOOST_SPIRIT_DEBUG_RULE(or_op);
00142           BOOST_SPIRIT_DEBUG_RULE(and_op);
00143           BOOST_SPIRIT_DEBUG_RULE(comparison_op);
00144           BOOST_SPIRIT_DEBUG_RULE(binary_comp);
00145           BOOST_SPIRIT_DEBUG_RULE(trinary_comp);
00146           BOOST_SPIRIT_DEBUG_RULE(cut);
00147           BOOST_SPIRIT_DEBUG_RULE(fun);
00148   
00149           boost::spirit::classic::assertion<SyntaxErrors> expectParenthesis(kMissingClosingParenthesis);
00150           boost::spirit::classic::assertion<SyntaxErrors> expect(kSyntaxError);
00151   
00152           number = 
00153             real_p [ number_s ];
00154           metharg = ( strict_real_p [ methodArg_s ] ) |
00155                     ( int_p [ methodArg_s ] ) |
00156                     ( ch_p('"' ) >> *(~ch_p('"' ))  >> ch_p('"' ) ) [ methodArg_s ] |
00157                     ( ch_p('\'') >> *(~ch_p('\''))  >> ch_p('\'') ) [ methodArg_s ];
00158           var = // alnum_p doesn't accept underscores, so we use chset<>; lexeme_d needed to avoid whitespace skipping within method names
00159             (lexeme_d[alpha_p >> * chset<>("a-zA-Z0-9_")] >>  
00160               ch_p('(') >> metharg >> * (ch_p(',') >> metharg ) >> expectParenthesis(ch_p(')'))) [ method_s ] |
00161             ( (lexeme_d[alpha_p >> * chset<>("a-zA-Z0-9_")]) [ method_s ] >> ! (ch_p('(') >> ch_p(')')) ) ;
00162           arrayAccess = ( ch_p('[') >> metharg >> * (ch_p(',') >> metharg ) >> expectParenthesis(ch_p(']'))) [ method_s ];
00163           method = 
00164             (var >> * (arrayAccess | (ch_p('.') >> expect(var)))) [ var_s ];
00165           function1 = 
00166             chseq_p("abs")  [ abs_s ]  | chseq_p("acos") [ acos_s ] | chseq_p("asin") [ asin_s ] |
00167             chseq_p("atan") [ atan_s ] | chseq_p("cosh") [ cosh_s ] | chseq_p("cos") [ cos_s ] |
00168             chseq_p("exp")  [ exp_s ]  | chseq_p("log") [ log_s ] | chseq_p("log10") [ log10_s ] |
00169             chseq_p("sinh") [ sinh_s ] | chseq_p("sin") [ sin_s ] | chseq_p("sqrt") [ sqrt_s ] |
00170             chseq_p("tanh") [ tanh_s ] | chseq_p("tan") [ tan_s ];
00171           function2 = 
00172             chseq_p("atan2") [ atan2_s ] | chseq_p("chi2prob") [ chi2prob_s ] | chseq_p("pow") [ pow_s ] |
00173             chseq_p("min") [ min_s ] | chseq_p("max") [ max_s ] | chseq_p("deltaPhi") [deltaPhi_s]  | chseq_p("hypot") [hypot_s] | chseq_p("test_bit") [test_bit_s] ;
00174           function4 =
00175             chseq_p("deltaR") [deltaR_s];
00176           expression =
00177             cond_expression |
00178             nocond_expression;
00179           nocond_expression = 
00180             term >> (* (('+' >> expect(term)) [ plus_s ] |
00181                         ('-' >> expect(term)) [ minus_s ]));
00182           cond_expression = 
00183              (ch_p('?') >> logical_expression >> ch_p('?') >> expect(expression) >> ch_p(":") >> expect(expression)) [cond_s];
00184           term = 
00185             power >> * (('*' >> expect(power)) [ multiplies_s ] |
00186                         ('/' >> expect(power)) [ divides_s ]);
00187           power = 
00188             factor >> * (('^' >> expect(factor)) [ power_of_s ]);
00189           factor = 
00190             number | 
00191             (function1 >> ch_p('(') [funOk_s ] >> expect(expression) >> expectParenthesis(ch_p(')'))) [ fun_s ] |
00192             (function2 >> ch_p('(') [funOk_s ] >> expect(expression) >> 
00193              expect(ch_p(',')) >> expect(expression) >> expectParenthesis(ch_p(')'))) [ fun_s ] |
00194             (function4 >> ch_p('(') [funOk_s ] >> expect(expression) >> expect(ch_p(',')) >> expect(expression) >> expect(ch_p(',')) >> expect(expression) >> 
00195              expect(ch_p(',')) >> expect(expression) >> expectParenthesis(ch_p(')'))) [ fun_s ] |
00196             //NOTE: no expect around the first ch_p('(') otherwise it can't parse a method that starts like a function name (i.e. maxSomething)
00197             method | 
00198             //NOTE: no 'expectedParenthesis around ending ')' because at this point the partial phrase
00199             //       "(a"
00200             //could refer to an expression, e.g., "(a+b)*c" or a logical expression "(a<1) &&"
00201             //so we need to allow the parser to 'backup' and try a different approach.
00202             //NOTE: if the parser were changed so a logical expression could be used as an expression,e.g.
00203             //  (a<b)+1 <2
00204             // then we could remove such an ambiguity.
00205             ch_p('(') >> expression >> ch_p(')') |   
00206             (ch_p('-') >> factor) [ negate_s ] |
00207             (ch_p('+') >> factor);
00208           comparison_op = 
00209             (ch_p('<') >> ch_p('=') [ less_equal_s    ]) | 
00210             (ch_p('<')              [ less_s          ]) | 
00211             (ch_p('=') >> ch_p('=') [ equal_to_s      ]) | 
00212             (ch_p('=')              [ equal_to_s      ]) | 
00213             (ch_p('>') >> ch_p('=') [ greater_equal_s ]) | 
00214             (ch_p('>')              [ greater_s       ]) | 
00215             (ch_p('!') >> ch_p('=') [ not_equal_to_s  ]);
00216           binary_comp = 
00217             (expression >> comparison_op >> expect(expression)) [ binary_s ];
00218           trinary_comp = 
00219             (expression >> comparison_op >> expect(expression) >> comparison_op >> expect(expression)) [ trinary_s ];
00220           or_op = ch_p('|') >> ch_p('|') | ch_p('|');
00221           and_op = ch_p('&') >> ch_p('&') | ch_p('&'); 
00222           logical_expression = 
00223             logical_term >> * (or_op >> expect(logical_term)) [ or_s ];
00224           logical_term = 
00225             logical_factor >> * (and_op >> expect(logical_factor)) [ and_s ];
00226           logical_factor =
00227             trinary_comp | 
00228             binary_comp |
00229             ch_p('(') >> logical_expression >> expectParenthesis(ch_p(')')) |
00230             (ch_p('!') >> expect(logical_factor)) [ not_s ] |
00231             expression [ expr_sel_s ];
00232 ;
00233           cut = logical_expression [ cut_s ];
00234           fun = expression [ expr_s ];
00235           start_parsers(cut, fun);
00236         }
00237       };
00238     };
00239   }
00240 }
00241 
00242 
00243 #endif