1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use crate::{
Parser, Span,
blocks::{Block, block::BlockParseOutcome},
span::MatchedItem,
warnings::{MatchAndWarnings, Warning},
};
/// Parse blocks until end of input or a pre-determined stop condition is
/// reached.
pub(crate) fn parse_blocks_until<'src, F>(
mut source: Span<'src>,
mut f: F,
parser: &mut Parser,
) -> MatchAndWarnings<'src, MatchedItem<'src, Vec<Block<'src>>>>
where
F: FnMut(&Span<'src>) -> bool,
{
let mut blocks: Vec<Block<'src>> = vec![];
let mut warnings: Vec<Warning<'src>> = vec![];
source = source.discard_empty_lines();
while !source.data().is_empty() {
if f(&source) {
break;
}
let mut maw = Block::parse_with_outcome(source, parser);
if !maw.warnings.is_empty() {
warnings.append(&mut maw.warnings);
}
if let BlockParseOutcome::Parsed(mi) = maw.item {
source = mi.after.discard_empty_lines();
blocks.push(mi.item);
} else if let BlockParseOutcome::Dropped(after) = maw.item {
// A dropped block (`attribute-missing=drop-line`) contributes no
// block, but parsing must still advance past its source.
source = after.discard_empty_lines();
}
// `BlockParseOutcome::NoMatch` is intentionally not handled: it only
// arises for empty/blank input, which never reaches here because the
// loop guard and the `discard_empty_lines` calls above keep `source`
// non-blank. (Matching the behavior before drop-line support, which
// likewise only advanced on a successful parse.)
}
MatchAndWarnings {
item: MatchedItem {
item: blocks,
after: source,
},
warnings,
}
}