use super::prelude::*;
use crate::span_wrap::SpanWrap;
pub fn collect<'p, 'r, 't, F>(
log: &slog::Logger,
parser: &'p mut Parser<'r, 't>,
rule: Rule,
close_conditions: &[ParseCondition],
invalid_conditions: &[ParseCondition],
warn_kind: Option<ParseWarningKind>,
mut process: F,
) -> ParseResult<'r, 't, &'r ExtractedToken<'t>>
where
F: FnMut(&slog::Logger, &mut Parser<'r, 't>) -> ParseResult<'r, 't, ()>,
{
let log = {
let ExtractedToken { token, slice, span } = parser.current();
&log.new(slog_o!(
"rule" => str!(rule.name()),
"token" => str!(token.name()),
"slice" => str!(slice),
"span" => SpanWrap::from(span),
"remaining-len" => parser.remaining().len(),
"close-conditions" => format!("{:?}", close_conditions),
"invalid-conditions" => format!("{:?}", invalid_conditions),
))
};
info!(log, "Trying to collect tokens for rule {:?}", rule);
let mut exceptions = Vec::new();
loop {
if parser.evaluate_any(close_conditions) {
debug!(
log,
"Found ending condition, returning collected elements";
"token" => parser.current().token,
);
let last = parser.current();
if parser.current().token != Token::InputEnd {
parser.step()?;
}
return ok!(last, exceptions);
}
if parser.evaluate_any(invalid_conditions) {
debug!(
log,
"Found invalid token, aborting container attempt";
"token" => parser.current().token,
);
return Err(
parser.make_warn(warn_kind.unwrap_or(ParseWarningKind::RuleFailed))
);
}
if parser.current().token == Token::InputEnd {
debug!(log, "Found end of input, aborting");
return Err(parser.make_warn(ParseWarningKind::EndOfInput));
}
let old_remaining = parser.remaining();
process(log, parser)?.chain(&mut exceptions);
if parser.same_pointer(old_remaining) {
parser.step()?;
}
}
}