CMS 3D CMS Logo

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