harper_core/parsers/
mask.rs

1use super::Parser;
2use crate::mask::Masker;
3use crate::{Span, Token, TokenKind};
4
5/// Composes a Masker and a Parser to parse only masked chunks of text.
6pub struct Mask<M, P>
7where
8    M: Masker,
9    P: Parser,
10{
11    pub masker: M,
12    pub parser: P,
13}
14
15impl<M, P> Mask<M, P>
16where
17    M: Masker,
18    P: Parser,
19{
20    pub fn new(masker: M, parser: P) -> Self {
21        Self { masker, parser }
22    }
23}
24
25impl<M, P> Parser for Mask<M, P>
26where
27    M: Masker,
28    P: Parser,
29{
30    fn parse(&self, source: &[char]) -> Vec<Token> {
31        let mask = self.masker.create_mask(source);
32
33        let mut tokens: Vec<Token> = Vec::new();
34
35        let mut last_allowed: Option<Span<char>> = None;
36
37        for (span, content) in mask.iter_allowed(source) {
38            // Check for a line break separating the current chunk from the preceding one.
39            if let Some(last_allowed) = last_allowed {
40                let intervening = Span::new(last_allowed.end, span.start);
41
42                if intervening.get_content(source).contains(&'\n') {
43                    tokens.push(Token::new(intervening, TokenKind::ParagraphBreak))
44                }
45            }
46
47            let new_tokens = &mut self.parser.parse(content);
48
49            for token in new_tokens.iter_mut() {
50                token.span.push_by(span.start);
51            }
52
53            tokens.append(new_tokens);
54            last_allowed = Some(span);
55        }
56
57        tokens
58    }
59}