cdoc_parser/ast/
visitor.rs

1use crate::ast::{Block, CodeBlock, Command, Inline, Math, Style};
2
3use anyhow::Result;
4use cowstr::CowStr;
5
6/// Implements the visitor pattern for the cdoc Ast type. Blanket implementations are provided so
7/// implementors only have to implement the methods they need to modify.
8pub trait AstVisitor {
9    fn walk_ast(&mut self, ast: &mut Vec<Block>) -> Result<()> {
10        self.visit_vec_block(ast)
11    }
12
13    fn walk_vec_block(&mut self, blocks: &mut Vec<Block>) -> Result<()> {
14        blocks.iter_mut().try_for_each(|b| self.visit_block(b))
15    }
16
17    fn walk_block(&mut self, block: &mut Block) -> Result<()> {
18        match *block {
19            Block::Heading { .. } => Ok(()),
20            Block::Plain(ref mut i) => self.visit_vec_inline(i),
21            Block::Paragraph(ref mut is) | Block::BlockQuote(ref mut is) => {
22                self.visit_vec_inline(is)
23            }
24            Block::List(_, ref mut blocks) => self.visit_vec_block(blocks),
25            Block::ListItem(ref mut blocks) => self.visit_vec_block(blocks),
26        }
27    }
28
29    fn walk_vec_inline(&mut self, inlines: &mut Vec<Inline>) -> Result<()> {
30        inlines.iter_mut().try_for_each(|i| self.visit_inline(i))
31    }
32
33    fn walk_inline(&mut self, inline: &mut Inline) -> Result<()> {
34        match inline {
35            Inline::Text(_) => Ok(()),
36            Inline::Styled(ref mut is, ref mut style) => self.visit_styled(is, style),
37            Inline::Code(s) => self.visit_code(s),
38            Inline::SoftBreak => Ok(()),
39            Inline::HardBreak => Ok(()),
40            Inline::Rule => Ok(()),
41            Inline::Image(_tp, _url, _alt, _inner) => Ok(()),
42            Inline::Link(_tp, _url, _alt, _inner) => Ok(()),
43            Inline::Html(h) => self.visit_html_inline(h),
44            Inline::Math(math) => self.visit_math(math),
45            Inline::Command(cmd) => self.visit_command(cmd),
46            Inline::CodeBlock(block) => self.visit_code_block(block),
47        }
48    }
49
50    fn visit_html_inline(&mut self, _input: &str) -> Result<()> {
51        Ok(())
52    }
53
54    fn visit_vec_block(&mut self, blocks: &mut Vec<Block>) -> Result<()> {
55        self.walk_vec_block(blocks)
56    }
57    fn visit_block(&mut self, block: &mut Block) -> Result<()> {
58        self.walk_block(block)
59    }
60    fn visit_vec_inline(&mut self, inlines: &mut Vec<Inline>) -> Result<()> {
61        self.walk_vec_inline(inlines)
62    }
63    fn visit_inline(&mut self, inline: &mut Inline) -> Result<()> {
64        self.walk_inline(inline)
65    }
66
67    fn visit_styled(&mut self, inlines: &mut Vec<Inline>, _style: &mut Style) -> Result<()> {
68        self.walk_vec_inline(inlines)
69    }
70    #[allow(clippy::too_many_arguments)]
71    fn visit_code_block(&mut self, _block: &mut CodeBlock) -> Result<()> {
72        Ok(())
73    }
74
75    fn visit_code(&mut self, _source: &mut CowStr) -> Result<()> {
76        Ok(())
77    }
78
79    fn visit_math(&mut self, _math: &mut Math) -> Result<()> {
80        Ok(())
81    }
82    fn visit_math_inline(&mut self, _source: &mut CowStr) -> Result<()> {
83        Ok(())
84    }
85
86    fn walk_command(&mut self, body: &mut Option<Vec<Block>>) -> Result<()> {
87        if let Some(body) = body {
88            self.walk_vec_block(body)?;
89        }
90        Ok(())
91    }
92
93    fn visit_command(&mut self, cmd: &mut Command) -> Result<()> {
94        self.walk_command(&mut cmd.body)
95    }
96}