chore(varcon): Add parse tracing

This commit is contained in:
Ed Page 2023-07-14 12:32:16 -05:00
parent e98fc52b0d
commit 0bde06af9a

View file

@ -1,4 +1,5 @@
use winnow::prelude::*; use winnow::prelude::*;
use winnow::trace::trace;
use crate::*; use crate::*;
@ -62,37 +63,41 @@ A Cv: acknowledgment's / Av B C: acknowledgement's
impl Cluster { impl Cluster {
pub fn parse(input: &str) -> IResult<&str, Self> { pub fn parse(input: &str) -> IResult<&str, Self> {
let header = ( trace("cluster", move |input| {
"#", let header = (
winnow::ascii::space0, "#",
winnow::ascii::not_line_ending, winnow::ascii::space0,
winnow::ascii::line_ending,
);
let note = winnow::combinator::preceded(
("##", winnow::ascii::space0),
winnow::combinator::terminated(
winnow::ascii::not_line_ending, winnow::ascii::not_line_ending,
winnow::ascii::line_ending, winnow::ascii::line_ending,
), );
); let note = winnow::combinator::preceded(
let mut cluster = ( ("##", winnow::ascii::space0),
winnow::combinator::opt(header), winnow::combinator::terminated(
winnow::combinator::repeat( winnow::ascii::not_line_ending,
1.., winnow::ascii::line_ending,
winnow::combinator::terminated(Entry::parse, winnow::ascii::line_ending), ),
), );
winnow::combinator::repeat(0.., note), let mut cluster = (
); winnow::combinator::opt(header),
let (input, (header, entries, notes)): (_, (_, _, Vec<_>)) = cluster.parse_next(input)?; winnow::combinator::repeat(
1..,
winnow::combinator::terminated(Entry::parse, winnow::ascii::line_ending),
),
winnow::combinator::repeat(0.., note),
);
let (input, (header, entries, notes)): (_, (_, _, Vec<_>)) =
cluster.parse_next(input)?;
let header = header.map(|s| s.2.to_owned()); let header = header.map(|s| s.2.to_owned());
let notes = notes.into_iter().map(|s| s.to_owned()).collect(); let notes = notes.into_iter().map(|s| s.to_owned()).collect();
let c = Self { let c = Self {
header, header,
entries, entries,
notes, notes,
}; };
Ok((input, c)) Ok((input, c))
})
.parse_next(input)
} }
} }
@ -145,64 +150,70 @@ A B C: coloration's / B. Cv: colouration's
impl Entry { impl Entry {
pub fn parse(input: &str) -> IResult<&str, Self> { pub fn parse(input: &str) -> IResult<&str, Self> {
let var_sep = (winnow::ascii::space0, '/', winnow::ascii::space0); trace("entry", move |input| {
let (input, variants) = let var_sep = (winnow::ascii::space0, '/', winnow::ascii::space0);
winnow::combinator::separated1(Variant::parse, var_sep).parse_next(input)?; let (input, variants) =
winnow::combinator::separated1(Variant::parse, var_sep).parse_next(input)?;
let desc_sep = (winnow::ascii::space0, '|'); let desc_sep = (winnow::ascii::space0, '|');
let (input, description) = let (input, description) =
winnow::combinator::opt((desc_sep, Self::parse_description)).parse_next(input)?; winnow::combinator::opt((desc_sep, Self::parse_description)).parse_next(input)?;
let comment_sep = (winnow::ascii::space0, '#'); let comment_sep = (winnow::ascii::space0, '#');
let (input, comment) = winnow::combinator::opt(( let (input, comment) = winnow::combinator::opt((
comment_sep, comment_sep,
winnow::ascii::space1, winnow::ascii::space1,
winnow::ascii::not_line_ending, winnow::ascii::not_line_ending,
)) ))
.parse_next(input)?; .parse_next(input)?;
let mut e = match description { let mut e = match description {
Some((_, description)) => description, Some((_, description)) => description,
None => Self { None => Self {
variants: Vec::new(), variants: Vec::new(),
pos: None, pos: None,
archaic: false, archaic: false,
note: false, note: false,
description: None, description: None,
comment: None, comment: None,
}, },
}; };
e.variants = variants; e.variants = variants;
e.comment = comment.map(|c| c.2.to_owned()); e.comment = comment.map(|c| c.2.to_owned());
Ok((input, e)) Ok((input, e))
})
.parse_next(input)
} }
fn parse_description(input: &str) -> IResult<&str, Self> { fn parse_description(input: &str) -> IResult<&str, Self> {
let (input, (pos, archaic, note, description)) = ( trace("description", move |input| {
winnow::combinator::opt((winnow::ascii::space1, Pos::parse)), let (input, (pos, archaic, note, description)) = (
winnow::combinator::opt((winnow::ascii::space1, "(-)")), winnow::combinator::opt((winnow::ascii::space1, Pos::parse)),
winnow::combinator::opt((winnow::ascii::space1, "--")), winnow::combinator::opt((winnow::ascii::space1, "(-)")),
winnow::combinator::opt(( winnow::combinator::opt((winnow::ascii::space1, "--")),
winnow::ascii::space1, winnow::combinator::opt((
winnow::token::take_till0(('\n', '\r', '#')), winnow::ascii::space1,
)), winnow::token::take_till0(('\n', '\r', '#')),
) )),
.parse_next(input)?; )
.parse_next(input)?;
let variants = Vec::new(); let variants = Vec::new();
let pos = pos.map(|(_, p)| p); let pos = pos.map(|(_, p)| p);
let archaic = archaic.is_some(); let archaic = archaic.is_some();
let note = note.is_some(); let note = note.is_some();
let description = description.map(|(_, d)| d.to_owned()); let description = description.map(|(_, d)| d.to_owned());
let e = Self { let e = Self {
variants, variants,
pos, pos,
archaic, archaic,
note, note,
description, description,
comment: None, comment: None,
}; };
Ok((input, e)) Ok((input, e))
})
.parse_next(input)
} }
} }
@ -298,19 +309,25 @@ mod test_entry {
impl Variant { impl Variant {
pub fn parse(input: &str) -> IResult<&str, Self> { pub fn parse(input: &str) -> IResult<&str, Self> {
let types = winnow::combinator::separated1(Type::parse, winnow::ascii::space1); trace("variant", move |input| {
let sep = (":", winnow::ascii::space0); let types = winnow::combinator::separated1(Type::parse, winnow::ascii::space1);
let (input, (types, word)) = let sep = (":", winnow::ascii::space0);
winnow::combinator::separated_pair(types, sep, word).parse_next(input)?; let (input, (types, word)) =
let v = Self { types, word }; winnow::combinator::separated_pair(types, sep, word).parse_next(input)?;
Ok((input, v)) let v = Self { types, word };
Ok((input, v))
})
.parse_next(input)
} }
} }
fn word(input: &str) -> IResult<&str, String> { fn word(input: &str) -> IResult<&str, String> {
winnow::token::take_till1(|item: char| item.is_ascii_whitespace()) trace("word", move |input| {
.map(|s: &str| s.to_owned().replace('_', " ")) winnow::token::take_till1(|item: char| item.is_ascii_whitespace())
.parse_next(input) .map(|s: &str| s.to_owned().replace('_', " "))
.parse_next(input)
})
.parse_next(input)
} }
#[cfg(test)] #[cfg(test)]
@ -382,12 +399,15 @@ mod test_variant {
impl Type { impl Type {
pub fn parse(input: &str) -> IResult<&str, Type> { pub fn parse(input: &str) -> IResult<&str, Type> {
let (input, category) = Category::parse(input)?; trace("type", move |input| {
let (input, tag) = winnow::combinator::opt(Tag::parse).parse_next(input)?; let (input, category) = Category::parse(input)?;
let (input, num) = winnow::combinator::opt(winnow::ascii::digit1).parse_next(input)?; let (input, tag) = winnow::combinator::opt(Tag::parse).parse_next(input)?;
let num = num.map(|s| s.parse().expect("parser ensured its a number")); let (input, num) = winnow::combinator::opt(winnow::ascii::digit1).parse_next(input)?;
let t = Type { category, tag, num }; let num = num.map(|s| s.parse().expect("parser ensured its a number"));
Ok((input, t)) let t = Type { category, tag, num };
Ok((input, t))
})
.parse_next(input)
} }
} }
@ -439,18 +459,21 @@ mod test_type {
impl Category { impl Category {
pub fn parse(input: &str) -> IResult<&str, Category> { pub fn parse(input: &str) -> IResult<&str, Category> {
let symbols = winnow::token::one_of(['A', 'B', 'Z', 'C', 'D', '_']); trace("category", move |input| {
symbols let symbols = winnow::token::one_of(['A', 'B', 'Z', 'C', 'D', '_']);
.map(|c| match c { symbols
'A' => Category::American, .map(|c| match c {
'B' => Category::BritishIse, 'A' => Category::American,
'Z' => Category::BritishIze, 'B' => Category::BritishIse,
'C' => Category::Canadian, 'Z' => Category::BritishIze,
'D' => Category::Australian, 'C' => Category::Canadian,
'_' => Category::Other, 'D' => Category::Australian,
_ => unreachable!("parser won't select this option"), '_' => Category::Other,
}) _ => unreachable!("parser won't select this option"),
.parse_next(input) })
.parse_next(input)
})
.parse_next(input)
} }
} }
@ -475,17 +498,20 @@ mod test_category {
impl Tag { impl Tag {
pub fn parse(input: &str) -> IResult<&str, Tag> { pub fn parse(input: &str) -> IResult<&str, Tag> {
let symbols = winnow::token::one_of(['.', 'v', 'V', '-', 'x']); trace("tag", move |input| {
symbols let symbols = winnow::token::one_of(['.', 'v', 'V', '-', 'x']);
.map(|c| match c { symbols
'.' => Tag::Eq, .map(|c| match c {
'v' => Tag::Variant, '.' => Tag::Eq,
'V' => Tag::Seldom, 'v' => Tag::Variant,
'-' => Tag::Possible, 'V' => Tag::Seldom,
'x' => Tag::Improper, '-' => Tag::Possible,
_ => unreachable!("parser won't select this option"), 'x' => Tag::Improper,
}) _ => unreachable!("parser won't select this option"),
.parse_next(input) })
.parse_next(input)
})
.parse_next(input)
} }
} }
@ -510,12 +536,15 @@ mod test_tag {
impl Pos { impl Pos {
pub fn parse(input: &str) -> IResult<&str, Pos> { pub fn parse(input: &str) -> IResult<&str, Pos> {
winnow::branch::alt(( trace("pos", move |input| {
"<N>".value(Pos::Noun), winnow::branch::alt((
"<V>".value(Pos::Verb), "<N>".value(Pos::Noun),
"<Adj>".value(Pos::Adjective), "<V>".value(Pos::Verb),
"<Adv>".value(Pos::Adverb), "<Adj>".value(Pos::Adjective),
)) "<Adv>".value(Pos::Adverb),
))
.parse_next(input)
})
.parse_next(input) .parse_next(input)
} }
} }