org_rust_parser/element/
footnote_def.rs

1use crate::constants::{NEWLINE, RBRACK, SPACE};
2use crate::node_pool::NodeID;
3use crate::parse::parse_element;
4use crate::types::{Cursor, Expr, ParseOpts, Parseable, Parser, Result};
5
6#[derive(Debug, Clone)]
7pub struct FootnoteDef<'a> {
8    pub label: &'a str,
9    pub children: Vec<NodeID>,
10}
11
12impl<'a> Parseable<'a> for FootnoteDef<'a> {
13    fn parse(
14        parser: &mut Parser<'a>,
15        mut cursor: Cursor<'a>,
16        parent: Option<NodeID>,
17        parse_opts: ParseOpts,
18    ) -> Result<NodeID> {
19        let start = cursor.index;
20
21        cursor.word("[fn:")?;
22        let label_match = cursor.fn_until(|chr| matches!(chr, NEWLINE | RBRACK | SPACE))?;
23        cursor.index = label_match.end;
24        cursor.word("]")?;
25
26        // Handle CONTENTS
27        // used to restore index to the previous position in the event of two
28        // blank lines
29        let mut blank_obj: Option<NodeID> = None;
30        let mut prev_ind = cursor.index;
31        let mut children = Vec::new();
32        let reserve_id = parser.pool.reserve_id();
33
34        while let Ok(element_id) = parse_element(parser, cursor, Some(reserve_id), parse_opts) {
35            let pool_loc = &parser.pool[element_id];
36            match &pool_loc.obj {
37                Expr::BlankLine => {
38                    if blank_obj.is_some() {
39                        cursor.index = prev_ind;
40                        break;
41                    } else {
42                        blank_obj = Some(element_id);
43                        prev_ind = cursor.index;
44                    }
45                }
46                Expr::FootnoteDef(_) => {
47                    break;
48                }
49                Expr::Heading(_) => {
50                    break;
51                }
52                _ => {
53                    if let Some(blank_id) = blank_obj {
54                        children.push(blank_id);
55                        blank_obj = None;
56                    }
57                    children.push(element_id);
58                }
59            }
60            cursor.move_to(pool_loc.end);
61        }
62
63        parser.footnotes.insert(label_match.obj, reserve_id);
64        let ret_id = parser.alloc_with_id(
65            Self {
66                label: label_match.obj,
67                children,
68            },
69            start,
70            cursor.index,
71            parent,
72            reserve_id,
73        );
74        // let a: String = format!("fn.{}", parser.footnotes.len());
75        // parser.pool[ret_id].id_target = Some(a.into());
76        Ok(ret_id)
77    }
78}