ATLAS Offline Software
Loading...
Searching...
No Matches
LogicParser.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <boost/tokenizer.hpp>
8#include <iostream>
9#include <string>
10#include <iterator>
11
12TrigConf::LogicParser::LogicParser()
13{}
14
15namespace {
16 void printSubExpr(const std::string & id, const std::vector<std::string> & tokExpr, size_t & front, const size_t back) {
17 std::cout << id << ": ";
18 for(size_t i = front; i<=back; i++) {
19 std::cout << tokExpr[i] << " ";
20 }
21 std::cout << std::endl;
22 }
23
24 size_t findMatchingClosingParenthesis(const std::vector<std::string> & tokExpr, size_t front, size_t back) {
25 if(tokExpr[front]!="(") {
26 throw TrigConf::LogicParsingException(std::string("Looking for closing parenthesis, but not starting with '(', but '") + tokExpr[front] + "'");
27 }
28 size_t pos(front);
29 size_t parCount = 1;
30 size_t matchingClosingPar = 0;
31 while(++pos <= back) {
32 if(tokExpr[pos]=="(") {
33 parCount++;
34 }
35 if(tokExpr[pos]==")") {
36 parCount--;
37 }
38 if(parCount==0) {
39 matchingClosingPar = pos;
40 break;
41 }
42 }
43 if( matchingClosingPar == 0 ) {
44 printSubExpr("Search for matching parenthesis", tokExpr, front, back);
45 throw TrigConf::LogicParsingException("Found no closing parenthesis, matching '('");
46 }
47 return matchingClosingPar;
48 }
49
50}
51
52std::shared_ptr<TrigConf::Logic>
53TrigConf::LogicParser::parse(const std::string & expr) {
54 std::unique_ptr<TrigConf::Logic> node( nullptr );
55 try {
56 auto exprTok = tokenize(expr);
57 node = buildTree(exprTok);
58 node->setExpression(expr);
59 } catch (LogicParsingException & ex) {
60 std::cerr << "Error in expression " << expr << ":" << ex.msg() << std::endl;
61 throw;
62 return nullptr;
63 }
64 return std::shared_ptr<TrigConf::Logic>(std::move(node));
65}
66
67std::vector<std::string>
68TrigConf::LogicParser::tokenize(const std::string & expr) const {
69 std::vector<std::string> tokens;
70 // build tokens with separators ()&|! and <space>. Keeps all separators except <space> in the list of tokens
71 for ( auto & tok : boost::tokenizer<boost::char_separator<char> > (expr, boost::char_separator<char>(" ", "()&|!")) ) {
72 tokens.emplace_back(tok);
73 }
74 return tokens;
75}
76
77
78
79std::unique_ptr<TrigConf::Logic>
80TrigConf::LogicParser::buildTree(const std::vector<std::string> & tokExpr) const {
81
82 size_t front = 0;
83 size_t back = tokExpr.size()-1;
84 return buildNode(tokExpr,front,back);
85}
86
87
88std::unique_ptr<TrigConf::Logic>
89TrigConf::LogicParser::buildNode(const std::vector<std::string> & tokExpr, size_t front, size_t back) const {
90
91 auto logicLeft = findSubExpr(tokExpr,front, back);
92
93 if(front >= back) {
94 return logicLeft;
95 }
96
97 std::string token = tokExpr[front];
98 if( token!="&" && token != "|" ) {
99 throw LogicParsingException(std::string("Did expect a & or | here, but got a ") + token + ".");
100 }
101 front++;
102
103 // cppcheck-suppress accessMoved; false positive
104 LogicOPS * logic = token=="&" ? static_cast<LogicOPS*>(new LogicAND(std::move(logicLeft))) : static_cast<LogicOPS*>(new LogicOR(std::move(logicLeft)));
105
106 auto logicRight = buildNode(tokExpr, front, back);
107
108 if(logicRight->nodeType() == logic->nodeType()) {
109 auto subLogics = static_cast<LogicOPS*>(logicRight.get())->takeSubLogics();
110 for(auto && sublogic : std::move(subLogics)) {
111 logic->addSubLogic(std::move(sublogic));
112 }
113 } else {
114 logic->addSubLogic(std::move(logicRight));
115 }
116
117 return std::unique_ptr<TrigConf::Logic>( logic );
118}
119
120
121
127std::unique_ptr<TrigConf::Logic>
128TrigConf::LogicParser::findSubExpr(const std::vector<std::string> & tokExpr, size_t & front, const size_t back) const {
129
130 std::string token = tokExpr[front];
131
132 auto logic = std::unique_ptr<TrigConf::Logic>( nullptr );
133
134 if(token=="!") {
135 front++; // to eat the '!'
136 token = tokExpr[front];
137 if(token == "(") {
138 logic = findSubExpr(tokExpr,front, back);
139 } else {
140 front++; // eat this token
141 logic = std::unique_ptr<TrigConf::Logic>(new LogicLeaf(token));
142 }
143 logic->setNegate();
144 } else if(token=="(") {
145 size_t parEnd = findMatchingClosingParenthesis(tokExpr, front, back);
146 logic = buildNode(tokExpr,front+1,parEnd-1);
147 front = parEnd + 1;
148 } else {
149 logic = std::unique_ptr<TrigConf::Logic>(new LogicLeaf(token));
150 ++front;
151 }
152 return logic;
153}
154
Definition node.h:24
std::vector< std::string > tokenize(const std::string &the_str, std::string_view delimiters)
Splits the string into smaller substrings.
STL namespace.