ATLAS Offline Software
Loading...
Searching...
No Matches
LogicExpression.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "./LogicExpression.h"
6#include <cstdlib>
7#include <string>
8#include <iostream>
9#include <sstream>
10#include <stdio.h>
11
12using namespace TrigConf;
13
16 m_Element(""),
17 m_ostream(o)
18{}
19
20
21LogicExpression::LogicExpression(const std::string& name, std::ostream & o)
24 m_ostream(o)
25{}
26
27
28bool
30 std::string valid_sym = "_";
31 if (isalpha(c) || isdigit(c) || valid_sym.find(c)!=std::string::npos) {
32 return true;
33 } else {
34 return false;
35 }
36}
37
38
39std::string
40LogicExpression::extractElementName(const std::string& expr) {
41 std::string name="";
42 for (unsigned int i=0; i<expr.size(); ++i) {
43 if (isValidElementChar(expr[i])) name += expr[i];
44 else break;
45 }
46 return name;
47}
48
49
50int
51LogicExpression::parse(const std::string& expr, bool enclosed) {
52 unsigned int i=0;
53 char c;
54 bool no_problem=true;
55 char prev = ' ';
56 int n;
57
58 m_LogicRep = expr;
59 while (no_problem && i < expr.size()) {
60 c = expr[i];
61
62 switch (c) {
63 case kOPEN:
64 {
66 if ( (n = sub.parse(expr.substr(i+1), true)) > 0) {
67 addSubLogic(sub);
68 prev = kELEMENT;
69 i += n;
70 } else {
71 no_problem = false;
72 }
73 }
74 break;
75 case kCLOSE:
76 if ( ( (m_State == kAND || m_State == kOR) && subLogics().size()>=2) ||
77 (m_State == kNOT && subLogics().size()==1) ||
78 (m_State == kELEMENT && subLogics().size()<=1 && m_Element=="")) {
79 prev = kELEMENT;
81 return i + 1;
82 } else {
83 std::ostringstream formatedoutput;
84 formatedoutput << "Invalid logic: State=" << m_State << " Nsublogics=" << subLogics().size() << " Element=" << m_Element;
85 printError(formatedoutput.str(), i);
86 no_problem = false;
87 }
88 break;
89 case kAND: case kOR:
90 if (prev == kELEMENT &&
91 ( (subLogics().size() >= 2 && m_State==c) ||
92 (subLogics().size()==1 && m_State==kELEMENT))
93 ) {
94 m_State = c;
95 prev = c;
96 } else {
97 std::ostringstream formatedoutput;
98 formatedoutput << kAND << " or " << kOR << " must come after a logic element";
99 printError(formatedoutput.str(), i);
100 no_problem = false;
101 }
102 break;
103 case kNOT:
104 if (kELEMENT != prev) {
106 sub.setState(kNOT);
107 if ( (i+1)<expr.size() && isValidElementChar(expr[i+1])) {
108 std::string name = extractElementName(expr.substr(i+1));
110 i += name.size();
111 addSubLogic(sub);
112 } else if ( (i+1)<expr.size() && expr[i+1]==kOPEN) {
114 if ( (n = sub2.parse(expr.substr(i+2), true)) > 0) {
115 sub.addSubLogic(sub2);
116 i += (n+1);
117 addSubLogic(sub);
118 } else {
119 no_problem = false;
120 }
121 } else {
122 printError("Was expecting a sub-logic after !", i);
123 no_problem = false;
124 }
125 } else {
126 printError("! must not come directly after a logic element", i);
127 no_problem = false;
128 }
129 prev = kELEMENT;
130 break;
131 default:
132 // Start of a candidate of an element string.
133 if (subLogics().size()==0 ||
134 (subLogics().size()>0 && m_State != kELEMENT)) {
135 std::string name = extractElementName(expr.substr(i));
136 if (name.size() > 0) {
138 i += name.size()-1;
139 } else {
140 printError("Unrecognized string", i);
141 no_problem = false;
142 }
143 prev = kELEMENT;
144 } else {
145 printError("A logic element may not come immediately after another logic element", i);
146 no_problem = false;
147 }
148 break;
149 }
150 i ++;
151
152 }
153 if (!no_problem) {
154 return -1;
155 }
156
157 if (enclosed) {
158 // The logic expression started with a '(' but didn't find ')' and
159 // reached the end of the string.
160 printError("The expression started with a '(' but ')' not found.", i);
161 return 0;
162 }
164
165 return i;
166}
167
168void
170 if (m_State == kELEMENT && subLogics().size() == 1 && m_Element=="") {
171 m_State = kOPEN;
172 }
173}
174
175std::string
177 std::string s="";
178 if (m_State == kELEMENT) {
179 s = m_Element;
180 } else if (m_State == kAND || m_State == kOR) {
181 LogicV_t::const_iterator p;
182 s = kOPEN;
183 for (p=subLogics().begin(); p!=subLogics().end(); ++p) {
184 s += (*p)->logicRep();
185 s += m_State;
186 }
187 if (s.size() > 1) s[s.size()-1] = kCLOSE;
188 else s += kCLOSE;
189 } else if (m_State == kNOT) {
190 s = kNOT;
191 s += kOPEN;
192 if (subLogics().size() == 1) s += subLogics()[0]->logicRep();
193 s += kCLOSE;
194 } else if (m_State == kOPEN) {
195 s += kOPEN;
196 if (subLogics().size() == 1) s += subLogics()[0]->logicRep();
197 s += kCLOSE;
198 }
199 return s;
200}
201
202
203void
205 LogicV_t::const_iterator p;
206 for (p=subLogics().begin(); p!=subLogics().end(); ++p) {
207 (*p)->normalize();
208 }
209 if (isPlaceHolder()) {
210 char s = subLogics()[0]->state();
211 std::string e = subLogics()[0]->element();
212 LogicV_t sublogics = subLogics()[0]->subLogics();
213 clear();
214 setState(s);
215 setElement(e);
216 for (p=sublogics.begin(); p!=sublogics.end(); ++p) {
217 addSubLogic(**p);
218 }
219 }
220}
221
222
223int
225 int n = 0;
226 LogicV_t::const_iterator p;
227
228 switch (m_State) {
229 case kELEMENT:
230 n = 1;
231 break;
232 case kAND: case kOR: case kNOT: case kOPEN:
233 for (p=subLogics().begin(); p!=subLogics().end(); ++p) {
234 n += (*p)->totalNumberOfElements();
235 }
236 break;
237 default:
238 n = 0;
239 break;
240 }
241 return n;
242}
243
244
245void
246LogicExpression::printError(const std::string& message, int i) {
247 std::string m="Error while parsing : ";
248 std::string s="";
249 int n = m.size();
250 for (int j=0; j<(n+i); ++j) s += " ";
251 s += "^";
252 m_ostream << m << m_LogicRep << " at " << i << "-th character" << std::endl;
253 m_ostream << s << std::endl;
254 m_ostream << message << std::endl;
255}
256
257
258void
260 char aaa[100];
261 sprintf(aaa, "Current state: State=%c Nsublogics=%d Element=%s",
262 m_State, (int)subLogics().size(), m_Element.c_str());
263 m_ostream << aaa << std::endl;
264}
265
266
267void
268LogicExpression::print(const std::string& indent) {
269 std::string s=indent;
270 if (m_State == kELEMENT) {
271 m_ostream << indent << m_Element << std::endl;
272 } else if (m_State == kAND || m_State == kOR) {
273 if (m_State==kAND) m_ostream << indent << "AND" << std::endl;
274 if (m_State==kOR) m_ostream << indent << "OR" << std::endl;
275 LogicV_t::const_iterator p;
276 for (p=subLogics().begin(); p!=subLogics().end(); ++p) {
277 (*p)->print(indent + " ");
278 }
279 } else if (m_State == kNOT) {
280 m_ostream << indent << "NOT" << std::endl;
281 if (subLogics().size() == 1) {
282 subLogic(0)->print(indent + " ");
283 }
284 } else if (m_State == kOPEN) {
285 if (subLogics().size() == 1) subLogic(0)->print(indent);
286 } else {
287 m_ostream << indent << "ERROR" << std::endl;
288 }
289}
290
291
292void
295 m_SubLogics.clear();
296 m_Element = "";
297}
298
void printError()
LogicExpression(std::ostream &o=std::cout)
constructor
std::ostream & m_ostream
output stream for all messages
static const char kAND
AND of sub-logics.
static const char kOPEN
empty logic but may have sub-logics.
virtual std::string logicRep() const
static const char kNOT
NOT of a sub-logic. (only one sub-logic)
void addSubLogic(const LogicExpression &sub)
static const char kCLOSE
')' is a valid symbol, but not allowed as a state.
static const char kELEMENT
simple element.
static bool isValidElementChar(char c)
void printError(const std::string &message, int i)
const LogicV_t & subLogics() const
void setElement(const std::string &e)
static const char kOR
OR of sub-logics.
const std::shared_ptr< LogicExpression > subLogic(int i) const
static std::string extractElementName(const std::string &expr)
void print(const std::string &indent="")
virtual int parse(const std::string &expr, bool enclosed=false)
Forward iterator to traverse the main components of the trigger configuration.
Definition Config.h:22
std::vector< std::shared_ptr< LogicExpression > > LogicV_t