Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Matching N times #8

Open
gotnone opened this issue Jan 30, 2020 · 0 comments
Open

Matching N times #8

gotnone opened this issue Jan 30, 2020 · 0 comments

Comments

@gotnone
Copy link

gotnone commented Jan 30, 2020

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant