1
//! Whitespace skipping and the `; @annotation` reader-comment
2
//! collector. The annotation handler is the only place that pulls
3
//! `parse_expr` back in from the surrounding module — annotations
4
//! evaluate their RHS as an expression so the sample harness can
5
//! attach metadata like `; @test (= (count 'defun) 5)`.
6

            
7
use winnow::ascii::{line_ending, space0, till_line_ending};
8
use winnow::combinator::opt;
9
use winnow::error::ModalResult;
10
use winnow::prelude::*;
11
use winnow::token::take_while;
12

            
13
use crate::ast::{Annotation, Expr};
14

            
15
9384417
pub(super) fn skip_ws_and_comments(
16
9384417
    input: &mut &str,
17
9384417
    annotations: &mut Vec<Annotation>,
18
9384417
) -> ModalResult<()> {
19
    loop {
20
12015311
        let _ = space0.parse_next(input)?;
21
12015311
        if input.starts_with("; @") {
22
11577
            let _ = "; @".parse_next(input)?;
23
57888
            let name: &str = take_while(1.., |c: char| c.is_alphanumeric() || c == '-' || c == '_')
24
11577
                .parse_next(input)?;
25
11577
            let _ = space0.parse_next(input)?;
26

            
27
11577
            let value = super::parse_expr(input).unwrap_or(Expr::Nil);
28
11577
            annotations.push(Annotation {
29
11577
                name: name.to_string(),
30
11577
                value,
31
11577
            });
32
11577
            let _ = till_line_ending.parse_next(input)?;
33
11577
            let _ = opt(line_ending).parse_next(input)?;
34
12003734
        } else if input.starts_with(';') {
35
1264071
            let _ = till_line_ending.parse_next(input)?;
36
1264071
            let _ = opt(line_ending).parse_next(input)?;
37
10739663
        } else if input.starts_with('\n') || input.starts_with('\r') {
38
1355246
            let _ = line_ending.parse_next(input)?;
39
        } else {
40
9384417
            break;
41
        }
42
    }
43
9384417
    Ok(())
44
9384417
}
45

            
46
8390548
pub(super) fn skip_ws_and_comments_no_annotations(input: &mut &str) -> ModalResult<()> {
47
8390548
    let mut dummy = Vec::new();
48
8390548
    skip_ws_and_comments(input, &mut dummy)
49
8390548
}