Actually just three programming languages in a trenchcoat
1use crate::Parser;
2use trilogy_scanner::Token;
3use trilogy_scanner::TokenType::{self, DocInner, DocOuter};
4
5/// A documentation comment, either inner or outer.
6///
7/// ```trilogy
8/// ## Hello this is a doc comment.
9/// ## It may be multiple lines long.
10/// ```
11#[derive(Clone, Debug, Spanned, PrettyPrintSExpr)]
12pub struct Documentation {
13 pub tokens: Vec<Token>,
14}
15
16impl Documentation {
17 fn parse(parser: &mut Parser, token_type: TokenType) -> Option<Self> {
18 let mut tokens = vec![];
19
20 while let Ok(token) = parser.expect(token_type) {
21 tokens.push(token);
22 }
23 if tokens.is_empty() {
24 return None;
25 }
26
27 Some(Self { tokens })
28 }
29
30 pub(crate) fn parse_inner(parser: &mut Parser) -> Option<Self> {
31 Self::parse(parser, DocInner)
32 }
33
34 pub(crate) fn parse_outer(parser: &mut Parser) -> Option<Self> {
35 Self::parse(parser, DocOuter)
36 }
37}
38
39#[cfg(test)]
40mod test {
41 use super::*;
42
43 test_parse!(documentation_inner: "#! hello\n" => Documentation::parse_inner => "(Documentation _)");
44 test_parse!(documentation_inner_multiline: "#! hello\n#! world\n" => Documentation::parse_inner => "(Documentation _)");
45 test_parse!(documentation_inner_gaps: "#! hello\n\n#! world\n" => Documentation::parse_inner => "(Documentation _)");
46
47 test_parse!(documentation_outer: "## hello\n" => Documentation::parse_outer => "(Documentation _)");
48 test_parse!(documentation_outer_multiline: "## hello\n## world\n" => Documentation::parse_outer => "(Documentation _)");
49 test_parse!(documentation_outer_gaps: "## hello\n\n## world\n" => Documentation::parse_outer => "(Documentation _)");
50}