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

Repeat expression that doesn't consume input should be a compile time error #210

Closed
hfiguiere opened this issue Oct 18, 2019 · 7 comments
Closed
Labels
diagnostics Improvements to error reporting

Comments

@hfiguiere
Copy link

I found this issue porting from 0.5.0 to 0.6.0.

When I run my parser test, it get stuck in an infinite loop (ie it never terminate).

This is the reduced test case:

extern crate peg;

peg::parser!{grammar p() for str {

pub rule string_literal() -> String
        = "\"" s:$((!['"'])*) "\"" { println!("literal {}", s); s.to_owned() }

}}

fn main() {

    let r = p::string_literal("\"literal\"");

    if let Ok(l) = r {
        println!("Parsed {}", l);
    } else {
        println!("Parse failed {:?}", r);
    }
}

Expected:

  • either it doesn't compile because it's a syntax error (i.e. I'm doing the rule wrong with the update syntax)
  • or it is a parse error

Instead it just get stuck when I cargo run.

@kevinmehall
Copy link
Owner

kevinmehall commented Oct 18, 2019

(!['"'])* matches nothing, repeatedly, as long as the next character is not a quote.

The !X operator is negative lookahead -- it matches without consuming characters if X fails to match, or fails to match if X matches at the current position. It looks like you're trying to use (!['"'])* as "any character besides "", presumably as a replacement for 0.5's [^"]. You actually want (!['"'] [_])* where the [_] consumes the character if it's not a quote.

0.6 adds compile-time checks for other patterns like left recursion that infinite loop in PEG, so repeating an expression that matches without consuming input should similarly be made an error.

@kevinmehall
Copy link
Owner

Also, I meant to find a new syntax for inverted character sets that would be compatible with token trees and the new expansion into match arms, but since the hack with negative lookahead worked, I never came up with a replacement. It is a common enough pattern that it probably deserves its own syntax, though.

For now, I added an example inverted character set to the upgrade steps in the 0.6 release notes that hopefully helps clarify this for others.

@hfiguiere
Copy link
Author

Thanks !

@kevinmehall kevinmehall changed the title Parser stuck in an infinite loop Compile time error for repeat expression that doesn't consume input Oct 18, 2019
@kevinmehall kevinmehall changed the title Compile time error for repeat expression that doesn't consume input Repeat expression that doesn't consume input should be a compile time error Oct 18, 2019
@kw217
Copy link
Contributor

kw217 commented May 9, 2020

Hi - I'm using 0.6.2 and I don't believe this is completely fixed. Here is my code, which leads to an infinite loop:

use peg;

pub fn main() {
    test_parser::top("test").unwrap()
}

peg::parser!{
    grammar test_parser() for str {
        rule _() = " "*
        rule nl() = _* "\n" _*
        pub rule top() = nl()
    }
}

It would be nice if this was spotted by the compiler.

It was quite hard to find this in my (larger) codebase; is there a way to set a maximum recursion depth or parse time or something, to aid debugging?

@kevinmehall
Copy link
Owner

Yeah, this issue is still open. As of 0.6, rust-peg checks for infinite loops by left recursion, but it does not yet check for * infinitely matching zero characters.

Your best bet for debugging issues like this would be the trace feature. Or a backtrace in a debugger like GDB should give you a reasonable stack trace of parse_<rulename> calls.

@kw217
Copy link
Contributor

kw217 commented May 9, 2020

OK, thanks.

@kevinmehall kevinmehall added the diagnostics Improvements to error reporting label Jul 12, 2020
@kw217
Copy link
Contributor

kw217 commented Mar 2, 2021

Great, thanks!

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

No branches or pull requests

3 participants