CMS 3D CMS Logo

Grammar.h
Go to the documentation of this file.
1 #ifndef CommonTools_Utils_Grammar_h
2 #define CommonTools_Utils_Grammar_h
3 /* \class reco::parser::Grammar
4  *
5  * parser grammar
6  *
7  * \author original version: Chris Jones, Cornell,
8  * extended by Luca Lista, INFN
9  *
10  * \version $Revision: 1.13 $
11  *
12  */
13 #include "boost/spirit/include/classic_core.hpp"
14 #include "boost/spirit/include/classic_grammar_def.hpp"
15 #include "boost/spirit/include/classic_chset.hpp"
16 #include <functional>
41 // #include "CommonTools/Utils/src/Abort.h"
42 
43 namespace reco {
44  namespace parser {
45  struct Grammar : public boost::spirit::classic::grammar<Grammar> {
46 
51  bool lazy_;
60  mutable IntStack intStack;
61 
62  Grammar(SelectorPtr & sel, const edm::TypeWithDict& iType, bool lazy=false) :
63  sel_(& sel), expr_(& dummyExpr_), lazy_(lazy) {
64  typeStack.push_back(iType);
65  }
66 
67  Grammar(ExpressionPtr & expr, const edm::TypeWithDict& iType, bool lazy=false) :
68  sel_(& dummySel_), expr_(& expr), lazy_(lazy) {
69  typeStack.push_back(iType);
70  }
71 
72  template <typename ScannerT>
73  struct definition :
74  public boost::spirit::classic::grammar_def<boost::spirit::classic::rule<ScannerT>,
75  boost::spirit::classic::same,
76  boost::spirit::classic::same>{
77  typedef boost::spirit::classic::rule<ScannerT> rule;
81  or_op, and_op, cut, fun;
82  definition(const Grammar & self) {
83  using namespace boost::spirit::classic;
84  using namespace std;
85 
86  ExpressionNumberSetter number_s(self.exprStack);
87  IntSetter int_s(self.intStack);
88  ExpressionVarSetter var_s(self.exprStack, self.methStack, self.lazyMethStack, self.typeStack);
89  ExpressionConditionSetter cond_s(self.exprStack, self.selStack);
90  MethodArgumentSetter methodArg_s(self.methArgStack);
91  MethodSetter method_s(self.methStack, self.lazyMethStack, self.typeStack, self.methArgStack, self.lazy_);
92  ComparisonSetter<less_equal<double> > less_equal_s(self.cmpStack);
93  ComparisonSetter<less<double> > less_s(self.cmpStack);
94  ComparisonSetter<equal_to<double> > equal_to_s(self.cmpStack);
95  ComparisonSetter<greater_equal<double> > greater_equal_s(self.cmpStack);
96  ComparisonSetter<greater<double> > greater_s(self.cmpStack);
97  ComparisonSetter<not_equal_to<double> > not_equal_to_s(self.cmpStack);
99  abs_s(kAbs, self.funStack), acos_s(kAcos, self.funStack), asin_s(kAsin, self.funStack),
100  atan2_s(kAtan, self.funStack), atan_s(kAtan, self.funStack),
101  chi2prob_s(kChi2Prob, self.funStack),
102  cosh_s(kCosh, self.funStack),
103  cos_s(kCos, self.funStack), exp_s(kExp, self.funStack), hypot_s(kHypot, self.funStack), log_s(kLog, self.funStack),
104  log10_s(kLog10, self.funStack), max_s(kMax, self.funStack), min_s(kMin, self.funStack),
105  pow_s(kPow, self.funStack), sinh_s(kSinh, self.funStack),
106  sin_s(kSin, self.funStack), sqrt_s(kSqrt, self.funStack), tanh_s(kTanh, self.funStack),
107  tan_s(kTan, self.funStack),
108  deltaPhi_s(kDeltaPhi, self.funStack), deltaR_s(kDeltaR, self.funStack),
109  test_bit_s(kTestBit, self.funStack);
110  FunctionSetterCommit funOk_s(self.funStack, self.finalFunStack);
111  TrinarySelectorSetter trinary_s(self.selStack, self.cmpStack, self.exprStack);
112  BinarySelectorSetter binary_s(self.selStack, self.cmpStack, self.exprStack);
113  ExpressionSelectorSetter expr_sel_s(self.selStack, self.exprStack);
114  BinaryCutSetter<logical_and<bool> > and_s(self.selStack);
115  BinaryCutSetter<logical_or<bool> > or_s(self.selStack);
116  UnaryCutSetter<logical_not<bool> > not_s(self.selStack);
117  CutSetter cut_s(* self.sel_, self.selStack);
118  ExpressionSetter expr_s(* self.expr_, self.exprStack);
119  ExpressionBinaryOperatorSetter<plus<double> > plus_s(self.exprStack);
120  ExpressionBinaryOperatorSetter<minus<double> > minus_s(self.exprStack);
121  ExpressionBinaryOperatorSetter<multiplies<double> > multiplies_s(self.exprStack);
122  ExpressionBinaryOperatorSetter<divides<double> > divides_s(self.exprStack);
123  ExpressionBinaryOperatorSetter<power_of<double> > power_of_s(self.exprStack);
124  ExpressionUnaryOperatorSetter<negate<double> > negate_s(self.exprStack);
125  ExpressionFunctionSetter fun_s(self.exprStack, self.finalFunStack);
126  // Abort abort_s;
127  BOOST_SPIRIT_DEBUG_RULE(var);
128  BOOST_SPIRIT_DEBUG_RULE(arrayAccess);
129  BOOST_SPIRIT_DEBUG_RULE(method);
130  BOOST_SPIRIT_DEBUG_RULE(logical_expression);
131  BOOST_SPIRIT_DEBUG_RULE(cond_expression);
132  BOOST_SPIRIT_DEBUG_RULE(logical_term);
133  BOOST_SPIRIT_DEBUG_RULE(logical_factor);
134  BOOST_SPIRIT_DEBUG_RULE(number);
135  BOOST_SPIRIT_DEBUG_RULE(metharg);
136  BOOST_SPIRIT_DEBUG_RULE(function1);
137  BOOST_SPIRIT_DEBUG_RULE(function2);
138  BOOST_SPIRIT_DEBUG_RULE(function4);
139  BOOST_SPIRIT_DEBUG_RULE(expression);
140  BOOST_SPIRIT_DEBUG_RULE(term);
141  BOOST_SPIRIT_DEBUG_RULE(power);
142  BOOST_SPIRIT_DEBUG_RULE(factor);
143  BOOST_SPIRIT_DEBUG_RULE(or_op);
144  BOOST_SPIRIT_DEBUG_RULE(and_op);
145  BOOST_SPIRIT_DEBUG_RULE(comparison_op);
146  BOOST_SPIRIT_DEBUG_RULE(binary_comp);
147  BOOST_SPIRIT_DEBUG_RULE(trinary_comp);
148  BOOST_SPIRIT_DEBUG_RULE(cut);
149  BOOST_SPIRIT_DEBUG_RULE(fun);
150 
151  boost::spirit::classic::assertion<SyntaxErrors> expectParenthesis(kMissingClosingParenthesis);
152  boost::spirit::classic::assertion<SyntaxErrors> expect(kSyntaxError);
153 
154  number =
155  real_p [ number_s ];
156  metharg = ( strict_real_p [ methodArg_s ] ) |
157  ( int_p [ methodArg_s ] ) |
158  ( ch_p('"' ) >> *(~ch_p('"' )) >> ch_p('"' ) ) [ methodArg_s ] |
159  ( ch_p('\'') >> *(~ch_p('\'')) >> ch_p('\'') ) [ methodArg_s ];
160  var = // alnum_p doesn't accept underscores, so we use chset<>; lexeme_d needed to avoid whitespace skipping within method names
161  (lexeme_d[alpha_p >> * chset<>("a-zA-Z0-9_")] >>
162  ch_p('(') >> metharg >> * (ch_p(',') >> metharg ) >> expectParenthesis(ch_p(')'))) [ method_s ] |
163  ( (lexeme_d[alpha_p >> * chset<>("a-zA-Z0-9_")]) [ method_s ] >> ! (ch_p('(') >> ch_p(')')) ) ;
164  arrayAccess = ( ch_p('[') >> metharg >> * (ch_p(',') >> metharg ) >> expectParenthesis(ch_p(']'))) [ method_s ];
165  method =
166  (var >> * (arrayAccess | (ch_p('.') >> expect(var)))) [ var_s ];
167  function1 =
168  chseq_p("abs") [ abs_s ] | chseq_p("acos") [ acos_s ] | chseq_p("asin") [ asin_s ] |
169  chseq_p("atan") [ atan_s ] | chseq_p("cosh") [ cosh_s ] | chseq_p("cos") [ cos_s ] |
170  chseq_p("exp") [ exp_s ] | chseq_p("log") [ log_s ] | chseq_p("log10") [ log10_s ] |
171  chseq_p("sinh") [ sinh_s ] | chseq_p("sin") [ sin_s ] | chseq_p("sqrt") [ sqrt_s ] |
172  chseq_p("tanh") [ tanh_s ] | chseq_p("tan") [ tan_s ];
173  function2 =
174  chseq_p("atan2") [ atan2_s ] | chseq_p("chi2prob") [ chi2prob_s ] | chseq_p("pow") [ pow_s ] |
175  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] ;
176  function4 =
177  chseq_p("deltaR") [deltaR_s];
178  expression =
179  cond_expression |
181  nocond_expression =
182  term >> (* (('+' >> expect(term)) [ plus_s ] |
183  ('-' >> expect(term)) [ minus_s ]));
184  cond_expression =
185  (ch_p('?') >> logical_expression >> ch_p('?') >> expect(expression) >> ch_p(":") >> expect(expression)) [cond_s];
186  term =
187  power >> * (('*' >> expect(power)) [ multiplies_s ] |
188  ('/' >> expect(power)) [ divides_s ]);
189  power =
190  factor >> * (('^' >> expect(factor)) [ power_of_s ]);
191  factor =
192  number |
193  (function1 >> ch_p('(') [funOk_s ] >> expect(expression) >> expectParenthesis(ch_p(')'))) [ fun_s ] |
194  (function2 >> ch_p('(') [funOk_s ] >> expect(expression) >>
195  expect(ch_p(',')) >> expect(expression) >> expectParenthesis(ch_p(')'))) [ fun_s ] |
196  (function4 >> ch_p('(') [funOk_s ] >> expect(expression) >> expect(ch_p(',')) >> expect(expression) >> expect(ch_p(',')) >> expect(expression) >>
197  expect(ch_p(',')) >> expect(expression) >> expectParenthesis(ch_p(')'))) [ fun_s ] |
198  //NOTE: no expect around the first ch_p('(') otherwise it can't parse a method that starts like a function name (i.e. maxSomething)
199  method |
200  //NOTE: no 'expectedParenthesis around ending ')' because at this point the partial phrase
201  // "(a"
202  //could refer to an expression, e.g., "(a+b)*c" or a logical expression "(a<1) &&"
203  //so we need to allow the parser to 'backup' and try a different approach.
204  //NOTE: if the parser were changed so a logical expression could be used as an expression,e.g.
205  // (a<b)+1 <2
206  // then we could remove such an ambiguity.
207  ch_p('(') >> expression >> ch_p(')') |
208  (ch_p('-') >> factor) [ negate_s ] |
209  (ch_p('+') >> factor);
210  comparison_op =
211  (ch_p('<') >> ch_p('=') [ less_equal_s ]) |
212  (ch_p('<') [ less_s ]) |
213  (ch_p('=') >> ch_p('=') [ equal_to_s ]) |
214  (ch_p('=') [ equal_to_s ]) |
215  (ch_p('>') >> ch_p('=') [ greater_equal_s ]) |
216  (ch_p('>') [ greater_s ]) |
217  (ch_p('!') >> ch_p('=') [ not_equal_to_s ]);
218  binary_comp =
219  (expression >> comparison_op >> expect(expression)) [ binary_s ];
220  trinary_comp =
221  (expression >> comparison_op >> expect(expression) >> comparison_op >> expect(expression)) [ trinary_s ];
222  or_op = ch_p('|') >> ch_p('|') | ch_p('|');
223  and_op = ch_p('&') >> ch_p('&') | ch_p('&');
224  logical_expression =
225  logical_term >> * (or_op >> expect(logical_term)) [ or_s ];
226  logical_term =
227  logical_factor >> * (and_op >> expect(logical_factor)) [ and_s ];
228  logical_factor =
229  trinary_comp |
230  binary_comp |
231  ch_p('(') >> logical_expression >> expectParenthesis(ch_p(')')) |
232  (ch_p('!') >> expect(logical_factor)) [ not_s ] |
233  expression [ expr_sel_s ];
234 ;
235  cut = logical_expression [ cut_s ];
236  fun = expression [ expr_s ];
237  this->start_parsers(cut, fun);
238  }
239  };
240  };
241  }
242 }
243 
244 
245 #endif
FunctionStack funStack
Definition: Grammar.h:55
Grammar(SelectorPtr &sel, const edm::TypeWithDict &iType, bool lazy=false)
Definition: Grammar.h:62
ComparisonStack cmpStack
Definition: Grammar.h:53
LazyMethodStack lazyMethStack
Definition: Grammar.h:57
std::vector< edm::TypeWithDict > TypeStack
Definition: TypeStack.h:17
FunctionStack finalFunStack
Definition: Grammar.h:55
boost::shared_ptr< ExpressionBase > ExpressionPtr
Grammar(ExpressionPtr &expr, const edm::TypeWithDict &iType, bool lazy=false)
Definition: Grammar.h:67
std::vector< AnyMethodArgument > MethodArgumentStack
boost::spirit::classic::rule< ScannerT > rule
Definition: Grammar.h:77
std::vector< boost::shared_ptr< ExpressionBase > > ExpressionStack
std::vector< SelectorPtr > SelectorStack
Definition: SelectorStack.h:18
ExpressionPtr * expr_
Definition: Grammar.h:50
std::vector< LazyInvoker > LazyMethodStack
Definition: MethodStack.h:18
std::vector< int > IntStack
Definition: IntStack.h:16
SelectorStack selStack
Definition: Grammar.h:54
IntStack intStack
Definition: Grammar.h:60
boost::shared_ptr< SelectorBase > SelectorPtr
Definition: SelectorPtr.h:17
SelectorPtr * sel_
Definition: Grammar.h:49
MethodArgumentStack methArgStack
Definition: Grammar.h:58
definition(const Grammar &self)
Definition: Grammar.h:82
SelectorPtr dummySel_
Definition: Grammar.h:47
fixed size matrix
ExpressionPtr dummyExpr_
Definition: Grammar.h:48
std::vector< MethodInvoker > MethodStack
Definition: MethodStack.h:17
ExpressionStack exprStack
Definition: Grammar.h:52
MethodStack methStack
Definition: Grammar.h:56
std::vector< boost::shared_ptr< ComparisonBase > > ComparisonStack
std::vector< Function > FunctionStack
Definition: FunctionStack.h:17
TypeStack typeStack
Definition: Grammar.h:59