harper_literate_haskell/
lib.rs

1use harper_comments::CommentParser;
2use harper_core::{
3    Lrc, Masker, Token,
4    parsers::{Markdown, MarkdownOptions, Mask, Parser},
5};
6
7mod masker;
8use harper_core::spell::MutableDictionary;
9use itertools::Itertools;
10use masker::LiterateHaskellMasker;
11
12/// Parses a Literate Haskell document by masking out the code and considering text as Markdown.
13pub struct LiterateHaskellParser {
14    inner: Lrc<dyn Parser>,
15}
16
17impl LiterateHaskellParser {
18    pub fn new(inner: Lrc<dyn Parser>) -> Self {
19        Self { inner }
20    }
21
22    pub fn new_markdown(markdown_options: MarkdownOptions) -> Self {
23        Self {
24            inner: Lrc::new(Markdown::new(markdown_options)),
25        }
26    }
27
28    pub fn create_ident_dict(
29        &self,
30        source: &[char],
31        markdown_options: MarkdownOptions,
32    ) -> Option<MutableDictionary> {
33        let parser = CommentParser::new_from_language_id("haskell", markdown_options).unwrap();
34        let mask = LiterateHaskellMasker::code_only().create_mask(source);
35
36        let code = mask
37            .iter_allowed(source)
38            .flat_map(|(_, src)| src.to_owned())
39            .collect_vec();
40        parser.create_ident_dict(&code)
41    }
42}
43
44impl Parser for LiterateHaskellParser {
45    fn parse(&self, source: &[char]) -> Vec<Token> {
46        Mask::new(LiterateHaskellMasker::text_only(), self.inner.clone()).parse(source)
47    }
48}