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