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