ratex_parser/functions/
mod.rs1pub mod genfrac;
2pub mod sqrt;
3pub mod op;
4pub mod accent;
5pub mod font;
6pub mod color;
7pub mod sizing;
8pub mod delimsizing;
9pub mod left_right;
10pub mod spacing;
11pub mod styling;
12pub mod overline;
13pub mod kern;
14pub mod phantom;
15pub mod text;
16pub mod cr;
17pub mod relax;
18pub mod verb;
19pub mod symbols_cmd;
20pub mod environment;
21pub mod mclass;
22pub mod operatorname;
23pub mod horiz_brace;
24pub mod arrow;
25pub mod enclose;
26pub mod rule;
27pub mod href;
28pub mod hbox;
29pub mod lap;
30pub mod raisebox;
31pub mod vcenter;
32pub mod pmb;
33pub mod mathchoice;
34pub mod def;
35pub mod htmlmathml;
36pub mod char_cmd;
37pub mod math;
38pub mod tag;
39pub mod nonumber;
40pub mod bussproofs;
41
42use std::collections::HashMap;
43use crate::error::ParseResult;
44use crate::parse_node::{Mode, ParseNode};
45
46use ratex_lexer::token::Token;
47
48pub struct FunctionContext<'a, 'b> {
50 pub func_name: String,
51 pub parser: &'a mut crate::parser::Parser<'b>,
52 pub token: Option<Token>,
53 pub break_on_token_text: Option<String>,
54}
55
56pub type FunctionHandler =
58 fn(ctx: &mut FunctionContext, args: Vec<ParseNode>, opt_args: Vec<Option<ParseNode>>) -> ParseResult<ParseNode>;
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62pub enum ArgType {
63 Color,
64 Size,
65 Url,
66 Math,
67 Text,
68 HBox,
69 Raw,
70 Primitive,
71 Original,
72}
73
74pub struct FunctionSpec {
76 pub node_type: &'static str,
77 pub num_args: usize,
78 pub num_optional_args: usize,
79 pub arg_types: Option<Vec<ArgType>>,
80 pub allowed_in_argument: bool,
81 pub allowed_in_text: bool,
82 pub allowed_in_math: bool,
83 pub infix: bool,
84 pub primitive: bool,
85 pub handler: FunctionHandler,
86}
87
88pub static FUNCTIONS: std::sync::LazyLock<HashMap<&'static str, FunctionSpec>> =
90 std::sync::LazyLock::new(|| {
91 let mut map = HashMap::new();
92 genfrac::register(&mut map);
93 sqrt::register(&mut map);
94 op::register(&mut map);
95 accent::register(&mut map);
96 font::register(&mut map);
97 color::register(&mut map);
98 sizing::register(&mut map);
99 delimsizing::register(&mut map);
100 left_right::register(&mut map);
101 spacing::register(&mut map);
102 styling::register(&mut map);
103 overline::register(&mut map);
104 kern::register(&mut map);
105 phantom::register(&mut map);
106 text::register(&mut map);
107 cr::register(&mut map);
108 relax::register(&mut map);
109 verb::register(&mut map);
110 symbols_cmd::register(&mut map);
111 environment::register(&mut map);
112 mclass::register(&mut map);
113 operatorname::register(&mut map);
114 horiz_brace::register(&mut map);
115 arrow::register(&mut map);
116 enclose::register(&mut map);
117 rule::register(&mut map);
118 href::register(&mut map);
119 hbox::register(&mut map);
120 lap::register(&mut map);
121 raisebox::register(&mut map);
122 vcenter::register(&mut map);
123 pmb::register(&mut map);
124 mathchoice::register(&mut map);
125 def::register(&mut map);
126 htmlmathml::register(&mut map);
127 char_cmd::register(&mut map);
128 math::register(&mut map);
129 tag::register(&mut map);
130 nonumber::register(&mut map);
131 bussproofs::register(&mut map);
132 map
133 });
134
135pub fn define_function(
137 map: &mut HashMap<&'static str, FunctionSpec>,
138 names: &[&'static str],
139 node_type: &'static str,
140 num_args: usize,
141 handler: FunctionHandler,
142) {
143 define_function_full(
144 map, names, node_type, num_args, 0, None, false, false, true, false, false, handler,
145 );
146}
147
148#[allow(clippy::too_many_arguments)]
149pub fn define_function_full(
150 map: &mut HashMap<&'static str, FunctionSpec>,
151 names: &[&'static str],
152 node_type: &'static str,
153 num_args: usize,
154 num_optional_args: usize,
155 arg_types: Option<Vec<ArgType>>,
156 allowed_in_argument: bool,
157 allowed_in_text: bool,
158 allowed_in_math: bool,
159 infix: bool,
160 primitive: bool,
161 handler: FunctionHandler,
162) {
163 for &name in names {
164 map.insert(
165 name,
166 FunctionSpec {
167 node_type,
168 num_args,
169 num_optional_args,
170 arg_types: arg_types.clone(),
171 allowed_in_argument,
172 allowed_in_text,
173 allowed_in_math,
174 infix,
175 primitive,
176 handler,
177 },
178 );
179 }
180}
181
182pub fn check_mode_compatibility(
184 func: &FunctionSpec,
185 mode: Mode,
186 func_name: &str,
187 token: Option<&Token>,
188) -> ParseResult<()> {
189 if mode == Mode::Text && !func.allowed_in_text {
190 return Err(crate::error::ParseError::new(
191 format!("Can't use function '{}' in text mode", func_name),
192 token,
193 ));
194 }
195 if mode == Mode::Math && !func.allowed_in_math {
196 return Err(crate::error::ParseError::new(
197 format!("Can't use function '{}' in math mode", func_name),
198 token,
199 ));
200 }
201 Ok(())
202}