ratex_parser/functions/
delimsizing.rs1use 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 { mclass: "mopen", size: 1 }),
15 "\\Bigl" => Some(DelimInfo { mclass: "mopen", size: 2 }),
16 "\\biggl" => Some(DelimInfo { mclass: "mopen", size: 3 }),
17 "\\Biggl" => Some(DelimInfo { mclass: "mopen", size: 4 }),
18 "\\bigr" => Some(DelimInfo { mclass: "mclose", size: 1 }),
19 "\\Bigr" => Some(DelimInfo { mclass: "mclose", size: 2 }),
20 "\\biggr" => Some(DelimInfo { mclass: "mclose", size: 3 }),
21 "\\Biggr" => Some(DelimInfo { mclass: "mclose", size: 4 }),
22 "\\bigm" => Some(DelimInfo { mclass: "mrel", size: 1 }),
23 "\\Bigm" => Some(DelimInfo { mclass: "mrel", size: 2 }),
24 "\\biggm" => Some(DelimInfo { mclass: "mrel", size: 3 }),
25 "\\Biggm" => Some(DelimInfo { mclass: "mrel", size: 4 }),
26 "\\big" => Some(DelimInfo { mclass: "mord", size: 1 }),
27 "\\Big" => Some(DelimInfo { mclass: "mord", size: 2 }),
28 "\\bigg" => Some(DelimInfo { mclass: "mord", size: 3 }),
29 "\\Bigg" => Some(DelimInfo { mclass: "mord", size: 4 }),
30 _ => None,
31 }
32}
33
34pub fn register(map: &mut HashMap<&'static str, FunctionSpec>) {
35 define_function_full(
36 map,
37 &[
38 "\\bigl", "\\Bigl", "\\biggl", "\\Biggl",
39 "\\bigr", "\\Bigr", "\\biggr", "\\Biggr",
40 "\\bigm", "\\Bigm", "\\biggm", "\\Biggm",
41 "\\big", "\\Big", "\\bigg", "\\Bigg",
42 ],
43 "delimsizing",
44 1, 0,
45 Some(vec![ArgType::Primitive]),
46 false, false, true, false, false,
47 handle_delimsizing,
48 );
49}
50
51fn handle_delimsizing(
52 ctx: &mut FunctionContext,
53 args: Vec<ParseNode>,
54 _opt_args: Vec<Option<ParseNode>>,
55) -> ParseResult<ParseNode> {
56 let delim = check_delimiter(&args[0], &ctx.func_name)?;
57 let info = delim_info(&ctx.func_name).unwrap();
58
59 Ok(ParseNode::DelimSizing {
60 mode: ctx.parser.mode,
61 size: info.size,
62 mclass: info.mclass.to_string(),
63 delim,
64 loc: None,
65 })
66}
67
68fn check_delimiter(node: &ParseNode, func_name: &str) -> ParseResult<String> {
69 if let Some(text) = node.symbol_text() {
70 if is_valid_delimiter(text) {
71 return Ok(text.to_string());
72 }
73 return Err(ParseError::msg(format!(
74 "Invalid delimiter '{}' after '{}'",
75 text, func_name
76 )));
77 }
78 Err(ParseError::msg(format!(
79 "Invalid delimiter type '{}' after '{}'",
80 node.type_name(),
81 func_name
82 )))
83}
84
85fn is_valid_delimiter(text: &str) -> bool {
86 matches!(
87 text,
88 "(" | "\\lparen" | ")" | "\\rparen"
89 | "[" | "\\lbrack" | "]" | "\\rbrack"
90 | "\\{" | "\\lbrace" | "\\}" | "\\rbrace"
91 | "\\lfloor" | "\\rfloor"
92 | "\\lceil" | "\\rceil"
93 | "<" | ">" | "\\langle" | "\\rangle" | "\\lt" | "\\gt"
94 | "\\lvert" | "\\rvert" | "\\lVert" | "\\rVert"
95 | "\\lgroup" | "\\rgroup"
96 | "\\lmoustache" | "\\rmoustache"
97 | "/" | "\\backslash"
98 | "|" | "\\vert" | "\\|" | "\\Vert"
99 | "\\uparrow" | "\\Uparrow"
100 | "\\downarrow" | "\\Downarrow"
101 | "\\updownarrow" | "\\Updownarrow"
102 | "."
103 )
104}