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 
42 namespace reco {
43  namespace parser {
44  struct Grammar : public boost::spirit::classic::grammar<Grammar> {
49  bool lazy_;
58  mutable IntStack intStack;
59 
60  Grammar(SelectorPtr& sel, const edm::TypeWithDict& iType, bool lazy = false)
61  : sel_(&sel), expr_(&dummyExpr_), lazy_(lazy) {
62  typeStack.push_back(iType);
63  }
64 
65  Grammar(ExpressionPtr& expr, const edm::TypeWithDict& iType, bool lazy = false)
66  : sel_(&dummySel_), expr_(&expr), lazy_(lazy) {
67  typeStack.push_back(iType);
68  }
69 
70  template <typename ScannerT>
71  struct definition : public boost::spirit::classic::grammar_def<boost::spirit::classic::rule<ScannerT>,
72  boost::spirit::classic::same,
73  boost::spirit::classic::same> {
74  typedef boost::spirit::classic::rule<ScannerT> rule;
78  definition(const Grammar& self) {
79  using namespace boost::spirit::classic;
80  using namespace std;
81 
82  ExpressionNumberSetter number_s(self.exprStack);
83  IntSetter int_s(self.intStack);
84  ExpressionVarSetter var_s(self.exprStack, self.methStack, self.lazyMethStack, self.typeStack);
85  ExpressionConditionSetter cond_s(self.exprStack, self.selStack);
86  MethodArgumentSetter methodArg_s(self.methArgStack);
87  MethodSetter method_s(self.methStack, self.lazyMethStack, self.typeStack, self.methArgStack, self.lazy_);
88  ComparisonSetter<less_equal<double> > less_equal_s(self.cmpStack);
91  ComparisonSetter<greater_equal<double> > greater_equal_s(self.cmpStack);
93  ComparisonSetter<not_equal_to<double> > not_equal_to_s(self.cmpStack);
94  FunctionSetter abs_s(kAbs, self.funStack), acos_s(kAcos, self.funStack), asin_s(kAsin, self.funStack),
95  atan2_s(kAtan, self.funStack), atan_s(kAtan, self.funStack), chi2prob_s(kChi2Prob, self.funStack),
96  cosh_s(kCosh, self.funStack), cos_s(kCos, self.funStack), exp_s(kExp, self.funStack),
97  hypot_s(kHypot, self.funStack), log_s(kLog, self.funStack), log10_s(kLog10, self.funStack),
98  max_s(kMax, self.funStack), min_s(kMin, self.funStack), pow_s(kPow, self.funStack),
99  sinh_s(kSinh, self.funStack), sin_s(kSin, self.funStack), sqrt_s(kSqrt, self.funStack),
100  tanh_s(kTanh, self.funStack), tan_s(kTan, self.funStack), deltaPhi_s(kDeltaPhi, self.funStack),
101  deltaR_s(kDeltaR, self.funStack), test_bit_s(kTestBit, self.funStack);
102  FunctionSetterCommit funOk_s(self.funStack, self.finalFunStack);
103  TrinarySelectorSetter trinary_s(self.selStack, self.cmpStack, self.exprStack);
104  BinarySelectorSetter binary_s(self.selStack, self.cmpStack, self.exprStack);
105  ExpressionSelectorSetter expr_sel_s(self.selStack, self.exprStack);
109  CutSetter cut_s(*self.sel_, self.selStack);
110  ExpressionSetter expr_s(*self.expr_, self.exprStack);
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];
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  ('%' >> expect(power))[remainder_s]);
172  power = factor >> *(('^' >> expect(factor))[power_of_s]);
173  factor =
174  number | (function1 >> ch_p('(')[funOk_s] >> expect(expression) >> expectParenthesis(ch_p(')')))[fun_s] |
175  (function2 >> ch_p('(')[funOk_s] >> expect(expression) >> expect(ch_p(',')) >> expect(expression) >>
176  expectParenthesis(ch_p(')')))[fun_s] |
177  (function4 >> ch_p('(')[funOk_s] >> expect(expression) >> expect(ch_p(',')) >> expect(expression) >>
178  expect(ch_p(',')) >> expect(expression) >> expect(ch_p(',')) >> expect(expression) >>
179  expectParenthesis(ch_p(')')))[fun_s] |
180  //NOTE: no expect around the first ch_p('(') otherwise it can't parse a method that starts like a function name (i.e. maxSomething)
181  method |
182  //NOTE: no 'expectedParenthesis around ending ')' because at this point the partial phrase
183  // "(a"
184  //could refer to an expression, e.g., "(a+b)*c" or a logical expression "(a<1) &&"
185  //so we need to allow the parser to 'backup' and try a different approach.
186  //NOTE: if the parser were changed so a logical expression could be used as an expression,e.g.
187  // (a<b)+1 <2
188  // then we could remove such an ambiguity.
189  ch_p('(') >> expression >> ch_p(')') | (ch_p('-') >> factor)[negate_s] | (ch_p('+') >> factor);
190  comparison_op = (ch_p('<') >> ch_p('=')[less_equal_s]) | (ch_p('<')[less_s]) |
191  (ch_p('=') >> ch_p('=')[equal_to_s]) | (ch_p('=')[equal_to_s]) |
192  (ch_p('>') >> ch_p('=')[greater_equal_s]) | (ch_p('>')[greater_s]) |
193  (ch_p('!') >> ch_p('=')[not_equal_to_s]);
194  binary_comp = (expression >> comparison_op >> expect(expression))[binary_s];
195  trinary_comp =
196  (expression >> comparison_op >> expect(expression) >> comparison_op >> expect(expression))[trinary_s];
197  or_op = ch_p('|') >> ch_p('|') | ch_p('|');
198  and_op = ch_p('&') >> ch_p('&') | ch_p('&');
199  logical_expression = logical_term >> *(or_op >> expect(logical_term))[or_s];
200  logical_term = logical_factor >> *(and_op >> expect(logical_factor))[and_s];
202  ch_p('(') >> logical_expression >> expectParenthesis(ch_p(')')) |
203  (ch_p('!') >> expect(logical_factor))[not_s] | expression[expr_sel_s];
204  ;
205  cut = logical_expression[cut_s];
206  fun = expression[expr_s];
207  this->start_parsers(cut, fun);
208  }
209  };
210  };
211  } // namespace parser
212 } // namespace reco
213 
214 #endif
FunctionStack funStack
Definition: Grammar.h:53
std::vector< std::shared_ptr< ComparisonBase > > ComparisonStack
Grammar(SelectorPtr &sel, const edm::TypeWithDict &iType, bool lazy=false)
Definition: Grammar.h:60
ComparisonStack cmpStack
Definition: Grammar.h:51
LazyMethodStack lazyMethStack
Definition: Grammar.h:55
std::shared_ptr< ExpressionBase > ExpressionPtr
std::vector< edm::TypeWithDict > TypeStack
Definition: TypeStack.h:17
FunctionStack finalFunStack
Definition: Grammar.h:53
Grammar(ExpressionPtr &expr, const edm::TypeWithDict &iType, bool lazy=false)
Definition: Grammar.h:65
std::vector< std::shared_ptr< ExpressionBase > > ExpressionStack
std::vector< AnyMethodArgument > MethodArgumentStack
boost::spirit::classic::rule< ScannerT > rule
Definition: Grammar.h:74
std::vector< SelectorPtr > SelectorStack
Definition: SelectorStack.h:18
ExpressionPtr * expr_
Definition: Grammar.h:48
std::vector< LazyInvoker > LazyMethodStack
Definition: MethodStack.h:18
std::vector< int > IntStack
Definition: IntStack.h:16
SelectorStack selStack
Definition: Grammar.h:52
IntStack intStack
Definition: Grammar.h:58
SelectorPtr * sel_
Definition: Grammar.h:47
MethodArgumentStack methArgStack
Definition: Grammar.h:56
definition(const Grammar &self)
Definition: Grammar.h:78
SelectorPtr dummySel_
Definition: Grammar.h:45
fixed size matrix
ExpressionPtr dummyExpr_
Definition: Grammar.h:46
std::vector< MethodInvoker > MethodStack
Definition: MethodStack.h:17
ExpressionStack exprStack
Definition: Grammar.h:50
MethodStack methStack
Definition: Grammar.h:54
std::vector< Function > FunctionStack
Definition: FunctionStack.h:17
TypeStack typeStack
Definition: Grammar.h:57
std::shared_ptr< SelectorBase > SelectorPtr
Definition: SelectorPtr.h:18