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