Skip to content

Commit f6788d4

Browse files
DPL DataDescriptorQueryBuilder: Implementing support for property modifiers
First implemented operation is negation of the subSpecification matcher to realize "all but specification", e.g. EMC/RAW/!0
1 parent afff25e commit f6788d4

File tree

1 file changed

+38
-5
lines changed

1 file changed

+38
-5
lines changed

Framework/Core/src/DataDescriptorQueryBuilder.cxx

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ enum QueryBuilderState {
4141
IN_END_QUERY,
4242
IN_STRING,
4343
IN_NUMBER,
44+
IN_NEGATION,
4445
IN_ERROR,
4546
IN_BEGIN_ATTRIBUTES,
4647
IN_END_ATTRIBUTES,
@@ -82,6 +83,22 @@ std::vector<InputSpec> DataDescriptorQueryBuilder::parse(char const* config)
8283
states.push_back(state);
8384
};
8485

86+
auto checkModifier = [&states, &cur, &next, &error](QueryBuilderState state, const char* mod) {
87+
const char* modifier = nullptr;
88+
if (mod[0] != '\0' && (modifier = strpbrk(cur, mod)) != nullptr) {
89+
switch (*modifier) {
90+
case '!':
91+
states.push_back(IN_NEGATION);
92+
break;
93+
default:
94+
error("invalid modifier '" + std::string(modifier, 1) + "'");
95+
return;
96+
}
97+
next = ++cur;
98+
}
99+
states.push_back(state);
100+
};
101+
85102
auto token = [&states, &expectedSeparators](QueryBuilderState state, char const* sep) {
86103
states.push_back(state);
87104
expectedSeparators = sep;
@@ -143,6 +160,18 @@ std::vector<InputSpec> DataDescriptorQueryBuilder::parse(char const* config)
143160
return InputSpec{binding, std::move(*lastMatcher.release()), lifetime, attributes};
144161
};
145162

163+
auto pushMatcher = [&nodes, &states](auto&& matcher) {
164+
if (states.back() == IN_NEGATION) {
165+
states.pop_back();
166+
auto notMatcher = std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Xor,
167+
std::move(matcher),
168+
data_matcher::ConstantValueMatcher{true});
169+
nodes.push_back(std::move(notMatcher));
170+
} else {
171+
nodes.push_back(std::move(matcher));
172+
}
173+
};
174+
146175
while (states.empty() == false) {
147176
auto const state = states.back();
148177
states.pop_back();
@@ -224,21 +253,22 @@ std::vector<InputSpec> DataDescriptorQueryBuilder::parse(char const* config)
224253
}
225254
} break;
226255
case IN_BEGIN_SUBSPEC: {
227-
pushState(IN_END_SUBSPEC);
256+
checkModifier(IN_END_SUBSPEC, "!");
228257
token(IN_NUMBER, ";%?");
229258
} break;
230259
case IN_END_SUBSPEC: {
231260
if (*next == '%' && assignLastNumericMatch("subspec", currentSubSpec, IN_BEGIN_TIMEMODULO)) {
232-
nodes.push_back(SubSpecificationTypeValueMatcher{*currentSubSpec});
233261
} else if (*next == '?' && assignLastNumericMatch("subspec", currentSubSpec, IN_BEGIN_ATTRIBUTES)) {
234-
nodes.push_back(SubSpecificationTypeValueMatcher{*currentSubSpec});
235262
} else if (*next == ';' && assignLastNumericMatch("subspec", currentSubSpec, IN_END_MATCHER)) {
236-
nodes.push_back(SubSpecificationTypeValueMatcher{*currentSubSpec});
237263
} else if (*next == '\0' && assignLastNumericMatch("subspec", currentSubSpec, IN_END_MATCHER)) {
238-
nodes.push_back(SubSpecificationTypeValueMatcher{*currentSubSpec});
239264
} else {
240265
error("Expected a number");
266+
break;
241267
}
268+
auto backup = states.back();
269+
states.pop_back();
270+
pushMatcher(SubSpecificationTypeValueMatcher{*currentSubSpec});
271+
states.push_back(backup);
242272
} break;
243273
case IN_BEGIN_TIMEMODULO: {
244274
pushState(IN_END_TIMEMODULO);
@@ -306,6 +336,9 @@ std::vector<InputSpec> DataDescriptorQueryBuilder::parse(char const* config)
306336
case IN_END_ATTRIBUTES: {
307337
pushState(IN_END_MATCHER);
308338
} break;
339+
case IN_NEGATION: {
340+
error("property modifiers should have been handled before when inserting previous matcher");
341+
} break;
309342
case IN_ERROR: {
310343
throw std::runtime_error("Parse error: " + errorString);
311344
} break;

0 commit comments

Comments
 (0)