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

regex with loop in loop incorrecly matches when it shouldn't #392

Closed
lukas-code opened this issue May 24, 2024 · 0 comments · Fixed by #393
Closed

regex with loop in loop incorrecly matches when it shouldn't #392

lukas-code opened this issue May 24, 2024 · 0 comments · Fixed by #393
Labels
bug Something isn't working

Comments

@lukas-code
Copy link
Contributor

Repro

I tried this code:

use logos::Logos;

#[derive(Debug, Logos)]
enum Token {
    #[regex(r"(a*b)*")]
    Foo,
}

fn main() {
    let input = "a";
    for token in Token::lexer(input) {
        println!("{token:?}");
    }
}

The regex (a*b)* should not match the string a, so this program should print Err(()). But Logos incorrectly thinks the regex matches and the program actually prints Ok(Foo).

Analysis

The problem appears to be in the construction of the NFA. For the program above, Logos will currently construct this NFA, which allows a single a to match:

flowchart LR
    s[start]-->2
    2((2))--a-->2((2))
    2((2))--_-->4((4))
    4((4))--b-->2((2))
    4((4))--_-->1((1))
    1((1))-->e[::Foo]
Loading

A possible solution would be to construct an NFA with separate paths for the first and the remaining iterations of the inner loop, such as the following. This way, every a must be eventually followed by a b to match.

flowchart LR
    s[start]-->2
    2((2))--a-->4((4))
    2((2))--_-->5((5))
    4((4))--a-->4((4))
    4((4))--_-->3((3))
    3((3))--b-->2((2))
    5((5))--b-->2((2))
    5((5))--_-->1((1))
    1((1))-->e[::Foo]
Loading

I will submit a PR implementing this approach shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants