CMS 3D CMS Logo

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