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

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

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