use winnow::{
ascii::space0,
combinator::{alt, empty, eof, fail, opt, peek, preceded},
dispatch,
stream::Stream as _,
token::{any, one_of, take_while},
ModalResult, Parser,
};
pub(crate) fn parse_comment(input: &mut &str) -> ModalResult<()> {
preceded(
'#',
take_while(
0..,
|c| !matches!(c, '\0'..='\u{08}' | '\u{0a}'..='\u{1f}' | '\u{7f}'),
),
)
.void()
.parse_next(input)
}
pub(crate) fn parse_comment_newline(input: &mut &str) -> ModalResult<()> {
(parse_comment, alt((newline, eof.void())))
.void()
.parse_next(input)
}
pub(crate) fn parse_whitespace_n_comments(input: &mut &str) -> ModalResult<()> {
let mut start = input.checkpoint();
loop {
let _ = space0.parse_next(input)?;
let next_token = opt(peek(any)).parse_next(input)?;
match next_token {
Some('#') => (parse_comment, newline).void().parse_next(input)?,
Some('\n') => (newline).void().parse_next(input)?,
Some('\r') => (newline).void().parse_next(input)?,
_ => break,
}
let end = input.checkpoint();
if start == end {
break;
}
start = end;
}
Ok(())
}
pub(crate) fn newline(input: &mut &str) -> ModalResult<()> {
dispatch! {any;
'\n' => empty,
'\r' => one_of('\n').void(),
_ => fail,
}
.parse_next(input)
}