CMS 3D CMS Logo

L1GtLogicParser.cc
Go to the documentation of this file.
1 
15 // this class header
17 
18 // system include files
19 #include <stack>
20 
21 #include <iostream>
22 #include <sstream>
23 
24 #include <boost/algorithm/string.hpp>
25 
26 // user include files
27 
30 
31 // forward declarations
32 
33 // constructor(s)
34 
35 // default constructor
37  // empty, default C++ initialization for string and vector are enough
38 }
39 
40 // from the RPN vector and the operand token vector
41 // no checks for consistency, empty logical and numerical expressions
42 // requires special care when used
43 L1GtLogicParser::L1GtLogicParser(const RpnVector& rpnVec, const std::vector<OperandToken>& opTokenVector) {
44  m_rpnVector = rpnVec;
45  m_operandTokenVector = opTokenVector;
46 }
47 
48 // from a constant logical expression
49 // numerical expression will be empty
50 L1GtLogicParser::L1GtLogicParser(const std::string& logicalExpressionVal) {
51  // checks also for syntactic correctness of the logical expression
52 
53  if (!setLogicalExpression(logicalExpressionVal)) {
54  // error(s) in logical expression - printed in the relevant place
55  throw cms::Exception("FailModule") << "\nError in parsing the logical expression = " << logicalExpressionVal
56  << std::endl;
57  }
58 }
59 
60 // from a non-constant logical expression - add/remove spaces if needed
61 // numerical expression will be empty
63  // checks also for syntactic correctness of the logical expression
64 
65  // add spaces around brackets
66  std::string logicalExpressionBS;
67  addBracketSpaces(logicalExpressionVal, logicalExpressionBS);
68 
69  // trim leading or trailing spaces
70  boost::trim(logicalExpressionBS);
71 
72  if (!buildRpnVector(logicalExpressionBS)) {
73  // error(s) in logical expression
74  throw cms::Exception("FailModule") << "\nError in parsing the logical expression = " << logicalExpressionVal
75  << std::endl;
76  }
77 
78  //LogDebug("L1GtLogicParser")
79  // << "\nInitial logical expression = '" << logicalExpressionVal << "'"
80  // << "\nFinal logical expression = '" << logicalExpressionBS << "'\n"
81  // << std::endl;
82 
83  logicalExpressionVal = logicalExpressionBS;
84  m_logicalExpression = logicalExpressionVal;
85 
86  // build operand token vector
87  // dummy tokenNumber; tokenResult false
89 }
90 
91 // from a logical and a numerical expression
92 L1GtLogicParser::L1GtLogicParser(const std::string logicalExpressionVal, const std::string numericalExpressionVal) {
93  // checks also for correctness
94 
95  if (!setLogicalExpression(logicalExpressionVal)) {
96  // error(s) in logical expression - printed in the relevant place
97  throw cms::Exception("FailModule") << "\nError in parsing the logical expression = " << logicalExpressionVal
98  << std::endl;
99  }
100 
101  if (!setNumericalExpression(numericalExpressionVal)) {
102  // error(s) in numerical expression - printed in the relevant place
103  throw cms::Exception("FileModule") << "\nError in parsing the numerical expression = " << numericalExpressionVal
104  << std::endl;
105  }
106 }
107 
108 // from a logical and a numerical expression
109 // no checks for correctness - use it only after the correctness was tested
110 L1GtLogicParser::L1GtLogicParser(const std::string& logicalExpressionVal,
111  const std::string& numericalExpressionVal,
112  const bool dummy) {
113  clearRpnVector();
114  if (!buildRpnVector(logicalExpressionVal)) {
115  throw cms::Exception("FileModule") << "\nError in building RPN vector for the logical expression = "
116  << logicalExpressionVal << std::endl;
117  }
118 
119  m_logicalExpression = logicalExpressionVal;
120  m_numericalExpression = numericalExpressionVal;
121 }
122 
123 // destructor
125  // empty now
126 }
127 
128 // public methods
129 
130 // check a logical expression for correctness - add/remove spaces if needed
132  // add spaces around brackets
133  std::string logicalExpressionBS;
134  addBracketSpaces(logicalExpressionVal, logicalExpressionBS);
135 
136  // trim leading or trailing spaces
137  boost::trim(logicalExpressionBS);
138 
139  clearRpnVector();
140 
141  if (!buildRpnVector(logicalExpressionBS)) {
142  return false;
143  }
144 
145  LogDebug("L1GtLogicParser") << "\nL1GtLogicParser::checkLogicalExpression - "
146  << "\nInitial logical expression = '" << logicalExpressionVal << "'"
147  << "\nFinal logical expression = '" << logicalExpressionBS << "'\n"
148  << std::endl;
149 
150  logicalExpressionVal = logicalExpressionBS;
151 
152  return true;
153 }
154 
164 bool L1GtLogicParser::buildRpnVector(const std::string& logicalExpressionVal) {
165  //LogDebug("L1GtLogicParser")
166  //<< "\nL1GtLogicParser::buildRpnVector - "
167  //<< "\nLogical expression = '" << logicalExpressionVal << "'\n"
168  //<< std::endl;
169 
170  OperationType actualOperation = OP_NULL;
171  OperationType lastOperation = OP_NULL;
172 
173  // token as string and as TokenRPN, stack to form the postfix notation
174  std::string tokenString;
175  TokenRPN rpnToken;
176  std::stack<TokenRPN> operatorStack;
177 
178  static const std::string whitespaces = " \r\v\n\t";
179 
180  // clear possible old rpn vector
181  clearRpnVector();
182 
183  // stringstream to separate all tokens
184  std::istringstream exprStringStream(logicalExpressionVal);
185 
186  while (!exprStringStream.eof()) {
187  exprStringStream >> std::skipws >> std::ws >> tokenString;
188 
189  // skip the end
190  if (tokenString.find_first_not_of(whitespaces) == std::string::npos || tokenString.length() == 0) {
191  //LogTrace("L1GtLogicParser")
192  //<< " Break for token string = " << tokenString
193  //<< std::endl;
194 
195  break;
196  }
197 
198  actualOperation = getOperation(tokenString, lastOperation, rpnToken);
199 
200  //LogTrace("L1GtLogicParser")
201  //<< " Token string = '" << tokenString << "'"
202  //<< "\tActual Operation = " << actualOperation
203  //<< std::endl;
204 
205  // http://en.wikipedia.org/wiki/Postfix_notation#Converting_from_infix_notation
206 
207  switch (actualOperation) {
208  case OP_OPERAND: {
209  // operands get pushed to the postfix notation immediately
210  m_rpnVector.push_back(rpnToken);
211  }
212 
213  break;
214  case OP_INVALID: {
215  int errorPosition = exprStringStream.tellg();
216 
217  edm::LogError("L1GtLogicParser") << "\nLogical expression = '" << logicalExpressionVal << "'"
218  << "\n Syntax error during parsing: "
219  << "\n " << exprStringStream.str().substr(0, errorPosition) << "\n "
220  << exprStringStream.str().substr(errorPosition)
221  << "\n Returned empty RPN vector and result false." << std::endl;
222 
223  // clear the rpn vector before returning
224  clearRpnVector();
225 
226  return false;
227  }
228 
229  break;
230  case OP_NOT: {
231  operatorStack.push(rpnToken);
232  // there are no operators with higher precedence
233  }
234 
235  break;
236  case OP_AND: {
237  // first pop operators with higher precedence (NOT)
238  while (!operatorStack.empty() && operatorStack.top().operation == OP_NOT) {
239  m_rpnVector.push_back(operatorStack.top());
240  operatorStack.pop();
241  }
242  operatorStack.push(rpnToken);
243  }
244 
245  break;
246  case OP_OR: {
247  // pop operators with higher precedence (AND, NOT)
248  while (!operatorStack.empty() &&
249  (operatorStack.top().operation == OP_NOT || operatorStack.top().operation == OP_AND)) {
250  m_rpnVector.push_back(operatorStack.top());
251  operatorStack.pop();
252  }
253  // push operator on stack
254  operatorStack.push(rpnToken);
255  }
256 
257  break;
258  case OP_OPENBRACKET: {
259  // just push it on stack
260  operatorStack.push(rpnToken);
261  }
262 
263  break;
264  case OP_CLOSEBRACKET: {
265  // check if the operatorStack is empty
266  if (operatorStack.empty()) {
267  int errorPosition = exprStringStream.tellg();
268 
269  edm::LogError("L1GtLogicParser") << "\nLogical expression = '" << logicalExpressionVal << "'"
270  << "\n Syntax error during parsing - misplaced ')':"
271  << "\n " << exprStringStream.str().substr(0, errorPosition) << "\n "
272  << exprStringStream.str().substr(errorPosition)
273  << "\n Returned empty RPN vector and result false." << std::endl;
274 
275  // clear the rpn vector before returning
276  clearRpnVector();
277 
278  return false;
279  }
280 
281  // pop stack until a left parenthesis is found
282  do {
283  if (operatorStack.top().operation != OP_OPENBRACKET) {
284  m_rpnVector.push_back(operatorStack.top()); // pop
285  operatorStack.pop();
286  }
287  if (operatorStack.empty()) { // the operatorStack must not be empty
288 
289  int errorPosition = exprStringStream.tellg();
290 
291  edm::LogError("L1GtLogicParser") << "\nLogical expression = '" << logicalExpressionVal << "'"
292  << "\n Syntax error during parsing - misplaced ')':"
293  << "\n " << exprStringStream.str().substr(0, errorPosition)
294  << "\n " << exprStringStream.str().substr(errorPosition)
295  << "\n Returned empty RPN vector and result false." << std::endl;
296 
297  // clear the rpn vector before returning
298  clearRpnVector();
299  return false;
300  }
301  } while (operatorStack.top().operation != OP_OPENBRACKET);
302 
303  operatorStack.pop(); // pop the open bracket.
304  }
305 
306  break;
307  default: {
308  // empty
309  } break;
310  }
311 
312  lastOperation = actualOperation; // for the next turn
313  }
314 
315  // pop the rest of the operator stack
316  while (!operatorStack.empty()) {
317  if (operatorStack.top().operation == OP_OPENBRACKET) {
318  edm::LogError("L1GtLogicParser") << "\nLogical expression = '" << logicalExpressionVal << "'"
319  << "\n Syntax error during parsing - missing ')':"
320  << "\n Returned empty RPN vector and result false." << std::endl;
321 
322  // clear the rpn vector before returning
323  clearRpnVector();
324  return false;
325  }
326 
327  m_rpnVector.push_back(operatorStack.top());
328  operatorStack.pop();
329  }
330 
331  // count all operations and check if the result is 1
332  int counter = 0;
333  for (RpnVector::iterator it = m_rpnVector.begin(); it != m_rpnVector.end(); it++) {
334  if (it->operation == OP_OPERAND)
335  counter++;
336  if (it->operation == OP_OR || it->operation == OP_AND)
337  counter--;
338  if (counter < 1) {
339  edm::LogError("L1GtLogicParser") << "\nLogical expression = '" << logicalExpressionVal << "'"
340  << "\n Syntax error during parsing - too many operators"
341  << "\n Returned empty RPN vector and result false." << std::endl;
342 
343  // clear the rpn vector before returning
344  clearRpnVector();
345  return false;
346  }
347  }
348 
349  if (counter > 1) {
350  edm::LogError("L1GtLogicParser") << "\nLogical expression = '" << logicalExpressionVal << "'"
351  << "\n Syntax error during parsing - too many operands"
352  << "\n Returned empty RPN vector and result false." << std::endl;
353 
354  // clear the rpn vector before returning
355  clearRpnVector();
356  return false;
357  }
358 
359  return true;
360 }
361 
362 // clear rpn vector
364 
365 // build from the RPN vector the operand token vector
366 // dummy tokenNumber and token result
368  //LogTrace("L1GtLogicParser")
369  //<< "\nL1GtLogicParser::buildOperandTokenVector - "
370  //<< std::endl;
371 
372  // reserve memory
373  size_t rpnVectorSize = m_rpnVector.size();
374  m_operandTokenVector.reserve(rpnVectorSize);
375 
376  int opNumber = 0;
377 
378  for (RpnVector::const_iterator it = m_rpnVector.begin(); it != m_rpnVector.end(); it++) {
379  //LogTrace("L1GtLogicParser")
380  //<< "\nit->operation = " << it->operation
381  //<< "\nit->operand = '" << it->operand << "'\n"
382  //<< std::endl;
383 
384  switch (it->operation) {
385  case OP_OPERAND: {
386  OperandToken opToken;
387  opToken.tokenName = it->operand;
388  opToken.tokenNumber = opNumber;
389  opToken.tokenResult = false;
390 
391  m_operandTokenVector.push_back(opToken);
392 
393  }
394 
395  break;
396  case OP_NOT: {
397  // do nothing
398  }
399 
400  break;
401  case OP_OR: {
402  // do nothing
403  }
404 
405  break;
406  case OP_AND: {
407  // do nothing
408  }
409 
410  break;
411  default: {
412  // should not arrive here
413  }
414 
415  break;
416  }
417 
418  opNumber++;
419  }
420 }
421 
422 // return the position index of the operand in the logical expression
423 int L1GtLogicParser::operandIndex(const std::string& operandNameVal) const {
424  int result = -1;
425 
426  OperationType actualOperation = OP_NULL;
427  OperationType lastOperation = OP_NULL;
428 
429  std::string tokenString;
430  TokenRPN rpnToken; // token to be used by getOperation
431 
432  // stringstream to separate all tokens
433  std::istringstream exprStringStream(m_logicalExpression);
434 
435  // temporary index for usage in the loop
436  int tmpIndex = -1;
437 
438  while (!exprStringStream.eof()) {
439  exprStringStream >> tokenString;
440 
441  //LogTrace("L1GtLogicParser")
442  //<< "Token string = " << tokenString
443  //<< std::endl;
444 
445  actualOperation = getOperation(tokenString, lastOperation, rpnToken);
446  if (actualOperation == OP_INVALID) {
447  // it should never be invalid
448  edm::LogError("L1GtLogicParser") << "\nLogical expression = '" << m_logicalExpression << "'"
449  << "\n Invalid operation/operand " << operandNameVal
450  << "\n Returned index is by default out of range (-1)." << std::endl;
451 
452  return result;
453  }
454 
455  if (actualOperation != OP_OPERAND) {
456  // do nothing
457 
458  } else {
459  tmpIndex++;
460  if (rpnToken.operand == operandNameVal) {
461  result = tmpIndex;
462 
463  //LogDebug("L1GtLogicParser")
464  //<< "\nL1GtLogicParser::operandIndex - "
465  //<< "\nLogical expression = '" << m_logicalExpression << "'"
466  //<< "\nIndex of operand " << operandNameVal << " = " << result
467  //<< std::endl;
468 
469  return result;
470  }
471  }
472  lastOperation = actualOperation;
473  }
474 
475  //
476  edm::LogError("L1GtLogicParser") << "\nLogical expression = '" << m_logicalExpression << "'"
477  << "\n Operand " << operandNameVal << " not found in the logical expression"
478  << "\n Returned index is by default out of range (-1)." << std::endl;
479 
480  return result;
481 }
482 
483 // return the name of the (iOperand)th operand in the logical expression
484 std::string L1GtLogicParser::operandName(const int iOperand) const {
486 
487  OperationType actualOperation = OP_NULL;
488  OperationType lastOperation = OP_NULL;
489 
490  std::string tokenString;
491  TokenRPN rpnToken; // token to be used by getOperation
492 
493  // stringstream to separate all tokens
494  std::istringstream exprStringStream(m_logicalExpression);
495 
496  // temporary index for usage in the loop
497  int tmpIndex = -1;
498 
499  while (!exprStringStream.eof()) {
500  exprStringStream >> tokenString;
501 
502  //LogTrace("L1GtLogicParser")
503  //<< "Token string = " << tokenString
504  //<< std::endl;
505 
506  actualOperation = getOperation(tokenString, lastOperation, rpnToken);
507  if (actualOperation == OP_INVALID) {
508  // it should never be invalid
509  edm::LogError("L1GtLogicParser") << "\nLogical expression = '" << m_logicalExpression << "'"
510  << "\n Invalid operation/operand at position " << iOperand
511  << "\n Returned empty name by default." << std::endl;
512 
513  return result;
514  }
515 
516  if (actualOperation != OP_OPERAND) {
517  // do nothing
518 
519  } else {
520  tmpIndex++;
521  if (tmpIndex == iOperand) {
522  result = rpnToken.operand;
523 
524  //LogDebug("L1GtLogicParser")
525  //<< "\nL1GtLogicParser::operandName - "
526  //<< "\nLogical expression = '" << m_logicalExpression << "'"
527  //<< "\nOperand with index " << iOperand << " = " << result
528  //<< std::endl;
529 
530  return result;
531  }
532  }
533  lastOperation = actualOperation;
534  }
535 
536  //
537  edm::LogError("L1GtLogicParser") << "\nLogical expression = '" << m_logicalExpression << "'"
538  << "\n No operand found at position " << iOperand
539  << "\n Returned empty name by default." << std::endl;
540 
541  return result;
542 }
543 
544 // return the result for an operand with name operandNameVal
545 // in the logical expression using the operand token vector
546 bool L1GtLogicParser::operandResult(const std::string& operandNameVal) const {
547  for (size_t i = 0; i < m_operandTokenVector.size(); ++i) {
548  if ((m_operandTokenVector[i]).tokenName == operandNameVal) {
549  return (m_operandTokenVector[i]).tokenResult;
550  }
551  }
552 
553  // return false - should not arrive here
554  edm::LogError("L1GtLogicParser") << "\n Operand " << operandNameVal << " not found in the operand token vector"
555  << "\n Returned false by default." << std::endl;
556 
557  return false;
558 }
559 
560 // return the result for an operand with tokenNumberVal
561 // using the operand token vector
562 bool L1GtLogicParser::operandResult(const int tokenNumberVal) const {
563  for (size_t i = 0; i < m_operandTokenVector.size(); ++i) {
564  if ((m_operandTokenVector[i]).tokenNumber == tokenNumberVal) {
565  return (m_operandTokenVector[i]).tokenResult;
566  }
567  }
568 
569  // return false - should not arrive here
570  edm::LogError("L1GtLogicParser") << "\n No operand with token number " << tokenNumberVal
571  << " found in the operand token vector"
572  << "\n Returned false by default." << std::endl;
573 
574  return false;
575 }
576 
577 // return the result for the logical expression
578 // require a proper operand token vector
580  //LogTrace("L1GtLogicParser")
581  //<< "\nL1GtLogicParser::expressionResult - "
582  //<< std::endl;
583 
584  // return false if there is no RPN vector built
585  if (m_rpnVector.empty()) {
586  edm::LogError("L1GtLogicParser") << "\n No built RPN vector exists."
587  << "\n Returned false by default." << std::endl;
588  return false;
589  }
590 
591  // stack containing temporary results
592  std::stack<bool> resultStack;
593  bool b1, b2;
594 
595  for (RpnVector::const_iterator it = m_rpnVector.begin(); it != m_rpnVector.end(); it++) {
596  //LogTrace("L1GtLogicParser")
597  //<< "\nit->operation = " << it->operation
598  //<< "\nit->operand = '" << it->operand << "'\n"
599  //<< std::endl;
600 
601  switch (it->operation) {
602  case OP_OPERAND: {
603  resultStack.push(operandResult(it->operand));
604  }
605 
606  break;
607  case OP_NOT: {
608  b1 = resultStack.top();
609  resultStack.pop(); // pop the top
610  resultStack.push(!b1); // and push the result
611  }
612 
613  break;
614  case OP_OR: {
615  b1 = resultStack.top();
616  resultStack.pop();
617  b2 = resultStack.top();
618  resultStack.pop();
619  resultStack.push(b1 || b2);
620  }
621 
622  break;
623  case OP_AND: {
624  b1 = resultStack.top();
625  resultStack.pop();
626  b2 = resultStack.top();
627  resultStack.pop();
628  resultStack.push(b1 && b2);
629  }
630 
631  break;
632  default: {
633  // should not arrive here
634  }
635 
636  break;
637  }
638  }
639 
640  // get the result in the top of the stack
641 
642  //LogTrace("L1GtLogicParser")
643  //<< "\nL1GtLogicParser::expressionResult - "
644  //<< "\nResult = " << resultStack.top()
645  //<< std::endl;
646 
647  return resultStack.top();
648 }
649 
650 // return the result for an operand with name operandNameVal
651 // in the logical expression using a numerical expression
652 bool L1GtLogicParser::operandResultNumExp(const std::string& operandNameVal) const {
653  bool result = false;
654 
655  // get the position index of the operand in the logical string
656  const int iOperand = operandIndex(operandNameVal);
657 
658  result = operandResult(iOperand);
659 
660  return result;
661 }
662 
663 // return the result for an operand with index iOperand
664 // in the logical expression using a numerical expression
665 bool L1GtLogicParser::operandResultNumExp(const int iOperand) const {
666  bool result = false;
667 
668  // parse the numerical expression
669 
670  OperationType actualOperation = OP_NULL;
671  OperationType lastOperation = OP_NULL;
672 
673  std::string tokenString;
674  TokenRPN rpnToken; // token to be used by getOperation
675 
676  // stringstream to separate all tokens
677  std::istringstream exprStringStream(m_numericalExpression);
678 
679  // temporary index for usage in the loop
680  int tmpIndex = -1;
681 
682  while (!exprStringStream.eof()) {
683  exprStringStream >> tokenString;
684 
685  //LogTrace("L1GtLogicParser")
686  //<< "Token string = " << tokenString
687  //<< std::endl;
688 
689  actualOperation = getOperation(tokenString, lastOperation, rpnToken);
690  if (actualOperation == OP_INVALID) {
691  // it should never be invalid
692  edm::LogError("L1GtLogicParser") << "\nNumerical expression = '" << m_numericalExpression << "'"
693  << "\n Invalid operation/operand at position " << iOperand
694  << "\n Returned false by default." << std::endl;
695 
696  result = false;
697  return result;
698  }
699 
700  if (actualOperation != OP_OPERAND) {
701  // do nothing
702 
703  } else {
704  tmpIndex++;
705  if (tmpIndex == iOperand) {
706  if (rpnToken.operand == "1") {
707  result = true;
708  } else {
709  if (rpnToken.operand == "0") {
710  result = false;
711  } else {
712  // something went wrong - break
713  //
714  edm::LogError("L1GtLogicParser") << "\nNumerical expression = '" << m_numericalExpression << "'"
715  << "\n Invalid result for operand at position " << iOperand << ": "
716  << rpnToken.operand << "\n It must be 0 or 1"
717  << "\n Returned false by default." << std::endl;
718 
719  result = false;
720  return result;
721  }
722  }
723 
724  //LogDebug("L1GtLogicParser")
725  //<< "\nL1GtLogicParser::operandResult - "
726  //<< "\nNumerical expression = '" << m_numericalExpression << "'"
727  //<< "\nResult for operand with index " << iOperand
728  //<< " = " << result << "'\n"
729  //<< std::endl;
730 
731  return result;
732  }
733  }
734  lastOperation = actualOperation;
735  }
736 
737  //
738  edm::LogError("L1GtLogicParser") << "\nNumerical expression = '" << m_numericalExpression << "'"
739  << "\n No operand found at position " << iOperand
740  << "\n Returned false by default." << std::endl;
741 
742  return result;
743 }
744 
745 // build from the RPN vector the operand token vector
746 // using a numerical expression
748  //LogTrace("L1GtLogicParser")
749  //<< "\nL1GtLogicParser::buildOperandTokenVector - "
750  //<< std::endl;
751 
752  // reserve memory
753  size_t rpnVectorSize = m_rpnVector.size();
754  m_operandTokenVector.reserve(rpnVectorSize);
755 
756  int opNumber = 0;
757 
758  for (RpnVector::const_iterator it = m_rpnVector.begin(); it != m_rpnVector.end(); it++) {
759  //LogTrace("L1GtLogicParser")
760  //<< "\nit->operation = " << it->operation
761  //<< "\nit->operand = '" << it->operand << "'\n"
762  //<< std::endl;
763 
764  switch (it->operation) {
765  case OP_OPERAND: {
766  OperandToken opToken;
767  opToken.tokenName = it->operand;
768  opToken.tokenNumber = opNumber;
769  opToken.tokenResult = operandResultNumExp(it->operand);
770 
771  m_operandTokenVector.push_back(opToken);
772 
773  }
774 
775  break;
776  case OP_NOT: {
777  // do nothing
778  }
779 
780  break;
781  case OP_OR: {
782  // do nothing
783  }
784 
785  break;
786  case OP_AND: {
787  // do nothing
788  }
789 
790  break;
791  default: {
792  // should not arrive here
793  }
794 
795  break;
796  }
797 
798  opNumber++;
799  }
800 }
801 
802 // return the result for the logical expression
804  //LogTrace("L1GtLogicParser")
805  //<< "\nL1GtLogicParser::expressionResult - "
806  //<< std::endl;
807 
808  // return false if there is no expression
809  if (m_rpnVector.empty()) {
810  edm::LogError("L1GtLogicParser") << "\n No built RPN vector exists."
811  << "\n Returned false by default." << std::endl;
812  return false;
813  }
814 
815  // stack containing temporary results
816  std::stack<bool> resultStack;
817  bool b1, b2;
818 
819  for (RpnVector::const_iterator it = m_rpnVector.begin(); it != m_rpnVector.end(); it++) {
820  //LogTrace("L1GtLogicParser")
821  //<< "\nit->operation = " << it->operation
822  //<< "\nit->operand = '" << it->operand << "'\n"
823  //<< std::endl;
824 
825  switch (it->operation) {
826  case OP_OPERAND: {
827  resultStack.push(operandResultNumExp(it->operand));
828  }
829 
830  break;
831  case OP_NOT: {
832  b1 = resultStack.top();
833  resultStack.pop(); // pop the top
834  resultStack.push(!b1); // and push the result
835  }
836 
837  break;
838  case OP_OR: {
839  b1 = resultStack.top();
840  resultStack.pop();
841  b2 = resultStack.top();
842  resultStack.pop();
843  resultStack.push(b1 || b2);
844  }
845 
846  break;
847  case OP_AND: {
848  b1 = resultStack.top();
849  resultStack.pop();
850  b2 = resultStack.top();
851  resultStack.pop();
852  resultStack.push(b1 && b2);
853  }
854 
855  break;
856  default: {
857  // should not arrive here
858  }
859 
860  break;
861  }
862  }
863 
864  // get the result in the top of the stack
865 
866  //LogTrace("L1GtLogicParser")
867  //<< "\nL1GtLogicParser::expressionResult - "
868  //<< "\nLogical expression = '" << m_logicalExpression << "'"
869  //<< "\nNumerical expression = '" << m_numericalExpression << "'"
870  //<< "\nResult = " << resultStack.top()
871  //<< std::endl;
872 
873  return resultStack.top();
874 }
875 
876 // convert the logical expression composed with names to
877 // a logical expression composed with int numbers using
878 // a (string, int) map
879 
880 void L1GtLogicParser::convertNameToIntLogicalExpression(const std::map<std::string, int>& nameToIntMap) {
881  if (m_logicalExpression.empty()) {
882  return;
883  }
884 
885  // non-empty logical expression
886 
887  OperationType actualOperation = OP_NULL;
888  OperationType lastOperation = OP_NULL;
889 
890  std::string tokenString;
891  TokenRPN rpnToken; // token to be used by getOperation
892 
893  int intValue = -1;
894 
895  // stringstream to separate all tokens
896  std::istringstream exprStringStream(m_logicalExpression);
897  std::string convertedLogicalExpression;
898 
899  while (!exprStringStream.eof()) {
900  exprStringStream >> tokenString;
901 
902  actualOperation = getOperation(tokenString, lastOperation, rpnToken);
903  if (actualOperation == OP_INVALID) {
904  // it should never be invalid
905  edm::LogError("L1GtLogicParser") << "\nLogical expression = '" << m_logicalExpression << "'"
906  << "\n Invalid operation/operand in logical expression."
907  << "\n Return empty logical expression." << std::endl;
908 
909  m_logicalExpression.clear();
910  return;
911  }
912 
913  if (actualOperation != OP_OPERAND) {
914  convertedLogicalExpression.append(getRuleFromType(actualOperation)->opString);
915 
916  } else {
917  typedef std::map<std::string, int>::const_iterator CIter;
918 
919  CIter it = nameToIntMap.find(rpnToken.operand);
920  if (it != nameToIntMap.end()) {
921  intValue = it->second;
922  std::stringstream intStr;
923  intStr << intValue;
924  convertedLogicalExpression.append(intStr.str());
925 
926  } else {
927  // it should never be happen
928  edm::LogError("L1GtLogicParser") << "\nLogical expression = '" << m_logicalExpression << "'"
929  << "\n Could not convert " << rpnToken.operand << " to integer!"
930  << "\n Return empty logical expression." << std::endl;
931 
932  m_logicalExpression.clear();
933  return;
934  }
935  }
936 
937  convertedLogicalExpression.append(" "); // one whitespace after each token
938  lastOperation = actualOperation;
939  }
940 
941  // remove the last space
942  //convertedLogicalExpression.erase(convertedLogicalExpression.size() - 1);
943  boost::trim(convertedLogicalExpression);
944 
945  LogDebug("L1GtLogicParser") << "\nL1GtLogicParser::convertNameToIntLogicalExpression - "
946  << "\nLogical expression (strings) = '" << m_logicalExpression << "'"
947  << "\nLogical expression (int) = '" << convertedLogicalExpression << "'\n"
948  << std::endl;
949 
950  // replace now the logical expression with strings with
951  // the converted logical expression
952 
953  m_logicalExpression = convertedLogicalExpression;
954 
955  return;
956 }
957 
958 // convert a logical expression composed with integer numbers to
959 // a logical expression composed with names using a map (int, string)
960 
961 void L1GtLogicParser::convertIntToNameLogicalExpression(const std::map<int, std::string>& intToNameMap) {
962  if (m_logicalExpression.empty()) {
963  return;
964  }
965 
966  // non-empty logical expression
967 
968  OperationType actualOperation = OP_NULL;
969  OperationType lastOperation = OP_NULL;
970 
971  std::string tokenString;
972  TokenRPN rpnToken; // token to be used by getOperation
973 
974  // stringstream to separate all tokens
975  std::istringstream exprStringStream(m_logicalExpression);
976  std::string convertedLogicalExpression;
977 
978  while (!exprStringStream.eof()) {
979  exprStringStream >> tokenString;
980 
981  actualOperation = getOperation(tokenString, lastOperation, rpnToken);
982  if (actualOperation == OP_INVALID) {
983  // it should never be invalid
984  edm::LogError("L1GtLogicParser") << "\nLogical expression = '" << m_logicalExpression << "'"
985  << "\n Invalid operation/operand in logical expression."
986  << "\n Return empty logical expression." << std::endl;
987 
988  m_logicalExpression.clear();
989  return;
990  }
991 
992  if (actualOperation != OP_OPERAND) {
993  convertedLogicalExpression.append(getRuleFromType(actualOperation)->opString);
994 
995  } else {
996  typedef std::map<int, std::string>::const_iterator CIter;
997 
998  // convert string to int
999  int indexInt;
1000  std::istringstream iss(rpnToken.operand);
1001  iss >> std::dec >> indexInt;
1002 
1003  CIter it = intToNameMap.find(indexInt);
1004  if (it != intToNameMap.end()) {
1005  convertedLogicalExpression.append(it->second);
1006 
1007  } else {
1008  // it should never be happen
1009  edm::LogError("L1GtLogicParser") << "\nLogical expression = '" << m_logicalExpression << "'"
1010  << "\n Could not convert " << rpnToken.operand << " to string!"
1011  << "\n Return empty logical expression." << std::endl;
1012 
1013  m_logicalExpression.clear();
1014  return;
1015  }
1016  }
1017 
1018  convertedLogicalExpression.append(" "); // one whitespace after each token
1019  lastOperation = actualOperation;
1020  }
1021 
1022  // remove the last space
1023  //convertedLogicalExpression.erase(convertedLogicalExpression.size() - 1);
1024  boost::trim(convertedLogicalExpression);
1025 
1026  //LogDebug("L1GtLogicParser")
1027  // << "\nL1GtLogicParser::convertIntToNameLogicalExpression - "
1028  // << "\nLogical expression (int) = '" << m_logicalExpression << "'"
1029  // << "\nLogical expression (string) = '" << convertedLogicalExpression << "'\n"
1030  // << std::endl;
1031 
1032  // replace now the logical expression with int with
1033  // the converted logical expression
1034 
1035  m_logicalExpression = convertedLogicalExpression;
1036 
1037  return;
1038 }
1039 
1040 // return the list of operand tokens for the logical expression
1041 // which are to be used as seeds
1042 std::vector<L1GtLogicParser::OperandToken> L1GtLogicParser::expressionSeedsOperandList() {
1043  //LogDebug("L1GtLogicParser")
1044  //<< "\nL1GtLogicParser::expressionSeedsOperandList - "
1045  //<< "\nLogical expression = '" << m_logicalExpression << "'"
1046  //<< "\nm_rpnVector.size() = " << m_rpnVector.size()
1047  //<< "\nm_operandTokenVector.size() = " << m_operandTokenVector.size()
1048  //<< std::endl;
1049 
1050  // seed list
1051  std::vector<OperandToken> opVector;
1052  opVector.reserve(m_operandTokenVector.size());
1053 
1054  // temporary results
1055  std::stack<OperandToken> tmpStack;
1056  std::vector<OperandToken> tmpVector;
1057  tmpVector.reserve(m_operandTokenVector.size());
1058 
1059  OperandToken b1, b2;
1060 
1061  bool newOperandBlock = true;
1062  bool oneBlockOnly = true;
1063  bool operandOnly = true;
1064 
1065  int iOperand = -1;
1066 
1067  OperandToken dummyToken;
1068  dummyToken.tokenName = "dummy";
1069  dummyToken.tokenNumber = -1;
1070  dummyToken.tokenResult = false;
1071 
1072  for (RpnVector::const_iterator it = m_rpnVector.begin(); it != m_rpnVector.end(); it++) {
1073  //LogTrace("L1GtLogicParser")
1074  //<< "\nit->operation = " << it->operation
1075  //<< "\nit->operand = '" << it->operand << "'\n"
1076  //<< std::endl;
1077 
1078  switch (it->operation) {
1079  // RPN always start a block with an operand
1080  case OP_OPERAND: {
1081  // more blocks with operations
1082  // push operands from previous block, if any in the tmpVector
1083  // (reverse order to compensate the stack push/top/pop)
1084  if ((!newOperandBlock)) {
1085  for (std::vector<OperandToken>::reverse_iterator itOp = tmpVector.rbegin(); itOp != tmpVector.rend();
1086  itOp++) {
1087  opVector.push_back(*itOp);
1088 
1089  //LogTrace("L1GtLogicParser")
1090  //<< " Push operand " << (*itOp).tokenName
1091  //<<" on the seed operand list"
1092  //<< std::endl;
1093  }
1094 
1095  tmpVector.clear();
1096 
1097  newOperandBlock = true;
1098  oneBlockOnly = false;
1099  }
1100 
1101  iOperand++;
1102 
1103  //LogTrace("L1GtLogicParser")
1104  //<< " Push operand " << (m_operandTokenVector.at(iOperand)).tokenName
1105  //<< " on the operand stack"
1106  //<< std::endl;
1107 
1108  tmpStack.push(m_operandTokenVector.at(iOperand));
1109  }
1110 
1111  break;
1112  case OP_NOT: {
1113  newOperandBlock = false;
1114  operandOnly = false;
1115 
1116  b1 = tmpStack.top();
1117  tmpStack.pop(); // pop the top
1118 
1119  tmpStack.push(dummyToken); // and push dummy result
1120 
1121  //LogTrace("L1GtLogicParser")
1122  //<< " Clear tmp operand list"
1123  //<< std::endl;
1124 
1125  tmpVector.clear();
1126 
1127  }
1128 
1129  break;
1130  case OP_OR: {
1131  newOperandBlock = false;
1132  operandOnly = false;
1133 
1134  b1 = tmpStack.top();
1135  tmpStack.pop();
1136  b2 = tmpStack.top();
1137  tmpStack.pop();
1138 
1139  tmpStack.push(dummyToken); // and push dummy result
1140 
1141  if (b1.tokenNumber >= 0) {
1142  tmpVector.push_back(b1);
1143 
1144  //LogTrace("L1GtLogicParser")
1145  //<< " Push operand " << b1.tokenName
1146  //<<" on the tmp list"
1147  //<< std::endl;
1148  }
1149 
1150  if (b2.tokenNumber >= 0) {
1151  tmpVector.push_back(b2);
1152 
1153  //LogTrace("L1GtLogicParser")
1154  //<< " Push operand " << b2.tokenName
1155  //<<" on the tmp list"
1156  //<< std::endl;
1157  }
1158 
1159  }
1160 
1161  break;
1162  case OP_AND: {
1163  newOperandBlock = false;
1164  operandOnly = false;
1165 
1166  b1 = tmpStack.top();
1167  tmpStack.pop();
1168  b2 = tmpStack.top();
1169  tmpStack.pop();
1170 
1171  tmpStack.push(dummyToken);
1172 
1173  if (b1.tokenNumber >= 0) {
1174  tmpVector.push_back(b1);
1175 
1176  //LogTrace("L1GtLogicParser")
1177  //<< " Push operand " << b1.tokenName
1178  //<<" on the tmp list"
1179  //<< std::endl;
1180  }
1181 
1182  if (b2.tokenNumber >= 0) {
1183  tmpVector.push_back(b2);
1184 
1185  //LogTrace("L1GtLogicParser")
1186  //<< " Push operand " << b2.tokenName
1187  //<<" on the tmp list"
1188  //<< std::endl;
1189  }
1190 
1191  }
1192 
1193  break;
1194  default: {
1195  // should not arrive here
1196  }
1197 
1198  break;
1199  }
1200  }
1201 
1202  // one block only or one operand only
1203  if (oneBlockOnly || operandOnly) {
1204  // one operand only -
1205  // there can be only one operand, otherwise one needs an operation
1206  if (operandOnly) {
1207  b1 = tmpStack.top();
1208  tmpVector.push_back(b1);
1209  }
1210 
1211  //
1212  for (std::vector<OperandToken>::reverse_iterator itOp = tmpVector.rbegin(); itOp != tmpVector.rend(); itOp++) {
1213  opVector.push_back(*itOp);
1214 
1215  //LogTrace("L1GtLogicParser")
1216  //<< " One block or one operand only: push operand " << (*itOp).tokenName
1217  //<<" on the seed operand list"
1218  //<< std::endl;
1219  }
1220 
1221  } else {
1222  //LogTrace("L1GtLogicParser")
1223  // << " More blocks: push the last block on the seed operand list" << std::endl;
1224 
1225  for (std::vector<OperandToken>::reverse_iterator itOp = tmpVector.rbegin(); itOp != tmpVector.rend(); itOp++) {
1226  opVector.push_back(*itOp);
1227 
1228  //LogTrace("L1GtLogicParser")
1229  //<< " Push operand: " << (*itOp).tokenName
1230  //<<" on the seed operand list"
1231  //<< std::endl;
1232  }
1233  }
1234 
1235  // remove duplicates from the seed vector
1236  // slow...
1237  std::vector<OperandToken> opVectorU;
1238  opVectorU.reserve(opVector.size());
1239 
1240  for (std::vector<OperandToken>::const_iterator constIt = opVector.begin(); constIt != opVector.end(); constIt++) {
1241  bool tokenIncluded = false;
1242 
1243  for (std::vector<OperandToken>::iterator itOpU = opVectorU.begin(); itOpU != opVectorU.end(); itOpU++) {
1244  if ((*itOpU).tokenName == (*constIt).tokenName) {
1245  tokenIncluded = true;
1246  break;
1247  }
1248  }
1249 
1250  if (!tokenIncluded) {
1251  opVectorU.push_back(*constIt);
1252  }
1253  }
1254 
1255  return opVectorU;
1256 }
1257 
1258 // private methods
1259 
1272  OperationType lastOperation,
1273  TokenRPN& rpnToken) const {
1274  OperationType actualOperation = OP_OPERAND; // default value
1275 
1276  int i = 0;
1277 
1278  while (m_operationRules[i].opType != OP_OPERAND) {
1279  if (tokenString == m_operationRules[i].opString) {
1280  actualOperation = (OperationType)m_operationRules[i].opType;
1281  break;
1282  }
1283  i++;
1284  }
1285 
1286  // check if the operation is allowed
1287  if (m_operationRules[i].forbiddenLastOperation & lastOperation) {
1288  return OP_INVALID;
1289  }
1290 
1291  //
1292  if (actualOperation == OP_OPERAND) {
1293  rpnToken.operand = tokenString;
1294 
1295  } else {
1296  rpnToken.operand = "";
1297  }
1298 
1299  rpnToken.operation = actualOperation;
1300 
1301  // else we got a valid operation
1302  return actualOperation;
1303 }
1304 
1316  int i = 0;
1317 
1318  while ((m_operationRules[i].opType != oType) && (m_operationRules[i].opType != OP_NULL)) {
1319  i++;
1320  }
1321 
1322  if (m_operationRules[i].opType == OP_NULL) {
1323  return nullptr;
1324  }
1325 
1326  return &(m_operationRules[i]);
1327 }
1328 
1329 // add spaces before and after parentheses - make separation easier
1330 void L1GtLogicParser::addBracketSpaces(const std::string& srcExpression, std::string& dstExpression) {
1331  static const std::string brackets = "()"; // the brackets to be found
1332 
1333  dstExpression = srcExpression; // copy the string
1334 
1335  size_t position = 0;
1336  while ((position = dstExpression.find_first_of(brackets, position)) != std::string::npos) {
1337  // add space after if none is there
1338  if (((position + 1) != std::string::npos) && (dstExpression[position + 1] != ' ')) {
1339  dstExpression.insert(position + 1, " ");
1340  }
1341 
1342  // add space before if none is there
1343  if ((position != 0) && (dstExpression[position - 1] != ' ')) {
1344  dstExpression.insert(position, " ");
1345  position++;
1346  }
1347  position++;
1348  }
1349 }
1350 
1351 // set the logical expression - check for correctness the input string
1352 bool L1GtLogicParser::setLogicalExpression(const std::string& logicalExpressionVal) {
1353  // add spaces around brackets
1354  std::string logicalExpressionBS;
1355  addBracketSpaces(logicalExpressionVal, logicalExpressionBS);
1356 
1357  // trim leading or trailing spaces
1358  boost::trim(logicalExpressionBS);
1359 
1360  clearRpnVector();
1361 
1362  if (!buildRpnVector(logicalExpressionBS)) {
1363  m_logicalExpression = "";
1364  return false;
1365  }
1366 
1367  m_logicalExpression = logicalExpressionBS;
1368 
1369  //LogDebug("L1GtLogicParser")
1370  //<< "\nL1GtLogicParser::setLogicalExpression - "
1371  //<< "\nLogical expression = '" << m_logicalExpression << "'\n"
1372  //<< std::endl;
1373 
1374  return true;
1375 }
1376 
1377 // set the numerical expression (the logical expression with each operand
1378 // replaced with the value) from a string
1379 // check also for correctness the input string
1380 bool L1GtLogicParser::setNumericalExpression(const std::string& numericalExpressionVal) {
1381  // add spaces around brackets
1382  std::string numericalExpressionBS;
1383  addBracketSpaces(numericalExpressionVal, numericalExpressionBS);
1384 
1385  // check for consistency with the logical expression
1386  // TODO FIXME
1387 
1388  // trim leading or trailing spaces
1389  boost::trim(numericalExpressionBS);
1390 
1391  m_numericalExpression = numericalExpressionBS;
1392 
1393  //LogDebug("L1GtLogicParser")
1394  //<< "\nL1GtLogicParser::setNumericalExpression - "
1395  //<< "\nNumerical Expression = '" << m_numericalExpression << "'\n"
1396  //<< std::endl;
1397 
1398  return true;
1399 }
1400 
1401 // static members
1402 
1403 // rules for operations
1404 // 1st column: operation string
1405 // 2nd column: operation type
1406 // 3rd column: forbiddenLastOperation (what operation the operator/operand must not follow)
1408  {"AND", OP_AND, OP_AND | OP_OR | OP_NOT | OP_OPENBRACKET | OP_NULL},
1409  {"OR", OP_OR, OP_AND | OP_OR | OP_NOT | OP_OPENBRACKET | OP_NULL},
1410  {"NOT", OP_NOT, OP_OPERAND | OP_CLOSEBRACKET},
1413  {nullptr, OP_OPERAND, OP_OPERAND | OP_CLOSEBRACKET},
1414  {nullptr, OP_NULL, OP_NULL}};
std::vector< L1GtLogicParser::OperandToken > expressionSeedsOperandList()
void clearRpnVector()
clear possible old rpn vector
signed integer value
Definition: value.h:25
void convertNameToIntLogicalExpression(const std::map< std::string, int > &nameToIntMap)
bool operandResult(const std::string &operandNameVal) const
bool operandResultNumExp(const std::string &operandNameVal) const
int operandIndex(const std::string &operandNameVal) const
return the position index of the operand in the logical expression
bool buildRpnVector(const std::string &)
build the rpn vector
static void trim(std::string &s)
void buildOperandTokenVectorNumExp()
Log< level::Error, false > LogError
void addBracketSpaces(const std::string &, std::string &)
add spaces before and after parantheses
L1GtLogicParser()
constructor(s)
void convertIntToNameLogicalExpression(const std::map< int, std::string > &intToNameMap)
std::vector< OperandToken > m_operandTokenVector
vector of operand tokens
const OperationRule * getRuleFromType(OperationType t)
get the rule entry to an operation type
bool setNumericalExpression(const std::string &)
bias2_t b2[25]
Definition: b2.h:9
std::string m_logicalExpression
logical expression to be parsed
virtual const bool expressionResultNumExp() const
virtual OperationType getOperation(const std::string &tokenString, OperationType lastOperation, TokenRPN &rpnToken) const
RpnVector m_rpnVector
RPN vector - equivalent to the logical expression.
virtual ~L1GtLogicParser()
destructor
std::string operandName(const int iOperand) const
return the name of the (iOperand)th operand in the logical expression
static int position[264][3]
Definition: ReadPGInfo.cc:289
static const struct OperationRule m_operationRules[]
std::string m_numericalExpression
bool checkLogicalExpression(std::string &)
check a logical expression for correctness - add/remove spaces if needed
std::vector< TokenRPN > RpnVector
void buildOperandTokenVector()
bool setLogicalExpression(const std::string &)
set the logical expression - check for correctness the input string
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle brackets
Definition: Activities.doc:4
virtual const bool expressionResult() const
static constexpr float b1
#define LogDebug(id)