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

Stop parsing on pattern match #179

Closed
jocutajar opened this issue Oct 22, 2017 · 3 comments
Closed

Stop parsing on pattern match #179

jocutajar opened this issue Oct 22, 2017 · 3 comments
Labels
feature Something not supported that perhaps should be

Comments

@jocutajar
Copy link

Hi, I'd like to stop parsing the string input when a given pattern is matched. I'll give example for SMTP:

helo abc
mail from:<[email protected]>
rcpt to:<[email protected]>
data
$%!...?^ö

The desire is that I could parse all the commands until including the data command. There is no point parsing further as there may be binary data there.

You could add a #quit instruction to terminate further processing:

pub cmd_data -> SmtpCommand
= "data"i NL #quit
{ SmtpCommand::Data }

FYI: the full SMTP grammar on github. Btw, thanks a lot for PEG.

@kevinmehall
Copy link
Owner

Right now the generated wrapper function checks that the match reaches the end of input, and reports a expected EOF if it does not. This ensures that a top-level rule like statement* does not ignore statements that fail to match at the end of file. In your case, the "data" serves the same role. So we just need to add an optional attribute that disables that check.

@kevinmehall kevinmehall added the feature Something not supported that perhaps should be label Feb 4, 2018
@kevinmehall
Copy link
Owner

#[no_eof] was added in 0.7 - #233

@Mingun
Copy link

Mingun commented Jun 2, 2024

For someone who looking for concrete solution:

peg::parser! {
  pub grammar stream() for str {
    pub rule event() -> T = ...;

    pub rule event_list() -> Vec<T> = event()*;

    #[no_eof] // Do not check for EOF after parsing rule
    pub rule event_iter() -> (T, usize)
      // Return position after parsing
      = r:event() p:position!() { (r, p) };
  }
}

let mut content = "...";
while !content.is_empty() {
  let (event, pos) = stream::event_iter(content)?;
  content = &content[pos..];
  // process event...
}

We add a new *_iter rule which calls our target rule and returns result together with the position after parsing, so we know where to start parsing of the next piece. It is equivalent to event_list() rule except that we get events one-by-one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Something not supported that perhaps should be
Projects
None yet
Development

No branches or pull requests

3 participants