Skip to main content

ratex_parser/functions/
delimsizing.rs

1use std::collections::HashMap;
2
3use crate::error::{ParseError, ParseResult};
4use crate::functions::{define_function_full, ArgType, FunctionContext, FunctionSpec};
5use crate::parse_node::ParseNode;
6
7struct DelimInfo {
8    mclass: &'static str,
9    size: u8,
10}
11
12fn delim_info(name: &str) -> Option<DelimInfo> {
13    match name {
14        "\\bigl" => Some(DelimInfo {
15            mclass: "mopen",
16            size: 1,
17        }),
18        "\\Bigl" => Some(DelimInfo {
19            mclass: "mopen",
20            size: 2,
21        }),
22        "\\biggl" => Some(DelimInfo {
23            mclass: "mopen",
24            size: 3,
25        }),
26        "\\Biggl" => Some(DelimInfo {
27            mclass: "mopen",
28            size: 4,
29        }),
30        "\\bigr" => Some(DelimInfo {
31            mclass: "mclose",
32            size: 1,
33        }),
34        "\\Bigr" => Some(DelimInfo {
35            mclass: "mclose",
36            size: 2,
37        }),
38        "\\biggr" => Some(DelimInfo {
39            mclass: "mclose",
40            size: 3,
41        }),
42        "\\Biggr" => Some(DelimInfo {
43            mclass: "mclose",
44            size: 4,
45        }),
46        "\\bigm" => Some(DelimInfo {
47            mclass: "mrel",
48            size: 1,
49        }),
50        "\\Bigm" => Some(DelimInfo {
51            mclass: "mrel",
52            size: 2,
53        }),
54        "\\biggm" => Some(DelimInfo {
55            mclass: "mrel",
56            size: 3,
57        }),
58        "\\Biggm" => Some(DelimInfo {
59            mclass: "mrel",
60            size: 4,
61        }),
62        "\\big" => Some(DelimInfo {
63            mclass: "mord",
64            size: 1,
65        }),
66        "\\Big" => Some(DelimInfo {
67            mclass: "mord",
68            size: 2,
69        }),
70        "\\bigg" => Some(DelimInfo {
71            mclass: "mord",
72            size: 3,
73        }),
74        "\\Bigg" => Some(DelimInfo {
75            mclass: "mord",
76            size: 4,
77        }),
78        _ => None,
79    }
80}
81
82pub fn register(map: &mut HashMap<&'static str, FunctionSpec>) {
83    define_function_full(
84        map,
85        &[
86            "\\bigl", "\\Bigl", "\\biggl", "\\Biggl", "\\bigr", "\\Bigr", "\\biggr", "\\Biggr",
87            "\\bigm", "\\Bigm", "\\biggm", "\\Biggm", "\\big", "\\Big", "\\bigg", "\\Bigg",
88        ],
89        "delimsizing",
90        1,
91        0,
92        Some(vec![ArgType::Primitive]),
93        false,
94        false,
95        true,
96        false,
97        false,
98        handle_delimsizing,
99    );
100}
101
102fn handle_delimsizing(
103    ctx: &mut FunctionContext,
104    args: Vec<ParseNode>,
105    _opt_args: Vec<Option<ParseNode>>,
106) -> ParseResult<ParseNode> {
107    let delim = check_delimiter(&args[0], &ctx.func_name)?;
108    let info = delim_info(&ctx.func_name).unwrap();
109
110    Ok(ParseNode::DelimSizing {
111        mode: ctx.parser.mode,
112        size: info.size,
113        mclass: info.mclass.to_string(),
114        delim,
115        loc: None,
116    })
117}
118
119fn check_delimiter(node: &ParseNode, func_name: &str) -> ParseResult<String> {
120    if let Some(text) = node.symbol_text() {
121        if is_valid_delimiter(text) {
122            return Ok(text.to_string());
123        }
124        return Err(ParseError::msg(format!(
125            "Invalid delimiter '{}' after '{}'",
126            text, func_name
127        )));
128    }
129    Err(ParseError::msg(format!(
130        "Invalid delimiter type '{}' after '{}'",
131        node.type_name(),
132        func_name
133    )))
134}
135
136fn is_valid_delimiter(text: &str) -> bool {
137    matches!(
138        text,
139        "(" | "\\lparen"
140            | ")"
141            | "\\rparen"
142            | "["
143            | "\\lbrack"
144            | "]"
145            | "\\rbrack"
146            | "\\{"
147            | "\\lbrace"
148            | "\\}"
149            | "\\rbrace"
150            | "\\lfloor"
151            | "\\rfloor"
152            | "\\lceil"
153            | "\\rceil"
154            | "<"
155            | ">"
156            | "\\langle"
157            | "\\rangle"
158            | "\\lt"
159            | "\\gt"
160            | "\\lvert"
161            | "\\rvert"
162            | "\\lVert"
163            | "\\rVert"
164            | "\\lgroup"
165            | "\\rgroup"
166            | "\\lmoustache"
167            | "\\rmoustache"
168            | "/"
169            | "\\backslash"
170            | "|"
171            | "\\vert"
172            | "\\|"
173            | "\\Vert"
174            | "\\uparrow"
175            | "\\Uparrow"
176            | "\\downarrow"
177            | "\\Downarrow"
178            | "\\updownarrow"
179            | "\\Updownarrow"
180            | "."
181    )
182}