org_rust_parser/element/
footnote_def.rs1use 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 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 Ok(ret_id)
77 }
78}