-
|
For the following example: dec ::= '@' digit+
hex ::= '#' ( '0' .. '9' | 'a' .. 'f' )+
number ::= dec | hex
ident ::= '@' ( 'a' .. 'z' )+
item ::= number | ident
code ::= item ( ' ' item )* | <EOF>#[cfg(test)]
mod test {
use winnow::{
ModalResult,
ascii::{alpha1, digit1, hex_digit1},
combinator::{alt, cut_err, fail, preceded, separated},
error::{StrContext, StrContextValue},
prelude::*,
};
#[test]
fn test_alt_cut_err() {
#[derive(Debug)]
enum Number {
At(usize),
Hash(usize),
}
#[derive(Debug)]
struct Ident<'s>(&'s str);
#[derive(Debug)]
enum Item<'s> {
Number(Number),
Ident(Ident<'s>),
}
fn dec_num(input: &mut &str) -> ModalResult<usize> {
digit1
.verify_map(|x: &str| x.parse::<usize>().ok())
.parse_next(input)
}
fn hex_num(input: &mut &str) -> ModalResult<usize> {
hex_digit1
.verify_map(|x: &str| usize::from_str_radix(x, 16).ok())
.parse_next(input)
}
fn number(input: &mut &str) -> ModalResult<Number> {
alt((
preceded(
'@',
cut_err(dec_num).context(StrContext::Expected(StrContextValue::Description(
"Dec number",
))),
)
.map(Number::At),
preceded(
'#',
cut_err(hex_num).context(StrContext::Expected(StrContextValue::Description(
"Hex number",
))),
)
.map(Number::Hash),
))
.parse_next(input)
}
fn ident<'s>(input: &mut &'s str) -> ModalResult<Ident<'s>> {
preceded(
'@',
alpha1.context(StrContext::Expected(StrContextValue::Description("Ident"))),
)
.map(Ident)
.parse_next(input)
}
fn parser<'s>(input: &mut &'s str) -> ModalResult<Vec<Item<'s>>> {
separated(
0..,
alt((
number.map(Item::Number),
ident.map(Item::Ident),
cut_err(fail).context(StrContext::Label("Unknown item")),
)),
' ',
)
.parse_next(input)
}
let content: &str = "@1 #f @ident";
let items = parser.parse(content).unwrap();
println!("{:?}", items);
}
}Result: In this example, the grammar specifies that both number and ident can be prefixed with The Although in this simple case we could restructure the code to handle number and ident together, in more complex grammars such restructuring might significantly diverge the code structure from the actual grammar, harming maintainability. Could we design a version of |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
|
You can use However, where possible, the best route is to restructure. I recommend limiting |
Beta Was this translation helpful? Give feedback.
You can use
backtrack_errinnumberaroundaltto workaround it in this particular case.However, where possible, the best route is to restructure. I recommend limiting
cut_errto truly final errors. Personally, I'd also swap indispatch!in place ofalt.