Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:53:53

0001 /**
0002  * \class GlobalLogicParser
0003  *
0004  *
0005  * Description: see header file.
0006  *
0007  * Implementation:
0008  *    <TODO: enter implementation details>
0009  *
0010  * \author: Vasile Mihai Ghete - HEPHY Vienna
0011  *
0012  *
0013  */
0014 
0015 // this class header
0016 #include "DataFormats/L1TGlobal/interface/GlobalLogicParser.h"
0017 
0018 // system include files
0019 #include <stack>
0020 
0021 #include <iostream>
0022 #include <sstream>
0023 
0024 #include <boost/algorithm/string.hpp>
0025 
0026 // user include files
0027 
0028 #include "FWCore/Utilities/interface/EDMException.h"
0029 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0030 
0031 // forward declarations
0032 
0033 // constructor(s)
0034 
0035 //   default constructor
0036 GlobalLogicParser::GlobalLogicParser() {
0037   // empty, default C++ initialization for string and vector are enough
0038 }
0039 
0040 //   from the RPN vector and the operand token vector
0041 //   no checks for consistency, empty logical and numerical expressions
0042 //   requires special care when used
0043 GlobalLogicParser::GlobalLogicParser(const RpnVector& rpnVec, const std::vector<OperandToken>& opTokenVector) {
0044   m_rpnVector = rpnVec;
0045   m_operandTokenVector = opTokenVector;
0046 }
0047 
0048 //   from a constant logical expression
0049 //   numerical expression will be empty
0050 GlobalLogicParser::GlobalLogicParser(const std::string& logicalExpressionVal) {
0051   // checks also for syntactic correctness of the logical expression
0052 
0053   if (!setLogicalExpression(logicalExpressionVal)) {
0054     // error(s) in logical expression - printed in the relevant place
0055     throw cms::Exception("FailModule") << "\nError in parsing the logical expression = " << logicalExpressionVal
0056                                        << std::endl;
0057   }
0058 }
0059 
0060 //   from a non-constant logical expression - add/remove spaces if needed
0061 //   numerical expression will be empty
0062 GlobalLogicParser::GlobalLogicParser(std::string& logicalExpressionVal) {
0063   // checks also for syntactic correctness of the logical expression
0064 
0065   // add spaces around brackets
0066   std::string logicalExpressionBS;
0067   addBracketSpaces(logicalExpressionVal, logicalExpressionBS);
0068 
0069   // trim leading or trailing spaces
0070   boost::trim(logicalExpressionBS);
0071 
0072   if (!buildRpnVector(logicalExpressionBS)) {
0073     // error(s) in logical expression
0074     throw cms::Exception("FailModule") << "\nError in parsing the logical expression = " << logicalExpressionVal
0075                                        << std::endl;
0076   }
0077 
0078   //LogDebug("L1TGlobal")
0079   //    << "\nInitial logical expression = '" << logicalExpressionVal << "'"
0080   //    << "\nFinal   logical expression = '" << logicalExpressionBS << "'\n"
0081   //    << std::endl;
0082 
0083   logicalExpressionVal = logicalExpressionBS;
0084   m_logicalExpression = logicalExpressionVal;
0085 
0086   // build operand token vector
0087   // dummy tokenNumber; tokenResult false
0088   buildOperandTokenVector();
0089 }
0090 
0091 //   from a logical and a numerical expression
0092 GlobalLogicParser::GlobalLogicParser(const std::string logicalExpressionVal, const std::string numericalExpressionVal) {
0093   // checks also for correctness
0094 
0095   if (!setLogicalExpression(logicalExpressionVal)) {
0096     // error(s) in logical expression - printed in the relevant place
0097     throw cms::Exception("FailModule") << "\nError in parsing the logical expression = " << logicalExpressionVal
0098                                        << std::endl;
0099   }
0100 
0101   if (!setNumericalExpression(numericalExpressionVal)) {
0102     // error(s) in numerical expression - printed in the relevant place
0103     throw cms::Exception("FileModule") << "\nError in parsing the numerical expression = " << numericalExpressionVal
0104                                        << std::endl;
0105   }
0106 }
0107 
0108 //   from a logical and a numerical expression
0109 //   no checks for correctness - use it only after the correctness was tested
0110 GlobalLogicParser::GlobalLogicParser(const std::string& logicalExpressionVal,
0111                                      const std::string& numericalExpressionVal,
0112                                      const bool dummy) {
0113   clearRpnVector();
0114   if (!buildRpnVector(logicalExpressionVal)) {
0115     throw cms::Exception("FileModule") << "\nError in building RPN vector for the logical expression = "
0116                                        << logicalExpressionVal << std::endl;
0117   }
0118 
0119   m_logicalExpression = logicalExpressionVal;
0120   m_numericalExpression = numericalExpressionVal;
0121 }
0122 
0123 // destructor
0124 GlobalLogicParser::~GlobalLogicParser() {
0125   // empty now
0126 }
0127 
0128 // public methods
0129 
0130 // check a logical expression for correctness - add/remove spaces if needed
0131 bool GlobalLogicParser::checkLogicalExpression(std::string& logicalExpressionVal) {
0132   // add spaces around brackets
0133   std::string logicalExpressionBS;
0134   addBracketSpaces(logicalExpressionVal, logicalExpressionBS);
0135 
0136   // trim leading or trailing spaces
0137   boost::trim(logicalExpressionBS);
0138 
0139   clearRpnVector();
0140 
0141   if (!buildRpnVector(logicalExpressionBS)) {
0142     return false;
0143   }
0144 
0145   LogDebug("L1TGlobal") << "\nGtLogicParser::checkLogicalExpression - "
0146                         << "\nInitial logical expression = '" << logicalExpressionVal << "'"
0147                         << "\nFinal   logical expression = '" << logicalExpressionBS << "'\n"
0148                         << std::endl;
0149 
0150   logicalExpressionVal = logicalExpressionBS;
0151 
0152   return true;
0153 }
0154 
0155 /**
0156  * buildRpnVector Build the postfix notation.
0157  *
0158  * @param expression The expression to be parsed.
0159  *
0160  * @return "true" if everything was parsed. "false" if an error occured.
0161  *
0162  */
0163 
0164 bool GlobalLogicParser::buildRpnVector(const std::string& logicalExpressionVal) {
0165   //LogDebug("L1TGlobal")
0166   //<< "\nGtLogicParser::buildRpnVector - "
0167   //<< "\nLogical expression = '" << logicalExpressionVal << "'\n"
0168   //<< std::endl;
0169 
0170   OperationType actualOperation = OP_NULL;
0171   OperationType lastOperation = OP_NULL;
0172 
0173   // token as string and as TokenRPN, stack to form the postfix notation
0174   std::string tokenString;
0175   TokenRPN rpnToken;
0176   std::stack<TokenRPN> operatorStack;
0177 
0178   static const std::string whitespaces = " \r\v\n\t";
0179 
0180   // clear possible old rpn vector
0181   clearRpnVector();
0182 
0183   // stringstream to separate all tokens
0184   std::istringstream exprStringStream(logicalExpressionVal);
0185 
0186   while (!exprStringStream.eof()) {
0187     exprStringStream >> std::skipws >> std::ws >> tokenString;
0188 
0189     // skip the end
0190     if (tokenString.find_first_not_of(whitespaces) == std::string::npos || tokenString.length() == 0) {
0191       //LogTrace("L1TGlobal")
0192       //<< "  Break for token string = " << tokenString
0193       //<< std::endl;
0194 
0195       break;
0196     }
0197 
0198     actualOperation = getOperation(tokenString, lastOperation, rpnToken);
0199 
0200     //LogTrace("L1TGlobal")
0201     //<< "  Token string = '" << tokenString << "'"
0202     //<< "\tActual Operation = " << actualOperation
0203     //<< std::endl;
0204 
0205     // http://en.wikipedia.org/wiki/Postfix_notation#Converting_from_infix_notation
0206 
0207     switch (actualOperation) {
0208       case OP_OPERAND: {
0209         // operands get pushed to the postfix notation immediately
0210         m_rpnVector.push_back(rpnToken);
0211       }
0212 
0213       break;
0214       case OP_INVALID: {
0215         int errorPosition = exprStringStream.tellg();
0216 
0217         edm::LogError("L1TGlobal") << "\nLogical expression = '" << logicalExpressionVal << "'"
0218                                    << "\n  Syntax error during parsing: "
0219                                    << "\n     " << exprStringStream.str().substr(0, errorPosition) << "\n     "
0220                                    << exprStringStream.str().substr(errorPosition)
0221                                    << "\n  Returned empty RPN vector and result false." << std::endl;
0222 
0223         // clear the rpn vector before returning
0224         clearRpnVector();
0225 
0226         return false;
0227       }
0228 
0229       break;
0230       case OP_NOT: {
0231         operatorStack.push(rpnToken);
0232         // there are no operators with higher precedence
0233       }
0234 
0235       break;
0236       case OP_XOR: {
0237         // first pop operators with higher precedence (NOT)
0238         while (!operatorStack.empty() && operatorStack.top().operation == OP_NOT) {
0239           m_rpnVector.push_back(operatorStack.top());
0240           operatorStack.pop();
0241         }
0242         operatorStack.push(rpnToken);
0243       }
0244 
0245       break;
0246       case OP_AND: {
0247         // first pop operators with higher precedence (XOR, NOT)
0248         while (!operatorStack.empty() &&
0249                (operatorStack.top().operation == OP_NOT || operatorStack.top().operation == OP_AND)) {
0250           m_rpnVector.push_back(operatorStack.top());
0251           operatorStack.pop();
0252         }
0253         operatorStack.push(rpnToken);
0254       }
0255 
0256       break;
0257       case OP_OR: {
0258         // pop operators with higher precedence (AND, XOR, NOT)
0259         while (!operatorStack.empty() &&
0260                (operatorStack.top().operation == OP_NOT || operatorStack.top().operation == OP_XOR ||
0261                 operatorStack.top().operation == OP_AND)) {
0262           m_rpnVector.push_back(operatorStack.top());
0263           operatorStack.pop();
0264         }
0265         // push operator on stack
0266         operatorStack.push(rpnToken);
0267       }
0268 
0269       break;
0270       case OP_OPENBRACKET: {
0271         // just push it on stack
0272         operatorStack.push(rpnToken);
0273       }
0274 
0275       break;
0276       case OP_CLOSEBRACKET: {
0277         // check if the operatorStack is empty
0278         if (operatorStack.empty()) {
0279           int errorPosition = exprStringStream.tellg();
0280 
0281           edm::LogError("L1TGlobal") << "\nLogical expression = '" << logicalExpressionVal << "'"
0282                                      << "\n  Syntax error during parsing - misplaced ')':"
0283                                      << "\n     " << exprStringStream.str().substr(0, errorPosition) << "\n     "
0284                                      << exprStringStream.str().substr(errorPosition)
0285                                      << "\n  Returned empty RPN vector and result false." << std::endl;
0286 
0287           // clear the rpn vector before returning
0288           clearRpnVector();
0289 
0290           return false;
0291         }
0292 
0293         // pop stack until a left parenthesis is found
0294         do {
0295           if (operatorStack.top().operation != OP_OPENBRACKET) {
0296             m_rpnVector.push_back(operatorStack.top());  // pop
0297             operatorStack.pop();
0298           }
0299           if (operatorStack.empty()) {  // the operatorStack must not be empty
0300 
0301             int errorPosition = exprStringStream.tellg();
0302 
0303             edm::LogError("L1TGlobal") << "\nLogical expression = '" << logicalExpressionVal << "'"
0304                                        << "\n  Syntax error during parsing - misplaced ')':"
0305                                        << "\n     " << exprStringStream.str().substr(0, errorPosition) << "\n     "
0306                                        << exprStringStream.str().substr(errorPosition)
0307                                        << "\n  Returned empty RPN vector and result false." << std::endl;
0308 
0309             // clear the rpn vector before returning
0310             clearRpnVector();
0311             return false;
0312           }
0313         } while (operatorStack.top().operation != OP_OPENBRACKET);
0314 
0315         operatorStack.pop();  // pop the open bracket.
0316       }
0317 
0318       break;
0319       default: {
0320         // empty
0321       } break;
0322     }
0323 
0324     lastOperation = actualOperation;  // for the next turn
0325   }
0326 
0327   // pop the rest of the operator stack
0328   while (!operatorStack.empty()) {
0329     if (operatorStack.top().operation == OP_OPENBRACKET) {
0330       edm::LogError("L1TGlobal") << "\nLogical expression = '" << logicalExpressionVal << "'"
0331                                  << "\n  Syntax error during parsing - missing ')':"
0332                                  << "\n  Returned empty RPN vector and result false." << std::endl;
0333 
0334       // clear the rpn vector before returning
0335       clearRpnVector();
0336       return false;
0337     }
0338 
0339     m_rpnVector.push_back(operatorStack.top());
0340     operatorStack.pop();
0341   }
0342 
0343   // count all operations and check if the result is 1
0344   int counter = 0;
0345   for (RpnVector::iterator it = m_rpnVector.begin(); it != m_rpnVector.end(); it++) {
0346     if (it->operation == OP_OPERAND)
0347       counter++;
0348     if (it->operation == OP_OR || it->operation == OP_AND || it->operation == OP_XOR)
0349       counter--;
0350     if (counter < 1) {
0351       edm::LogError("L1TGlobal") << "\nLogical expression = '" << logicalExpressionVal << "'"
0352                                  << "\n  Syntax error during parsing - too many operators"
0353                                  << "\n  Returned empty RPN vector and result false." << std::endl;
0354 
0355       // clear the rpn vector before returning
0356       clearRpnVector();
0357       return false;
0358     }
0359   }
0360 
0361   if (counter > 1) {
0362     edm::LogError("L1TGlobal") << "\nLogical expression = '" << logicalExpressionVal << "'"
0363                                << "\n  Syntax error during parsing - too many operands"
0364                                << "\n  Returned empty RPN vector and result false." << std::endl;
0365 
0366     // clear the rpn vector before returning
0367     clearRpnVector();
0368     return false;
0369   }
0370   return true;
0371 }
0372 
0373 // clear rpn vector
0374 void GlobalLogicParser::clearRpnVector() { m_rpnVector.clear(); }
0375 
0376 // build from the RPN vector the operand token vector
0377 // dummy tokenNumber and token result
0378 void GlobalLogicParser::buildOperandTokenVector() {
0379   //LogTrace("L1TGlobal")
0380   //<< "\nGtLogicParser::buildOperandTokenVector - "
0381   //<< std::endl;
0382 
0383   // reserve memory
0384   size_t rpnVectorSize = m_rpnVector.size();
0385   m_operandTokenVector.reserve(rpnVectorSize);
0386 
0387   int opNumber = 0;
0388 
0389   for (RpnVector::const_iterator it = m_rpnVector.begin(); it != m_rpnVector.end(); it++) {
0390     //LogTrace("L1TGlobal")
0391     //<< "\nit->operation = " << it->operation
0392     //<< "\nit->operand =   '" << it->operand << "'\n"
0393     //<< std::endl;
0394 
0395     switch (it->operation) {
0396       case OP_OPERAND: {
0397         OperandToken opToken;
0398         opToken.tokenName = it->operand;
0399         opToken.tokenNumber = opNumber;
0400         opToken.tokenResult = false;
0401 
0402         m_operandTokenVector.push_back(opToken);
0403 
0404       }
0405 
0406       break;
0407       case OP_NOT: {
0408         // do nothing
0409       }
0410 
0411       break;
0412       case OP_OR: {
0413         // do nothing
0414       }
0415 
0416       break;
0417       case OP_AND: {
0418         // do nothing
0419       }
0420       case OP_XOR: {
0421         // do nothing
0422       }
0423 
0424       break;
0425       default: {
0426         // should not arrive here
0427       }
0428 
0429       break;
0430     }
0431 
0432     opNumber++;
0433   }
0434 }
0435 
0436 // return the position index of the operand in the logical expression
0437 int GlobalLogicParser::operandIndex(const std::string& operandNameVal) const {
0438   int result = -1;
0439 
0440   OperationType actualOperation = OP_NULL;
0441   OperationType lastOperation = OP_NULL;
0442 
0443   std::string tokenString;
0444   TokenRPN rpnToken;  // token to be used by getOperation
0445 
0446   // stringstream to separate all tokens
0447   std::istringstream exprStringStream(m_logicalExpression);
0448 
0449   // temporary index for usage in the loop
0450   int tmpIndex = -1;
0451 
0452   while (!exprStringStream.eof()) {
0453     exprStringStream >> tokenString;
0454 
0455     //LogTrace("L1TGlobal")
0456     //<< "Token string = " << tokenString
0457     //<< std::endl;
0458 
0459     actualOperation = getOperation(tokenString, lastOperation, rpnToken);
0460     if (actualOperation == OP_INVALID) {
0461       // it should never be invalid
0462       edm::LogError("L1TGlobal") << "\nLogical expression = '" << m_logicalExpression << "'"
0463                                  << "\n  Invalid operation/operand " << operandNameVal
0464                                  << "\n  Returned index is by default out of range (-1)." << std::endl;
0465 
0466       return result;
0467     }
0468 
0469     if (actualOperation != OP_OPERAND) {
0470       // do nothing
0471 
0472     } else {
0473       tmpIndex++;
0474       if (rpnToken.operand == operandNameVal) {
0475         result = tmpIndex;
0476 
0477         //LogDebug("L1TGlobal")
0478         //<< "\nGtLogicParser::operandIndex - "
0479         //<< "\nLogical expression = '" << m_logicalExpression << "'"
0480         //<< "\nIndex of operand " << operandNameVal << " = " << result
0481         //<< std::endl;
0482 
0483         return result;
0484       }
0485     }
0486     lastOperation = actualOperation;
0487   }
0488 
0489   //
0490   edm::LogError("L1TGlobal") << "\nLogical expression = '" << m_logicalExpression << "'"
0491                              << "\n  Operand " << operandNameVal << " not found in the logical expression"
0492                              << "\n  Returned index is by default out of range (-1)." << std::endl;
0493 
0494   return result;
0495 }
0496 
0497 // return the name of the (iOperand)th operand in the logical expression
0498 std::string GlobalLogicParser::operandName(const int iOperand) const {
0499   std::string result;
0500 
0501   OperationType actualOperation = OP_NULL;
0502   OperationType lastOperation = OP_NULL;
0503 
0504   std::string tokenString;
0505   TokenRPN rpnToken;  // token to be used by getOperation
0506 
0507   // stringstream to separate all tokens
0508   std::istringstream exprStringStream(m_logicalExpression);
0509 
0510   // temporary index for usage in the loop
0511   int tmpIndex = -1;
0512 
0513   while (!exprStringStream.eof()) {
0514     exprStringStream >> tokenString;
0515 
0516     //LogTrace("L1TGlobal")
0517     //<< "Token string = " << tokenString
0518     //<< std::endl;
0519 
0520     actualOperation = getOperation(tokenString, lastOperation, rpnToken);
0521     if (actualOperation == OP_INVALID) {
0522       // it should never be invalid
0523       edm::LogError("L1TGlobal") << "\nLogical expression = '" << m_logicalExpression << "'"
0524                                  << "\n  Invalid operation/operand at position " << iOperand
0525                                  << "\n  Returned empty name by default." << std::endl;
0526 
0527       return result;
0528     }
0529 
0530     if (actualOperation != OP_OPERAND) {
0531       // do nothing
0532 
0533     } else {
0534       tmpIndex++;
0535       if (tmpIndex == iOperand) {
0536         result = rpnToken.operand;
0537 
0538         //LogDebug("L1TGlobal")
0539         //<< "\nGtLogicParser::operandName - "
0540         //<< "\nLogical expression = '" << m_logicalExpression << "'"
0541         //<< "\nOperand with index " << iOperand << " = " << result
0542         //<< std::endl;
0543 
0544         return result;
0545       }
0546     }
0547     lastOperation = actualOperation;
0548   }
0549 
0550   //
0551   edm::LogError("L1TGlobal") << "\nLogical expression = '" << m_logicalExpression << "'"
0552                              << "\n  No operand found at position " << iOperand << "\n  Returned empty name by default."
0553                              << std::endl;
0554 
0555   return result;
0556 }
0557 
0558 // return the result for an operand with name operandNameVal
0559 // in the logical expression using the operand token vector
0560 bool GlobalLogicParser::operandResult(const std::string& operandNameVal) const {
0561   for (size_t i = 0; i < m_operandTokenVector.size(); ++i) {
0562     if ((m_operandTokenVector[i]).tokenName == operandNameVal) {
0563       return (m_operandTokenVector[i]).tokenResult;
0564     }
0565   }
0566 
0567   // return false - should not arrive here
0568   edm::LogError("L1TGlobal") << "\n  Operand " << operandNameVal << " not found in the operand token vector"
0569                              << "\n  Returned false by default." << std::endl;
0570 
0571   return false;
0572 }
0573 
0574 // return the result for an operand with tokenNumberVal
0575 // using the operand token vector
0576 bool GlobalLogicParser::operandResult(const int tokenNumberVal) const {
0577   for (size_t i = 0; i < m_operandTokenVector.size(); ++i) {
0578     if ((m_operandTokenVector[i]).tokenNumber == tokenNumberVal) {
0579       return (m_operandTokenVector[i]).tokenResult;
0580     }
0581   }
0582 
0583   // return false - should not arrive here
0584   edm::LogError("L1TGlobal") << "\n  No operand with token number " << tokenNumberVal
0585                              << " found in the operand token vector"
0586                              << "\n  Returned false by default." << std::endl;
0587 
0588   return false;
0589 }
0590 
0591 // return the result for the logical expression
0592 // require a proper operand token vector
0593 const bool GlobalLogicParser::expressionResult() const {
0594   //LogTrace("L1TGlobal")
0595   //<< "\nGtLogicParser::expressionResult - "
0596   //<< std::endl;
0597 
0598   // return false if there is no RPN vector built
0599   if (m_rpnVector.empty()) {
0600     edm::LogError("L1TGlobal") << "\n  No built RPN vector exists."
0601                                << "\n  Returned false by default." << std::endl;
0602     return false;
0603   }
0604 
0605   // stack containing temporary results
0606   std::stack<bool> resultStack;
0607   bool b1, b2;
0608 
0609   for (RpnVector::const_iterator it = m_rpnVector.begin(); it != m_rpnVector.end(); it++) {
0610     //LogTrace("L1TGlobal")
0611     //<< "\nit->operation = " << it->operation
0612     //<< "\nit->operand =   '" << it->operand << "'\n"
0613     //<< std::endl;
0614 
0615     switch (it->operation) {
0616       case OP_OPERAND: {
0617         resultStack.push(operandResult(it->operand));
0618       }
0619 
0620       break;
0621       case OP_NOT: {
0622         b1 = resultStack.top();
0623         resultStack.pop();      // pop the top
0624         resultStack.push(!b1);  // and push the result
0625       }
0626 
0627       break;
0628       case OP_OR: {
0629         b1 = resultStack.top();
0630         resultStack.pop();
0631         b2 = resultStack.top();
0632         resultStack.pop();
0633         resultStack.push(b1 || b2);
0634       }
0635 
0636       break;
0637       case OP_XOR: {
0638         b1 = resultStack.top();
0639         resultStack.pop();
0640         b2 = resultStack.top();
0641         resultStack.pop();
0642         resultStack.push(b1 ^ b2);
0643       }
0644 
0645       break;
0646       case OP_AND: {
0647         b1 = resultStack.top();
0648         resultStack.pop();
0649         b2 = resultStack.top();
0650         resultStack.pop();
0651         resultStack.push(b1 && b2);
0652       }
0653 
0654       break;
0655       default: {
0656         // should not arrive here
0657       }
0658 
0659       break;
0660     }
0661   }
0662 
0663   // get the result in the top of the stack
0664 
0665   //LogTrace("L1TGlobal")
0666   //<< "\nGtLogicParser::expressionResult - "
0667   //<< "\nResult = " << resultStack.top()
0668   //<< std::endl;
0669 
0670   return resultStack.top();
0671 }
0672 
0673 // return the result for an operand with name operandNameVal
0674 // in the logical expression using a numerical expression
0675 bool GlobalLogicParser::operandResultNumExp(const std::string& operandNameVal) const {
0676   bool result = false;
0677 
0678   // get the position index of the operand in the logical string
0679   const int iOperand = operandIndex(operandNameVal);
0680 
0681   result = operandResult(iOperand);
0682 
0683   return result;
0684 }
0685 
0686 // return the result for an operand with index iOperand
0687 // in the logical expression using a numerical expression
0688 bool GlobalLogicParser::operandResultNumExp(const int iOperand) const {
0689   bool result = false;
0690 
0691   // parse the numerical expression
0692 
0693   OperationType actualOperation = OP_NULL;
0694   OperationType lastOperation = OP_NULL;
0695 
0696   std::string tokenString;
0697   TokenRPN rpnToken;  // token to be used by getOperation
0698 
0699   // stringstream to separate all tokens
0700   std::istringstream exprStringStream(m_numericalExpression);
0701 
0702   // temporary index for usage in the loop
0703   int tmpIndex = -1;
0704 
0705   while (!exprStringStream.eof()) {
0706     exprStringStream >> tokenString;
0707 
0708     //LogTrace("L1TGlobal")
0709     //<< "Token string = " << tokenString
0710     //<< std::endl;
0711 
0712     actualOperation = getOperation(tokenString, lastOperation, rpnToken);
0713     if (actualOperation == OP_INVALID) {
0714       // it should never be invalid
0715       edm::LogError("L1TGlobal") << "\nNumerical expression = '" << m_numericalExpression << "'"
0716                                  << "\n  Invalid operation/operand at position " << iOperand
0717                                  << "\n  Returned false by default." << std::endl;
0718 
0719       result = false;
0720       return result;
0721     }
0722 
0723     if (actualOperation != OP_OPERAND) {
0724       // do nothing
0725 
0726     } else {
0727       tmpIndex++;
0728       if (tmpIndex == iOperand) {
0729         if (rpnToken.operand == "1") {
0730           result = true;
0731         } else {
0732           if (rpnToken.operand == "0") {
0733             result = false;
0734           } else {
0735             // something went wrong - break
0736             //
0737             edm::LogError("L1TGlobal") << "\nNumerical expression = '" << m_numericalExpression << "'"
0738                                        << "\n  Invalid result for operand at position " << iOperand << ": "
0739                                        << rpnToken.operand << "\n  It must be 0 or 1"
0740                                        << "\n  Returned false by default." << std::endl;
0741 
0742             result = false;
0743             return result;
0744           }
0745         }
0746 
0747         //LogDebug("L1TGlobal")
0748         //<< "\nGtLogicParser::operandResult - "
0749         //<< "\nNumerical expression = '" << m_numericalExpression << "'"
0750         //<< "\nResult for operand with index " << iOperand
0751         //<< " = " << result << "'\n"
0752         //<< std::endl;
0753 
0754         return result;
0755       }
0756     }
0757     lastOperation = actualOperation;
0758   }
0759 
0760   //
0761   edm::LogError("L1TGlobal") << "\nNumerical expression = '" << m_numericalExpression << "'"
0762                              << "\n  No operand found at position " << iOperand << "\n  Returned false by default."
0763                              << std::endl;
0764 
0765   return result;
0766 }
0767 
0768 // build from the RPN vector the operand token vector
0769 // using a numerical expression
0770 void GlobalLogicParser::buildOperandTokenVectorNumExp() {
0771   //LogTrace("L1TGlobal")
0772   //<< "\nGtLogicParser::buildOperandTokenVector - "
0773   //<< std::endl;
0774 
0775   // reserve memory
0776   size_t rpnVectorSize = m_rpnVector.size();
0777   m_operandTokenVector.reserve(rpnVectorSize);
0778 
0779   int opNumber = 0;
0780 
0781   for (RpnVector::const_iterator it = m_rpnVector.begin(); it != m_rpnVector.end(); it++) {
0782     //LogTrace("L1TGlobal")
0783     //<< "\nit->operation = " << it->operation
0784     //<< "\nit->operand =   '" << it->operand << "'\n"
0785     //<< std::endl;
0786 
0787     switch (it->operation) {
0788       case OP_OPERAND: {
0789         OperandToken opToken;
0790         opToken.tokenName = it->operand;
0791         opToken.tokenNumber = opNumber;
0792         opToken.tokenResult = operandResultNumExp(it->operand);
0793 
0794         m_operandTokenVector.push_back(opToken);
0795 
0796       }
0797 
0798       break;
0799       case OP_NOT: {
0800         // do nothing
0801       }
0802 
0803       break;
0804       case OP_OR: {
0805         // do nothing
0806       }
0807 
0808       break;
0809       case OP_XOR: {
0810         // do nothing
0811       }
0812 
0813       break;
0814       case OP_AND: {
0815         // do nothing
0816       }
0817 
0818       break;
0819       default: {
0820         // should not arrive here
0821       }
0822 
0823       break;
0824     }
0825 
0826     opNumber++;
0827   }
0828 }
0829 
0830 // return the result for the logical expression
0831 const bool GlobalLogicParser::expressionResultNumExp() const {
0832   //LogTrace("L1TGlobal")
0833   //<< "\nGtLogicParser::expressionResult - "
0834   //<< std::endl;
0835 
0836   // return false if there is no expression
0837   if (m_rpnVector.empty()) {
0838     edm::LogError("L1TGlobal") << "\n  No built RPN vector exists."
0839                                << "\n  Returned false by default." << std::endl;
0840     return false;
0841   }
0842 
0843   // stack containing temporary results
0844   std::stack<bool> resultStack;
0845   bool b1, b2;
0846 
0847   for (RpnVector::const_iterator it = m_rpnVector.begin(); it != m_rpnVector.end(); it++) {
0848     //LogTrace("L1TGlobal")
0849     //<< "\nit->operation = " << it->operation
0850     //<< "\nit->operand =   '" << it->operand << "'\n"
0851     //<< std::endl;
0852 
0853     switch (it->operation) {
0854       case OP_OPERAND: {
0855         resultStack.push(operandResultNumExp(it->operand));
0856       }
0857 
0858       break;
0859       case OP_NOT: {
0860         b1 = resultStack.top();
0861         resultStack.pop();      // pop the top
0862         resultStack.push(!b1);  // and push the result
0863       }
0864 
0865       break;
0866       case OP_OR: {
0867         b1 = resultStack.top();
0868         resultStack.pop();
0869         b2 = resultStack.top();
0870         resultStack.pop();
0871         resultStack.push(b1 || b2);
0872       }
0873 
0874       break;
0875       case OP_XOR: {
0876         b1 = resultStack.top();
0877         resultStack.pop();
0878         b2 = resultStack.top();
0879         resultStack.pop();
0880         resultStack.push(b1 ^ b2);
0881       }
0882 
0883       break;
0884       case OP_AND: {
0885         b1 = resultStack.top();
0886         resultStack.pop();
0887         b2 = resultStack.top();
0888         resultStack.pop();
0889         resultStack.push(b1 && b2);
0890       }
0891 
0892       break;
0893       default: {
0894         // should not arrive here
0895       }
0896 
0897       break;
0898     }
0899   }
0900 
0901   // get the result in the top of the stack
0902 
0903   //LogTrace("L1TGlobal")
0904   //<< "\nGtLogicParser::expressionResult - "
0905   //<< "\nLogical expression   = '" << m_logicalExpression << "'"
0906   //<< "\nNumerical expression = '" << m_numericalExpression << "'"
0907   //<< "\nResult = " << resultStack.top()
0908   //<< std::endl;
0909 
0910   return resultStack.top();
0911 }
0912 
0913 // convert the logical expression composed with names to
0914 // a logical expression composed with int numbers using
0915 // a (string, int)  map
0916 
0917 void GlobalLogicParser::convertNameToIntLogicalExpression(const std::map<std::string, int>& nameToIntMap) {
0918   if (m_logicalExpression.empty()) {
0919     return;
0920   }
0921 
0922   // non-empty logical expression
0923 
0924   OperationType actualOperation = OP_NULL;
0925   OperationType lastOperation = OP_NULL;
0926 
0927   std::string tokenString;
0928   TokenRPN rpnToken;  // token to be used by getOperation
0929 
0930   int intValue = -1;
0931 
0932   // stringstream to separate all tokens
0933   std::istringstream exprStringStream(m_logicalExpression);
0934   std::string convertedLogicalExpression;
0935 
0936   while (!exprStringStream.eof()) {
0937     exprStringStream >> tokenString;
0938 
0939     actualOperation = getOperation(tokenString, lastOperation, rpnToken);
0940     if (actualOperation == OP_INVALID) {
0941       // it should never be invalid
0942       edm::LogError("L1TGlobal") << "\nLogical expression = '" << m_logicalExpression << "'"
0943                                  << "\n  Invalid operation/operand in logical expression."
0944                                  << "\n  Return empty logical expression." << std::endl;
0945 
0946       m_logicalExpression.clear();
0947       return;
0948     }
0949 
0950     if (actualOperation != OP_OPERAND) {
0951       convertedLogicalExpression.append(getRuleFromType(actualOperation)->opString);
0952 
0953     } else {
0954       typedef std::map<std::string, int>::const_iterator CIter;
0955 
0956       CIter it = nameToIntMap.find(rpnToken.operand);
0957       if (it != nameToIntMap.end()) {
0958         intValue = it->second;
0959         std::stringstream intStr;
0960         intStr << intValue;
0961         convertedLogicalExpression.append(intStr.str());
0962 
0963       } else {
0964         // it should never be happen
0965         edm::LogError("L1TGlobal") << "\nLogical expression = '" << m_logicalExpression << "'"
0966                                    << "\n  Could not convert " << rpnToken.operand << " to integer!"
0967                                    << "\n  Return empty logical expression." << std::endl;
0968 
0969         m_logicalExpression.clear();
0970         return;
0971       }
0972     }
0973 
0974     convertedLogicalExpression.append(" ");  // one whitespace after each token
0975     lastOperation = actualOperation;
0976   }
0977 
0978   // remove the last space
0979   //convertedLogicalExpression.erase(convertedLogicalExpression.size() - 1);
0980   boost::trim(convertedLogicalExpression);
0981 
0982   LogDebug("L1TGlobal") << "\nGtLogicParser::convertNameToIntLogicalExpression - "
0983                         << "\nLogical expression (strings) = '" << m_logicalExpression << "'"
0984                         << "\nLogical expression (int)     = '" << convertedLogicalExpression << "'\n"
0985                         << std::endl;
0986 
0987   // replace now the logical expression with strings with
0988   // the converted logical expression
0989 
0990   m_logicalExpression = convertedLogicalExpression;
0991 
0992   return;
0993 }
0994 
0995 // convert a logical expression composed with integer numbers to
0996 // a logical expression composed with names using a map (int, string)
0997 
0998 void GlobalLogicParser::convertIntToNameLogicalExpression(const std::map<int, std::string>& intToNameMap) {
0999   if (m_logicalExpression.empty()) {
1000     return;
1001   }
1002 
1003   // non-empty logical expression
1004 
1005   OperationType actualOperation = OP_NULL;
1006   OperationType lastOperation = OP_NULL;
1007 
1008   std::string tokenString;
1009   TokenRPN rpnToken;  // token to be used by getOperation
1010 
1011   // stringstream to separate all tokens
1012   std::istringstream exprStringStream(m_logicalExpression);
1013   std::string convertedLogicalExpression;
1014 
1015   while (!exprStringStream.eof()) {
1016     exprStringStream >> tokenString;
1017 
1018     actualOperation = getOperation(tokenString, lastOperation, rpnToken);
1019     if (actualOperation == OP_INVALID) {
1020       // it should never be invalid
1021       edm::LogError("L1TGlobal") << "\nLogical expression = '" << m_logicalExpression << "'"
1022                                  << "\n  Invalid operation/operand in logical expression."
1023                                  << "\n  Return empty logical expression." << std::endl;
1024 
1025       m_logicalExpression.clear();
1026       return;
1027     }
1028 
1029     if (actualOperation != OP_OPERAND) {
1030       convertedLogicalExpression.append(getRuleFromType(actualOperation)->opString);
1031 
1032     } else {
1033       typedef std::map<int, std::string>::const_iterator CIter;
1034 
1035       // convert string to int
1036       int indexInt;
1037       std::istringstream iss(rpnToken.operand);
1038       iss >> std::dec >> indexInt;
1039 
1040       CIter it = intToNameMap.find(indexInt);
1041       if (it != intToNameMap.end()) {
1042         convertedLogicalExpression.append(it->second);
1043 
1044       } else {
1045         // it should never be happen
1046         edm::LogError("L1TGlobal") << "\nLogical expression = '" << m_logicalExpression << "'"
1047                                    << "\n  Could not convert " << rpnToken.operand << " to string!"
1048                                    << "\n  Return empty logical expression." << std::endl;
1049 
1050         m_logicalExpression.clear();
1051         return;
1052       }
1053     }
1054 
1055     convertedLogicalExpression.append(" ");  // one whitespace after each token
1056     lastOperation = actualOperation;
1057   }
1058 
1059   // remove the last space
1060   //convertedLogicalExpression.erase(convertedLogicalExpression.size() - 1);
1061   boost::trim(convertedLogicalExpression);
1062 
1063   //LogDebug("L1TGlobal")
1064   //        << "\nGtLogicParser::convertIntToNameLogicalExpression - "
1065   //        << "\nLogical expression (int) =    '" << m_logicalExpression << "'"
1066   //        << "\nLogical expression (string) = '" << convertedLogicalExpression << "'\n"
1067   //        << std::endl;
1068 
1069   // replace now the logical expression with int with
1070   // the converted logical expression
1071 
1072   m_logicalExpression = convertedLogicalExpression;
1073 
1074   return;
1075 }
1076 
1077 // return the list of operand tokens for the logical expression
1078 // which are to be used as seeds
1079 std::vector<GlobalLogicParser::OperandToken> GlobalLogicParser::expressionSeedsOperandList() {
1080   //LogDebug("L1TGlobal")
1081   //<< "\nGtLogicParser::expressionSeedsOperandList - "
1082   //<< "\nLogical expression = '" << m_logicalExpression << "'"
1083   //<< "\nm_rpnVector.size() = " << m_rpnVector.size()
1084   //<< "\nm_operandTokenVector.size() = " << m_operandTokenVector.size()
1085   //<< std::endl;
1086 
1087   // seed list
1088   std::vector<OperandToken> opVector;
1089   opVector.reserve(m_operandTokenVector.size());
1090 
1091   // temporary results
1092   std::stack<OperandToken> tmpStack;
1093   std::vector<OperandToken> tmpVector;
1094   tmpVector.reserve(m_operandTokenVector.size());
1095 
1096   OperandToken b1, b2;
1097 
1098   bool newOperandBlock = true;
1099   bool oneBlockOnly = true;
1100   bool operandOnly = true;
1101 
1102   int iOperand = -1;
1103 
1104   OperandToken dummyToken;
1105   dummyToken.tokenName = "dummy";
1106   dummyToken.tokenNumber = -1;
1107   dummyToken.tokenResult = false;
1108 
1109   for (RpnVector::const_iterator it = m_rpnVector.begin(); it != m_rpnVector.end(); it++) {
1110     //LogTrace("L1TGlobal")
1111     //<< "\nit->operation = " << it->operation
1112     //<< "\nit->operand =   '" << it->operand << "'\n"
1113     //<< std::endl;
1114 
1115     switch (it->operation) {
1116       // RPN always start a block with an operand
1117       case OP_OPERAND: {
1118         // more blocks with operations
1119         // push operands from previous block, if any in the tmpVector
1120         // (reverse order to compensate the stack push/top/pop)
1121         if ((!newOperandBlock)) {
1122           for (std::vector<OperandToken>::reverse_iterator itOp = tmpVector.rbegin(); itOp != tmpVector.rend();
1123                itOp++) {
1124             opVector.push_back(*itOp);
1125 
1126             //LogTrace("L1TGlobal")
1127             //<< "  Push operand " << (*itOp).tokenName
1128             //<<" on the seed operand list"
1129             //<< std::endl;
1130           }
1131 
1132           tmpVector.clear();
1133 
1134           newOperandBlock = true;
1135           oneBlockOnly = false;
1136         }
1137 
1138         iOperand++;
1139 
1140         //LogTrace("L1TGlobal")
1141         //<< "  Push operand " << (m_operandTokenVector.at(iOperand)).tokenName
1142         //<< " on the operand stack"
1143         //<< std::endl;
1144 
1145         tmpStack.push(m_operandTokenVector.at(iOperand));
1146       }
1147 
1148       break;
1149       case OP_NOT: {
1150         newOperandBlock = false;
1151         operandOnly = false;
1152 
1153         b1 = tmpStack.top();
1154         tmpStack.pop();  // pop the top
1155 
1156         tmpStack.push(dummyToken);  // and push dummy result
1157 
1158         //LogTrace("L1TGlobal")
1159         //<< "  Clear tmp operand list"
1160         //<< std::endl;
1161 
1162         tmpVector.clear();
1163 
1164       }
1165 
1166       break;
1167       case OP_OR: {
1168         newOperandBlock = false;
1169         operandOnly = false;
1170 
1171         b1 = tmpStack.top();
1172         tmpStack.pop();
1173         b2 = tmpStack.top();
1174         tmpStack.pop();
1175 
1176         tmpStack.push(dummyToken);  // and push dummy result
1177 
1178         if (b1.tokenNumber >= 0) {
1179           tmpVector.push_back(b1);
1180 
1181           //LogTrace("L1TGlobal")
1182           //<< "  Push operand " << b1.tokenName
1183           //<<" on the tmp list"
1184           //<< std::endl;
1185         }
1186 
1187         if (b2.tokenNumber >= 0) {
1188           tmpVector.push_back(b2);
1189 
1190           //LogTrace("L1TGlobal")
1191           //<< "  Push operand " << b2.tokenName
1192           //<<" on the tmp list"
1193           //<< std::endl;
1194         }
1195 
1196       }
1197 
1198       break;
1199       case OP_XOR: {
1200         newOperandBlock = false;
1201         operandOnly = false;
1202 
1203         b1 = tmpStack.top();
1204         tmpStack.pop();
1205         b2 = tmpStack.top();
1206         tmpStack.pop();
1207 
1208         tmpStack.push(dummyToken);  // and push dummy result
1209 
1210         if (b1.tokenNumber >= 0) {
1211           tmpVector.push_back(b1);
1212 
1213           //LogTrace("L1TGlobal")
1214           //<< "  Push operand " << b1.tokenName
1215           //<<" on the tmp list"
1216           //<< std::endl;
1217         }
1218 
1219         if (b2.tokenNumber >= 0) {
1220           tmpVector.push_back(b2);
1221 
1222           //LogTrace("L1TGlobal")
1223           //<< "  Push operand " << b2.tokenName
1224           //<<" on the tmp list"
1225           //<< std::endl;
1226         }
1227 
1228       }
1229 
1230       break;
1231       case OP_AND: {
1232         newOperandBlock = false;
1233         operandOnly = false;
1234 
1235         b1 = tmpStack.top();
1236         tmpStack.pop();
1237         b2 = tmpStack.top();
1238         tmpStack.pop();
1239 
1240         tmpStack.push(dummyToken);
1241 
1242         if (b1.tokenNumber >= 0) {
1243           tmpVector.push_back(b1);
1244 
1245           //LogTrace("L1TGlobal")
1246           //<< "  Push operand " << b1.tokenName
1247           //<<" on the tmp list"
1248           //<< std::endl;
1249         }
1250 
1251         if (b2.tokenNumber >= 0) {
1252           tmpVector.push_back(b2);
1253 
1254           //LogTrace("L1TGlobal")
1255           //<< "  Push operand " << b2.tokenName
1256           //<<" on the tmp list"
1257           //<< std::endl;
1258         }
1259 
1260       }
1261 
1262       break;
1263       default: {
1264         // should not arrive here
1265       }
1266 
1267       break;
1268     }
1269   }
1270 
1271   // one block only or one operand only
1272   if (oneBlockOnly || operandOnly) {
1273     // one operand only -
1274     // there can be only one operand, otherwise one needs an operation
1275     if (operandOnly) {
1276       b1 = tmpStack.top();
1277       tmpVector.push_back(b1);
1278     }
1279 
1280     //
1281     for (std::vector<OperandToken>::reverse_iterator itOp = tmpVector.rbegin(); itOp != tmpVector.rend(); itOp++) {
1282       opVector.push_back(*itOp);
1283 
1284       //LogTrace("L1TGlobal")
1285       //<< "  One block or one operand only: push operand " << (*itOp).tokenName
1286       //<<" on the seed operand list"
1287       //<< std::endl;
1288     }
1289 
1290   } else {
1291     //LogTrace("L1TGlobal")
1292     //        << "  More blocks:  push the last block on the seed operand list" << std::endl;
1293 
1294     for (std::vector<OperandToken>::reverse_iterator itOp = tmpVector.rbegin(); itOp != tmpVector.rend(); itOp++) {
1295       opVector.push_back(*itOp);
1296 
1297       //LogTrace("L1TGlobal")
1298       //<< "  Push operand:  " << (*itOp).tokenName
1299       //<<" on the seed operand list"
1300       //<< std::endl;
1301     }
1302   }
1303 
1304   // remove duplicates from the seed vector
1305   // slow...
1306   std::vector<OperandToken> opVectorU;
1307   opVectorU.reserve(opVector.size());
1308 
1309   for (std::vector<OperandToken>::const_iterator constIt = opVector.begin(); constIt != opVector.end(); constIt++) {
1310     bool tokenIncluded = false;
1311 
1312     for (std::vector<OperandToken>::iterator itOpU = opVectorU.begin(); itOpU != opVectorU.end(); itOpU++) {
1313       if ((*itOpU).tokenName == (*constIt).tokenName) {
1314         tokenIncluded = true;
1315         break;
1316       }
1317     }
1318 
1319     if (!tokenIncluded) {
1320       opVectorU.push_back(*constIt);
1321     }
1322   }
1323 
1324   return opVectorU;
1325 }
1326 
1327 // private methods
1328 
1329 /**
1330  * getOperation Get the operation from a string and check if it is allowed
1331  *
1332  * @param tokenString   The string to examine.
1333  * @param lastOperation The last operation.
1334  * @param rpnToken      The destination where the token for postfix notation is written to.
1335  *
1336  * @return              The Operation type or OP_INVALID, if the operation is not allowed
1337  *
1338  */
1339 
1340 GlobalLogicParser::OperationType GlobalLogicParser::getOperation(const std::string& tokenString,
1341                                                                  OperationType lastOperation,
1342                                                                  TokenRPN& rpnToken) const {
1343   OperationType actualOperation = OP_OPERAND;  // default value
1344 
1345   int i = 0;
1346 
1347   while (m_operationRules[i].opType != OP_OPERAND) {
1348     if (tokenString == m_operationRules[i].opString) {
1349       actualOperation = (OperationType)m_operationRules[i].opType;
1350       break;
1351     }
1352     i++;
1353   }
1354 
1355   // check if the operation is allowed
1356   if (m_operationRules[i].forbiddenLastOperation & lastOperation) {
1357     return OP_INVALID;
1358   }
1359 
1360   //
1361   if (actualOperation == OP_OPERAND) {
1362     rpnToken.operand = tokenString;
1363 
1364   } else {
1365     rpnToken.operand = "";
1366   }
1367 
1368   rpnToken.operation = actualOperation;
1369 
1370   // else we got a valid operation
1371   return actualOperation;
1372 }
1373 
1374 /**
1375  * getRuleFromType Looks for the entry in the operation rules
1376  *     and returns a reference if it was found
1377  *
1378  * @param oType The type of the operation.
1379  *
1380  * @return The reference to the entry or 0 if the Rule was not found.
1381  *
1382  */
1383 
1384 const GlobalLogicParser::OperationRule* GlobalLogicParser::getRuleFromType(OperationType oType) {
1385   int i = 0;
1386 
1387   while ((m_operationRules[i].opType != oType) && (m_operationRules[i].opType != OP_NULL)) {
1388     i++;
1389   }
1390 
1391   if (m_operationRules[i].opType == OP_NULL) {
1392     return nullptr;
1393   }
1394 
1395   return &(m_operationRules[i]);
1396 }
1397 
1398 // add spaces before and after parentheses - make separation easier
1399 void GlobalLogicParser::addBracketSpaces(const std::string& srcExpression, std::string& dstExpression) {
1400   static const std::string brackets = "()";  // the brackets to be found
1401 
1402   dstExpression = srcExpression;  // copy the string
1403 
1404   size_t position = 0;
1405   while ((position = dstExpression.find_first_of(brackets, position)) != std::string::npos) {
1406     // add space after if none is there
1407     if (((position + 1) != std::string::npos) && (dstExpression[position + 1] != ' ')) {
1408       dstExpression.insert(position + 1, " ");
1409     }
1410 
1411     // add space before if none is there
1412     if ((position != 0) && (dstExpression[position - 1] != ' ')) {
1413       dstExpression.insert(position, " ");
1414       position++;
1415     }
1416     position++;
1417   }
1418 }
1419 
1420 // set the logical expression - check for correctness the input string
1421 bool GlobalLogicParser::setLogicalExpression(const std::string& logicalExpressionVal) {
1422   // add spaces around brackets
1423   std::string logicalExpressionBS;
1424   addBracketSpaces(logicalExpressionVal, logicalExpressionBS);
1425 
1426   // trim leading or trailing spaces
1427   boost::trim(logicalExpressionBS);
1428 
1429   clearRpnVector();
1430 
1431   if (!buildRpnVector(logicalExpressionBS)) {
1432     m_logicalExpression = "";
1433     return false;
1434   }
1435 
1436   m_logicalExpression = logicalExpressionBS;
1437 
1438   //LogDebug("L1TGlobal")
1439   //<< "\nGtLogicParser::setLogicalExpression - "
1440   //<< "\nLogical expression = '" << m_logicalExpression << "'\n"
1441   //<< std::endl;
1442 
1443   return true;
1444 }
1445 
1446 // set the numerical expression (the logical expression with each operand
1447 // replaced with the value) from a string
1448 // check also for correctness the input string
1449 bool GlobalLogicParser::setNumericalExpression(const std::string& numericalExpressionVal) {
1450   // add spaces around brackets
1451   std::string numericalExpressionBS;
1452   addBracketSpaces(numericalExpressionVal, numericalExpressionBS);
1453 
1454   // check for consistency with the logical expression
1455   // TODO FIXME
1456 
1457   // trim leading or trailing spaces
1458   boost::trim(numericalExpressionBS);
1459 
1460   m_numericalExpression = numericalExpressionBS;
1461 
1462   //LogDebug("L1TGlobal")
1463   //<< "\nGtLogicParser::setNumericalExpression - "
1464   //<< "\nNumerical Expression = '" << m_numericalExpression << "'\n"
1465   //<< std::endl;
1466 
1467   return true;
1468 }
1469 
1470 // static members
1471 
1472 // rules for operations
1473 // 1st column: operation string
1474 // 2nd column: operation type
1475 // 3rd column: forbiddenLastOperation (what operation the operator/operand must not follow)
1476 const struct GlobalLogicParser::OperationRule GlobalLogicParser::m_operationRules[] = {
1477     {"AND", OP_AND, OP_AND | OP_OR | OP_XOR | OP_NOT | OP_OPENBRACKET | OP_NULL},
1478     {"OR", OP_OR, OP_AND | OP_OR | OP_XOR | OP_NOT | OP_OPENBRACKET | OP_NULL},
1479     {"XOR", OP_XOR, OP_AND | OP_OR | OP_XOR | OP_NOT | OP_OPENBRACKET | OP_NULL},
1480     {"NOT", OP_NOT, OP_OPERAND | OP_CLOSEBRACKET},
1481     {"(", OP_OPENBRACKET, OP_OPERAND | OP_CLOSEBRACKET},
1482     {")", OP_CLOSEBRACKET, OP_AND | OP_OR | OP_XOR | OP_NOT | OP_OPENBRACKET},
1483     {nullptr, OP_OPERAND, OP_OPERAND | OP_CLOSEBRACKET},
1484     {nullptr, OP_NULL, OP_NULL}};