Matching N times
I am trying to write a parser using CppCmb that will match N characters. I see that there are operators for matching zero or many (*) and one or many (+). I did not see the equivalent {N} operator that many grep languages afford.
My use case is to actually match up to N characters or the first null '\0' character from an input stream. E.g. if N is 3 and "\0" is the null character escape code, matching strings would be:
| INPUT | NOTES |
|---|---|
| "123" | "123" is captured |
| "ABCD" | "ABC" is captured, "D" remains and may be used for a different match |
| "12\0" | "12" or "12\0" as captures are fine, as long as the "\0" is consumed |
| "\0" | "" or "\0" are acceptable captures, as long as the "\0" is consumed |
Examples of not matching strings would be:
| INPUT | NOTES |
|---|---|
| "12" | where there is no "\0" following the "2" |
| "" | an empty stream with no "\0" |
I tried to see if I could use a template with a non type parameter to recursively apply a match where N is decremented each call, but It didn't seem to work correctly with your cppcmb_decl / def macro system.
Here is a function that will match up to N characters or the first NULL character given a filter predicate and a begin and end iterator. It returns a pair containing a boolean of the match outcome and the iterator pointing to the furthest character in the stream that was parsed.
template <size_t N, typename F, typename I>
constexpr auto parseNor0(F&& filter, I begin, I end) {
if constexpr (N == 0) {
return std::make_pair(false, begin);
}
if (*begin == '\0') {
return std::make_pair(true, begin);
}
if (filter(*begin)) {
if constexpr (N == 1) {
return std::make_pair(true, begin);
}
if constexpr (N > 1) {
if (++begin != end) {
//call recursively
return parseNor0<N-1>(filter, begin, end);
}
}
}
return std::make_pair(false, begin);
}
Do you have any suggestions on how to match N times?