Skip to main content

ratex_parser/functions/
tag.rs

1use std::collections::HashMap;
2
3use crate::error::{ParseError, ParseResult};
4use crate::functions::{define_function_full, FunctionContext, FunctionSpec};
5use crate::parse_node::{Mode, ParseNode};
6
7pub fn register(map: &mut HashMap<&'static str, FunctionSpec>) {
8    define_function_full(
9        map,
10        &["\\tag"],
11        "tag",
12        0,
13        0,
14        None,
15        true,
16        false,
17        true,
18        false,
19        true,
20        handle_tag,
21    );
22}
23
24fn handle_tag(
25    ctx: &mut FunctionContext,
26    _args: Vec<ParseNode>,
27    _opt_args: Vec<Option<ParseNode>>,
28) -> ParseResult<ParseNode> {
29    ctx.parser.consume_spaces()?;
30    let star = if ctx.parser.fetch()?.text == "*" {
31        ctx.parser.consume();
32        true
33    } else {
34        false
35    };
36
37    let arg = ctx
38        .parser
39        .parse_group("\\tag", None)?
40        .ok_or_else(|| ParseError::msg("\\tag requires an argument"))?;
41
42    let inner = match arg {
43        ParseNode::OrdGroup { body, .. } => body,
44        other => vec![other],
45    };
46
47    let tag = if star {
48        inner
49    } else {
50        let mut v = Vec::with_capacity(inner.len() + 2);
51        v.push(ParseNode::MathOrd {
52            mode: Mode::Math,
53            text: "(".to_string(),
54            loc: None,
55        });
56        v.extend(inner);
57        v.push(ParseNode::MathOrd {
58            mode: Mode::Math,
59            text: ")".to_string(),
60            loc: None,
61        });
62        v
63    };
64
65    Ok(ParseNode::Tag {
66        mode: ctx.parser.mode,
67        body: vec![],
68        tag,
69        loc: None,
70    })
71}