nom icon indicating copy to clipboard operation
nom copied to clipboard

Compilation time explodes exponentially when chaining `.or()` calls

Open balsoft opened this issue 4 months ago • 1 comments

I have an enum like this:

pub enum ValueType {
    Binary,
    Boolean,
    CalAddress,
    Date,
    DateTime,
    Duration,
    Float,
    Integer,
    Period,
    Recur,
    Text,
    Time,
    Uri,
    UtcOffset,
}

And I'm trying to parse its string representation with nom (actually, I'm trying to write a proc-macro to automatically parse similar enums in a similar way). This is the most obvious solution to me:

fn parse(s: &str) -> IResult<&str, ValueType> {
        tag("BINARY").map(|_| ValueType::Binary)
        .or(tag("BOOLEAN").map(|_| ValueType::Boolean))
        .or(tag("CALADDRESS").map(|_| ValueType::CalAddress))
        .or(tag("DATE").map(|_| ValueType::Date))
        .or(tag("DATETIME").map(|_| ValueType::DateTime))
        .or(tag("DURATION").map(|_| ValueType::Duration))
        .or(tag("FLOAT").map(|_| ValueType::Float))
        .or(tag("INTEGER").map(|_| ValueType::Integer))
        .or(tag("PERIOD").map(|_| ValueType::Period))
        .or(tag("RECUR").map(|_| ValueType::Recur))
        .or(tag("TEXT").map(|_| ValueType::Text))
        .or(tag("TIME").map(|_| ValueType::Time))
        .or(tag("URI").map(|_| ValueType::Uri))
        .or(tag("UTCOFFSET").map(|_| ValueType::UtcOffset))
        .parse(s)
}

This just hangs the compiler, seemingly indefinitely. Reducing the number of variants to 8 makes it compile (but very slowly), and 7 and down compiles fine. It appears to me that something somewhere is exploding the compilation time exponentially.

I understand I am probably using Nom wrong, and would be happy to know the "proper" Nom way of writing this parser; However, I also suggest mentioning somewhere in documentation that chaining parsers with or (and, I suspect, other combinators too) like this is unsupported and will blow up the compilation.

balsoft avatar Aug 30 '25 09:08 balsoft

Ah, I should have just used nom::branch::alt instead of chaining .or; probably still worth documenting.

balsoft avatar Aug 30 '25 09:08 balsoft