J-F-Liu / pom

PEG parser combinators using operator overloading without macros.
MIT License
496 stars 30 forks source link

Feature request: Support .clone() #55

Open mcclure opened 1 year ago

mcclure commented 1 year ago

Here is a simple sample program that uses Pom to decode a list of ranges, like "30-42,10-40".

To parse an integer it adapts number() from the sample code:

fn positive<'a>() -> Parser<'a, char, i64> {
    let integer = one_of("123456789") - one_of("0123456789").repeat(0..) | sym('0');
    integer.collect().convert(|s|String::from_iter(s.iter()).parse::<i64>())
}

Then it uses this like

fn range<'a>() -> Parser<'a, char, (i64, i64)>
    { positive() - sym('-') + positive() }

Notice it must call pinteger() twice. This is to make the borrow checker happy, but it also makes sense because (I expect?) each positive() will need internal state.

What if instead the Parser objects supported .clone() and/or Copy? Then it would not need to execute the code in positive() every time, and also the "fn"s and their <'a> boilerplate would be unnecessary. For example the code could just say:

let integerPattern = one_of("123456789") - one_of("0123456789").repeat(0..) | sym('0'); let positive = integerPattern.collect().convert(|s|String::from_iter(s.iter()).parse::()) let range = positive.clone() - sym('-') + positive.clone()

This is a lot less typing because the signatures are not needed.

J-F-Liu commented 1 year ago

The parser contains a box of dyn Fn trait, and Fn is not clonable.