I am using nom to parse hour/minute/second time formats such as 16:45:38
. I want to be able to parse various different formats, for example: 16
should be recognized as 16:00:00
, 16:45
as 16:45:00
and I also want to support 16 45 38
to be recognized.
This is the nom parser I use to achieve this:
named!(parse(&'a str) -> Self,
map!(
tuple!(
Units::parse,
opt!(
complete!(
alt!(
tuple!(
preceded!(
tag!(":"),
Units::parse
),
opt!(
complete!(
preceded!(
tag!(":"),
Units::parse
)
)
)
) // tuple!
|
tuple!(
preceded!(
space1,
Units::parse
),
opt!(
complete!(
preceded!(
space1,
Units::parse
)
)
)
) // tuple!
) // alt!
) // complete!
) // opt!
), // tuple!
|(h, tail)| {
let (m, s) =
tail
.map(|(minutes, osec)| (minutes, osec.unwrap_or(0)))
.unwrap_or((0, 0));
NaiveTime::from_hms(h as u32, m as u32, s as u32)
}) // map!
);
However I have a lot of code duplication because I have to alternate between the space1
and tag!(":")
parsers, but can't just alternate at each separator, because that would cause 16:45 38
or 16 45:38
to be accepted aswell, which I don't want.
I need something like a variable for a parser that I can set once, or a function that takes a parser as an argument. How would you solve this with nom?