1use std::collections::HashMap;
2
3use ratex_lexer::token::{SourceLocation, Token};
4use ratex_lexer::Lexer;
5
6use crate::error::{ParseError, ParseResult};
7use crate::functions::FUNCTIONS;
8use crate::parse_node::Mode;
9
10pub static IMPLICIT_COMMANDS: &[&str] = &["^", "_", "\\limits", "\\nolimits"];
13
14pub type FnMacroHandler = fn(&mut MacroExpander) -> ParseResult<Vec<Token>>;
17
18#[derive(Clone)]
20pub enum MacroDefinition {
21 Text(String),
23 Tokens {
25 tokens: Vec<Token>,
26 num_args: usize,
27 },
28 Function(FnMacroHandler),
30}
31
32impl std::fmt::Debug for MacroDefinition {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 match self {
35 Self::Text(s) => write!(f, "Text({:?})", s),
36 Self::Tokens { tokens, num_args } => {
37 write!(f, "Tokens {{ {} tokens, {} args }}", tokens.len(), num_args)
38 }
39 Self::Function(_) => write!(f, "Function(...)"),
40 }
41 }
42}
43
44struct MacroExpansion {
46 tokens: Vec<Token>,
47 num_args: usize,
48 unexpandable: bool,
49}
50
51pub struct MacroExpander<'a> {
59 pub lexer: Lexer<'a>,
60 pub mode: Mode,
61 stack: Vec<Token>,
62 macros: MacroNamespace,
63 expansion_count: usize,
64 max_expand: usize,
65}
66
67struct MacroNamespace {
69 current: HashMap<String, MacroDefinition>,
70 group_stack: Vec<HashMap<String, Option<MacroDefinition>>>,
71}
72
73impl MacroNamespace {
74 fn new() -> Self {
75 Self {
76 current: HashMap::new(),
77 group_stack: Vec::new(),
78 }
79 }
80
81 fn get(&self, name: &str) -> Option<&MacroDefinition> {
82 self.current.get(name)
83 }
84
85 fn set(&mut self, name: String, def: MacroDefinition) {
86 if let Some(undo) = self.group_stack.last_mut() {
87 undo.entry(name.clone()).or_insert_with(|| self.current.get(&name).cloned());
88 }
89 self.current.insert(name, def);
90 }
91
92 fn set_global(&mut self, name: String, def: MacroDefinition) {
93 self.current.insert(name, def);
94 }
95
96 fn has(&self, name: &str) -> bool {
97 self.current.contains_key(name)
98 }
99
100 fn begin_group(&mut self) {
101 self.group_stack.push(HashMap::new());
102 }
103
104 fn end_group(&mut self) {
105 if let Some(undo) = self.group_stack.pop() {
106 for (name, old_val) in undo {
107 match old_val {
108 Some(def) => { self.current.insert(name, def); }
109 None => { self.current.remove(&name); }
110 }
111 }
112 }
113 }
114
115 fn end_groups(&mut self) {
116 while !self.group_stack.is_empty() {
117 self.end_group();
118 }
119 }
120}
121
122fn lex_string_to_stack_tokens(text: &str) -> Vec<Token> {
124 let mut body_lexer = Lexer::new(text);
125 let mut tokens = Vec::new();
126 loop {
127 let tok = body_lexer.lex();
128 if tok.is_eof() {
129 break;
130 }
131 tokens.push(tok);
132 }
133 tokens.reverse();
134 tokens
135}
136
137impl<'a> MacroExpander<'a> {
138 pub fn new(input: &'a str, mode: Mode) -> Self {
139 let mut me = Self {
140 lexer: Lexer::new(input),
141 mode,
142 stack: Vec::new(),
143 macros: MacroNamespace::new(),
144 expansion_count: 0,
145 max_expand: 1000,
146 };
147 me.load_builtins();
148 me
149 }
150
151 fn load_builtins(&mut self) {
152 let builtins: &[(&str, &str)] = &[
153 ("\\bgroup", "{"),
155 ("\\egroup", "}"),
156
157 ("\\lq", "`"),
159 ("\\rq", "'"),
160 ("\\aa", "\\r a"),
162 ("\\AA", "\\r A"),
163
164 ("~", "\\nobreakspace"),
166
167 ("\\hphantom", "\\smash{\\phantom{#1}}"),
169
170 ("\\not", "\\html@mathml{\\mathrel{\\mathrlap\\@not}\\nobreak}{\\char\"338}"),
172 ("\\neq", "\\html@mathml{\\mathrel{\\not=}}{\\mathrel{\\char`≠}}"),
173 ("\\ne", "\\neq"),
174 ("\u{2260}", "\\neq"),
175 ("\\notin", "\\html@mathml{\\mathrel{{\\in}\\mathllap{/\\mskip1mu}}}{\\mathrel{\\char`∉}}"),
176 ("\u{2209}", "\\notin"),
177 ("\\notni", "\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u{220C}}}"),
178 ("\u{220C}", "\\notni"),
179 ("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;"),
183 ("\\implies", "\\DOTSB\\;\\Longrightarrow\\;"),
184 ("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"),
185
186 ("\\varGamma", "\\mathit{\\Gamma}"),
188 ("\\varDelta", "\\mathit{\\Delta}"),
189 ("\\varTheta", "\\mathit{\\Theta}"),
190 ("\\varLambda", "\\mathit{\\Lambda}"),
191 ("\\varXi", "\\mathit{\\Xi}"),
192 ("\\varPi", "\\mathit{\\Pi}"),
193 ("\\varSigma", "\\mathit{\\Sigma}"),
194 ("\\varUpsilon", "\\mathit{\\Upsilon}"),
195 ("\\varPhi", "\\mathit{\\Phi}"),
196 ("\\varPsi", "\\mathit{\\Psi}"),
197 ("\\varOmega", "\\mathit{\\Omega}"),
198
199 ("\\,", "\\TextOrMath{\\kern{.1667em}}{\\mskip{3mu}}"),
201 ("\\thinspace", "\\,"),
202 ("\\>", "\\mskip{4mu}"),
203 ("\\:", "\\TextOrMath{\\kern{.2222em}}{\\mskip{4mu}}"),
204 ("\\medspace", "\\:"),
205 ("\\;", "\\TextOrMath{\\kern{.2777em}}{\\mskip{5mu}}"),
206 ("\\thickspace", "\\;"),
207 ("\\!", "\\TextOrMath{\\kern{-.1667em}}{\\mskip{-3mu}}"),
208 ("\\negthinspace", "\\!"),
209 ("\\negmedspace", "\\TextOrMath{\\kern{-.2222em}}{\\mskip{-4mu}}"),
210 ("\\negthickspace", "\\TextOrMath{\\kern{-.2777em}}{\\mskip{-5mu}}"),
211 ("\\enspace", "\\kern.5em "),
212 ("\\enskip", "\\hskip.5em\\relax"),
213 ("\\quad", "\\hskip1em\\relax"),
214 ("\\qquad", "\\hskip2em\\relax"),
215
216 ("\\newline", "\\\\\\relax"),
218
219 ("\\@hspace", "\\hskip #1\\relax"),
221 ("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"),
222
223 ("\\llap", "\\mathllap{\\textrm{#1}}"),
225 ("\\rlap", "\\mathrlap{\\textrm{#1}}"),
226 ("\\clap", "\\mathclap{\\textrm{#1}}"),
227
228 ("\\TeX", "\\textrm{\\html@mathml{T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX}{TeX}}"),
230 ("\\LaTeX", "\\textrm{\\html@mathml{L\\kern-.36em\\raisebox{0.21em}{\\scriptstyle A}\\kern-.15em\\TeX}{LaTeX}}"),
231 ("\\KaTeX", "\\textrm{\\html@mathml{K\\kern-.17em\\raisebox{0.21em}{\\scriptstyle A}\\kern-.15em\\TeX}{KaTeX}}"),
232
233 ("\\imath", "\\html@mathml{\\@imath}{\u{0131}}"),
235 ("\\jmath", "\\html@mathml{\\@jmath}{\u{0237}}"),
236
237 ("\\minuso", "\\mathbin{\\html@mathml{{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}{\\char`\u{29B5}}}"),
239 ("\\clap", "\\mathclap{\\textrm{#1}}"),
240
241 ("\\mathstrut", "\\vphantom{(}"),
243 ("\\underbar", "\\underline{\\text{#1}}"),
244
245 ("\\Bbbk", "\\Bbb{k}"),
247
248 ("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"),
250
251 ("\\boxed", "\\fbox{$\\displaystyle{#1}$}"),
253
254 ("\\colon", "\\nobreak\\mskip2mu\\mathpunct{}\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu\\relax"),
256
257 ("\\dots", "\\cdots"),
259 ("\\cdots", "\\@cdots"),
260 ("\\dotsb", "\\cdots"),
261 ("\\dotsm", "\\cdots"),
262 ("\\dotsi", "\\!\\cdots"),
263 ("\\dotsx", "\\ldots\\,"),
264 ("\\dotsc", "\\ldots"), ("\\dotso", "\\ldots"), ("\\DOTSI", "\\relax"),
267 ("\\DOTSB", "\\relax"),
268 ("\\DOTSX", "\\relax"),
269
270 ("\\gvertneqq", "\\@gvertneqq"),
272 ("\\lvertneqq", "\\@lvertneqq"),
273 ("\\ngeqq", "\\@ngeqq"),
274 ("\\ngeqslant", "\\@ngeqslant"),
275 ("\\nleqq", "\\@nleqq"),
276 ("\\nleqslant", "\\@nleqslant"),
277 ("\\nshortmid", "\\@nshortmid"),
278 ("\\nshortparallel", "\\@nshortparallel"),
279 ("\\nsubseteqq", "\\@nsubseteqq"),
280 ("\\nsupseteqq", "\\@nsupseteqq"),
281 ("\\ulcorner", "\\@ulcorner"),
282 ("\\urcorner", "\\@urcorner"),
283 ("\\llcorner", "\\@llcorner"),
284 ("\\lrcorner", "\\@lrcorner"),
285 ("\\varsubsetneq", "\\@varsubsetneq"),
286 ("\\varsubsetneqq", "\\@varsubsetneqq"),
287 ("\\varsupsetneq", "\\@varsupsetneq"),
288 ("\\varsupsetneqq", "\\@varsupsetneqq"),
289
290 ("\\lBrace", "\\mathopen{\\{\\mkern-3.2mu[}"),
293 ("\\rBrace", "\\mathclose{]\\mkern-3.2mu\\}}"),
294 ("\\llbracket", "\\mathopen{[\\mkern-3.2mu[}"),
295 ("\\rrbracket", "\\mathclose{]\\mkern-3.2mu]}"),
296 ("\\copyright", "\\textcircled{c}"),
297 ("\\textregistered", "\u{00AE}"),
298
299 ("\\dddot", "{\\overset{\\raisebox{-0.1ex}{\\normalsize ...}}{#1}}"),
301 ("\\ddddot", "{\\overset{\\raisebox{-0.1ex}{\\normalsize ....}}{#1}}"),
302
303 ("\\vdots", "{\\varvdots\\rule{0pt}{15pt}}"),
305 ("\u{22ee}", "\\vdots"),
306
307 ("\\bmod", "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}\\mathbin{\\rm mod}\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"),
309 ("\\pod", "\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"),
310 ("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}"),
311 ("\\mod", "\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}{\\rm mod}\\,\\,#1"),
312
313 ("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}"),
315 ("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"),
316 ("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}"),
317 ("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}"),
318 ("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{lim}}"),
319 ("\\varliminf", "\\DOTSB\\operatorname*{\\underline{lim}}"),
320 ("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{lim}}"),
321 ("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{lim}}"),
322
323 ("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}"),
325 ("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}"),
326 ("\\plim", "\\DOTSB\\mathop{\\operatorname{plim}}\\limits"),
327
328 ("\\ordinarycolon", ":"),
330 ("\\vcentcolon", "\\mathrel{\\mathop\\ordinarycolon}"),
331 ("\\dblcolon", "\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}{\\mathop{\\char\"2237}}"),
332 ("\\coloneqq", "\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char\"2254}}"),
333 ("\\Coloneqq", "\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char\"2237\\char\"3d}}"),
334 ("\\coloneq", "\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char\"3a\\char\"2212}}"),
335 ("\\Coloneq", "\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char\"2237\\char\"2212}}"),
336 ("\\eqqcolon", "\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char\"2255}}"),
337 ("\\Eqqcolon", "\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char\"3d\\char\"2237}}"),
338 ("\\eqcolon", "\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char\"2239}}"),
339 ("\\Eqcolon", "\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char\"2212\\char\"2237}}"),
340 ("\\colonapprox", "\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char\"3a\\char\"2248}}"),
341 ("\\Colonapprox", "\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char\"2237\\char\"2248}}"),
342 ("\\colonsim", "\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char\"3a\\char\"223c}}"),
343 ("\\Colonsim", "\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char\"2237\\char\"223c}}"),
344
345 ("\\ratio", "\\vcentcolon"),
347 ("\\coloncolon", "\\dblcolon"),
348 ("\\colonequals", "\\coloneqq"),
349 ("\\coloncolonequals", "\\Coloneqq"),
350 ("\\equalscolon", "\\eqqcolon"),
351 ("\\equalscoloncolon", "\\Eqqcolon"),
352 ("\\colonminus", "\\coloneq"),
353 ("\\coloncolonminus", "\\Coloneq"),
354 ("\\minuscolon", "\\eqcolon"),
355 ("\\minuscoloncolon", "\\Eqcolon"),
356 ("\\coloncolonapprox", "\\Colonapprox"),
357 ("\\coloncolonsim", "\\Colonsim"),
358 ("\\simcolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),
359 ("\\simcoloncolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}"),
360 ("\\approxcolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),
361 ("\\approxcoloncolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"),
362
363 ("\\bra", "\\mathinner{\\langle{#1}|}"),
365 ("\\ket", "\\mathinner{|{#1}\\rangle}"),
366 ("\\braket", "\\mathinner{\\langle{#1}\\rangle}"),
367 ("\\Braket", "\\bra@ket{\\left\\langle}{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\right\\rangle}"),
368 ("\\Bra", "\\left\\langle#1\\right|"),
369 ("\\Ket", "\\left|#1\\right\\rangle"),
370
371 ("\\darr", "\\downarrow"),
373 ("\\dArr", "\\Downarrow"),
374 ("\\Darr", "\\Downarrow"),
375 ("\\lang", "\\langle"),
376 ("\\rang", "\\rangle"),
377 ("\\uarr", "\\uparrow"),
378 ("\\uArr", "\\Uparrow"),
379 ("\\Uarr", "\\Uparrow"),
380 ("\\N", "\\mathbb{N}"),
381 ("\\R", "\\mathbb{R}"),
382 ("\\Z", "\\mathbb{Z}"),
383 ("\\alef", "\\aleph"),
384 ("\\alefsym", "\\aleph"),
385 ("\\Alpha", "\\mathrm{A}"),
386 ("\\Beta", "\\mathrm{B}"),
387 ("\\bull", "\\bullet"),
388 ("\\Chi", "\\mathrm{X}"),
389 ("\\clubs", "\\clubsuit"),
390 ("\\cnums", "\\mathbb{C}"),
391 ("\\Complex", "\\mathbb{C}"),
392 ("\\Dagger", "\\ddagger"),
393 ("\\diamonds", "\\diamondsuit"),
394 ("\\empty", "\\emptyset"),
395 ("\\Epsilon", "\\mathrm{E}"),
396 ("\\Eta", "\\mathrm{H}"),
397 ("\\exist", "\\exists"),
398 ("\\harr", "\\leftrightarrow"),
399 ("\\hArr", "\\Leftrightarrow"),
400 ("\\Harr", "\\Leftrightarrow"),
401 ("\\hearts", "\\heartsuit"),
402 ("\\image", "\\Im"),
403 ("\\infin", "\\infty"),
404 ("\\Iota", "\\mathrm{I}"),
405 ("\\isin", "\\in"),
406 ("\\Kappa", "\\mathrm{K}"),
407 ("\\larr", "\\leftarrow"),
408 ("\\lArr", "\\Leftarrow"),
409 ("\\Larr", "\\Leftarrow"),
410 ("\\lrarr", "\\leftrightarrow"),
411 ("\\lrArr", "\\Leftrightarrow"),
412 ("\\Lrarr", "\\Leftrightarrow"),
413 ("\\Mu", "\\mathrm{M}"),
414 ("\\natnums", "\\mathbb{N}"),
415 ("\\Nu", "\\mathrm{N}"),
416 ("\\Omicron", "\\mathrm{O}"),
417 ("\\plusmn", "\\pm"),
418 ("\\rarr", "\\rightarrow"),
419 ("\\rArr", "\\Rightarrow"),
420 ("\\Rarr", "\\Rightarrow"),
421 ("\\real", "\\Re"),
422 ("\\reals", "\\mathbb{R}"),
423 ("\\Reals", "\\mathbb{R}"),
424 ("\\Rho", "\\mathrm{P}"),
425 ("\\sdot", "\\cdot"),
426 ("\\sect", "\\S"),
427 ("\\spades", "\\spadesuit"),
428 ("\\sub", "\\subset"),
429 ("\\sube", "\\subseteq"),
430 ("\\supe", "\\supseteq"),
431 ("\\Tau", "\\mathrm{T}"),
432 ("\\thetasym", "\\vartheta"),
433 ("\\weierp", "\\wp"),
434 ("\\Zeta", "\\mathrm{Z}"),
435
436 ("\\blue", "\\textcolor{##6495ed}{#1}"),
438 ("\\orange", "\\textcolor{##ffa500}{#1}"),
439 ("\\pink", "\\textcolor{##ff00af}{#1}"),
440 ("\\red", "\\textcolor{##df0030}{#1}"),
441 ("\\green", "\\textcolor{##28ae7b}{#1}"),
442 ("\\gray", "\\textcolor{gray}{#1}"),
443 ("\\purple", "\\textcolor{##9d38bd}{#1}"),
444
445 ("\u{212C}", "\\mathscr{B}"),
447 ("\u{2130}", "\\mathscr{E}"),
448 ("\u{2131}", "\\mathscr{F}"),
449 ("\u{210B}", "\\mathscr{H}"),
450 ("\u{2110}", "\\mathscr{I}"),
451 ("\u{2112}", "\\mathscr{L}"),
452 ("\u{2133}", "\\mathscr{M}"),
453 ("\u{211B}", "\\mathscr{R}"),
454 ("\u{212D}", "\\mathfrak{C}"),
455 ("\u{210C}", "\\mathfrak{H}"),
456 ("\u{2128}", "\\mathfrak{Z}"),
457
458 ("\\notni", "\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u{220C}}}"),
460
461 ("\\angln", "{\\angl n}"),
463
464 ("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"),
466 ("\\Set", "\\bra@set{\\left\\{\\:}{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"),
467
468 ("\\tag", "\\@ifstar\\tag@literal\\tag@paren"),
470 ("\\tag@paren", "\\tag@literal{({#1})}"),
471 ("\\tag@literal", "\\gdef\\df@tag{\\text{#1}}"),
472 ("\\nonumber", "\\relax"),
474 ("\\notag", "\\relax"),
475
476 (
478 "\\tripledash",
479 "{\\vphantom{-}\\raisebox{2.56mu}{$\\mkern2mu\\tiny\\text{-}\\mkern1mu\\text{-}\\mkern1mu\\text{-}\\mkern2mu$}}",
480 ),
481 ];
482
483 for &(name, expansion) in builtins {
484 self.macros.set(
485 name.to_string(),
486 MacroDefinition::Text(expansion.to_string()),
487 );
488 }
489
490 self.load_function_macros();
491 }
492
493 fn load_function_macros(&mut self) {
494 self.macros.set(
496 "\\noexpand".to_string(),
497 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
498 let mut tok = me.pop_token();
499 if me.is_expandable(&tok.text) {
500 tok.noexpand = true;
501 tok.treat_as_relax = true;
502 }
503 Ok(vec![tok])
504 }),
505 );
506
507 self.macros.set(
511 "\\@firstoftwo".to_string(),
512 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
513 let args = me.consume_args(2)?;
514 Ok(args.into_iter().next().unwrap())
515 }),
516 );
517
518 self.macros.set(
520 "\\@secondoftwo".to_string(),
521 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
522 let args = me.consume_args(2)?;
523 Ok(args.into_iter().nth(1).unwrap())
524 }),
525 );
526
527 self.macros.set(
529 "\\@ifnextchar".to_string(),
530 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
531 let args = me.consume_args(3)?;
532 me.consume_spaces();
533 let next = me.future().text.clone();
534 let char_arg = &args[0];
535 let char_text = char_arg.first().map_or("", |t| t.text.as_str());
537 if next == char_text {
538 Ok(args[1].clone())
539 } else {
540 Ok(args[2].clone())
541 }
542 }),
543 );
544
545 self.macros.set(
547 "\\@ifstar".to_string(),
548 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
549 let args = me.consume_args(2)?;
550 let next = me.future().text.clone();
551 if next == "*" {
552 me.pop_token();
553 Ok(args[0].clone())
554 } else {
555 Ok(args[1].clone())
556 }
557 }),
558 );
559
560 self.macros.set(
562 "\\TextOrMath".to_string(),
563 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
564 let args = me.consume_args(2)?;
565 if me.mode == Mode::Text {
566 Ok(args[0].clone())
567 } else {
568 Ok(args[1].clone())
569 }
570 }),
571 );
572
573 self.macros.set(
577 "\\newcommand".to_string(),
578 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
579 handle_newcommand(me, false, true)
580 }),
581 );
582
583 self.macros.set(
585 "\\renewcommand".to_string(),
586 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
587 handle_newcommand(me, true, false)
588 }),
589 );
590
591 self.macros.set(
593 "\\providecommand".to_string(),
594 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
595 handle_newcommand(me, true, true)
596 }),
597 );
598
599 self.macros.set(
601 "\\char".to_string(),
602 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
603 let mut tok = me.pop_token();
604 let mut number: i64;
605 let base: Option<u32>;
606
607 if tok.text == "'" {
608 base = Some(8);
609 tok = me.pop_token();
610 } else if tok.text == "\"" {
611 base = Some(16);
612 tok = me.pop_token();
613 } else if tok.text == "`" {
614 tok = me.pop_token();
615 if tok.text.starts_with('\\') {
616 number = tok.text.chars().nth(1).map_or(0, |c| c as i64);
617 } else {
618 number = tok.text.chars().next().map_or(0, |c| c as i64);
619 }
620 let s = number.to_string();
622 let loc = tok.loc.clone();
623 let mut result = vec![Token::new("}", loc.start, loc.end)];
624 for ch in s.chars().rev() {
625 result.push(Token::new(ch.to_string(), loc.start, loc.end));
626 }
627 result.push(Token::new("{", loc.start, loc.end));
628 result.push(Token::new("\\@char", loc.start, loc.end));
629 return Ok(result);
630 } else {
631 base = Some(10);
632 }
633
634 if let Some(b) = base {
635 number = i64::from_str_radix(&tok.text, b).unwrap_or(0);
636 loop {
637 let next = me.future().text.clone();
638 if let Ok(d) = i64::from_str_radix(&next, b) {
639 me.pop_token();
640 number = number * (b as i64) + d;
641 } else {
642 break;
643 }
644 }
645 } else {
646 number = 0;
647 }
648
649 let s = number.to_string();
650 let loc = tok.loc.clone();
651 let mut result = vec![Token::new("}", loc.start, loc.end)];
652 for ch in s.chars().rev() {
653 result.push(Token::new(ch.to_string(), loc.start, loc.end));
654 }
655 result.push(Token::new("{", loc.start, loc.end));
656 result.push(Token::new("\\@char", loc.start, loc.end));
657 Ok(result)
658 }),
659 );
660
661 self.macros.set(
663 "\\operatorname".to_string(),
664 MacroDefinition::Text(
665 "\\@ifstar\\operatornamewithlimits\\operatorname@".to_string(),
666 ),
667 );
668
669 self.macros.set(
671 "\\message".to_string(),
672 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
673 let _args = me.consume_args(1)?;
674 Ok(vec![])
675 }),
676 );
677
678 self.macros.set(
680 "\\errmessage".to_string(),
681 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
682 let _args = me.consume_args(1)?;
683 Ok(vec![])
684 }),
685 );
686
687 for name in &["\\htmlClass", "\\htmlData", "\\htmlId", "\\htmlStyle"] {
690 let name = (*name).to_string();
691 self.macros.set(
692 name.clone(),
693 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
694 let args = me.consume_args(2)?;
695 let content = args[1].iter().cloned().rev().collect::<Vec<_>>();
696 Ok(content)
697 }),
698 );
699 }
700
701 self.macros.set(
703 "\\bra@ket".to_string(),
704 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
705 let args = me.consume_args(4)?;
706 let left = args[0].clone();
707 let middle = args[1].clone();
708 let middle_double = args[2].clone();
709 let right = args[3].clone();
710
711 let content = me.consume_args(1)?;
712 let content = content.into_iter().next().unwrap();
713
714 let logical: Vec<Token> = content.into_iter().rev().collect();
717 let mut new_logical: Vec<Token> = Vec::new();
718 let mut depth: i32 = 0;
719 let mut i = 0;
720 while i < logical.len() {
721 let t = &logical[i];
722 if t.text == "{" {
723 depth += 1;
724 new_logical.push(t.clone());
725 } else if t.text == "}" {
726 depth -= 1;
727 new_logical.push(t.clone());
728 } else if depth == 0 && t.text == "|" {
729 if !middle_double.is_empty()
731 && i + 1 < logical.len()
732 && logical[i + 1].text == "|"
733 {
734 new_logical.extend(middle_double.iter().rev().cloned());
736 i += 2;
737 continue;
738 }
739 new_logical.extend(middle.iter().rev().cloned());
741 } else {
742 new_logical.push(t.clone());
743 }
744 i += 1;
745 }
746
747 let content_rev: Vec<Token> = new_logical.into_iter().rev().collect();
749
750 let mut to_expand = Vec::new();
752 to_expand.extend(right);
753 to_expand.extend(content_rev);
754 to_expand.extend(left);
755
756 me.begin_group();
757 let expanded = me.expand_tokens(to_expand)?;
758 me.end_group();
759
760 Ok(expanded)
761 }),
762 );
763
764 self.macros.set(
767 "\\bra@set".to_string(),
768 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
769 let args = me.consume_args(4)?;
770 let left = args[0].clone();
771 let middle = args[1].clone();
772 let middle_double = args[2].clone();
773 let right = args[3].clone();
774
775 let content = me.consume_args(1)?;
776 let mut content = content.into_iter().next().unwrap();
777
778 let mut depth: i32 = 0;
781 let mut _first_pipe_idx: Option<usize> = None;
782 for i in (0..content.len()).rev() {
784 let t = &content[i];
785 if t.text == "{" { depth += 1; }
786 else if t.text == "}" { depth -= 1; }
787 else if depth == 0 && t.text == "|" {
788 if !middle_double.is_empty() && i > 0 && content[i - 1].text == "|" {
790 _first_pipe_idx = Some(i);
791 content.remove(i);
793 content.remove(i - 1);
794 let insert_at = if i >= 2 { i - 1 } else { 0 };
795 for (j, tok) in middle_double.iter().enumerate() {
796 content.insert(insert_at + j, tok.clone());
797 }
798 break;
799 }
800 _first_pipe_idx = Some(i);
801 content.remove(i);
802 for (j, tok) in middle.iter().enumerate() {
803 content.insert(i + j, tok.clone());
804 }
805 break;
806 }
807 }
808
809 let mut to_expand = Vec::new();
811 to_expand.extend(right);
812 to_expand.extend(content);
813 to_expand.extend(left);
814
815 me.begin_group();
816 let expanded = me.expand_tokens(to_expand)?;
817 me.end_group();
818
819 Ok(expanded)
820 }),
821 );
822
823 self.macros.set(
825 "\\ce".to_string(),
826 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
827 let args = me.consume_args(1)?;
828 let s = crate::mhchem::mhchem_arg_tokens_to_string(&args[0]);
829 let tex = crate::mhchem::chem_parse_str(&s, "ce")
830 .map_err(|e| ParseError::msg(format!("\\ce: {e}")))?;
831 Ok(lex_string_to_stack_tokens(&tex))
832 }),
833 );
834 self.macros.set(
835 "\\pu".to_string(),
836 MacroDefinition::Function(|me: &mut MacroExpander| -> ParseResult<Vec<Token>> {
837 let args = me.consume_args(1)?;
838 let s = crate::mhchem::mhchem_arg_tokens_to_string(&args[0]);
839 let tex = crate::mhchem::chem_parse_str(&s, "pu")
840 .map_err(|e| ParseError::msg(format!("\\pu: {e}")))?;
841 Ok(lex_string_to_stack_tokens(&tex))
842 }),
843 );
844 }
845
846 pub fn set_macro(&mut self, name: String, def: MacroDefinition) {
847 self.macros.set(name, def);
848 }
849
850 pub fn set_macro_global(&mut self, name: String, def: MacroDefinition) {
851 self.macros.set_global(name, def);
852 }
853
854 pub fn set_text_macro(&mut self, name: &str, text: &str) {
855 self.macros.set(
856 name.to_string(),
857 MacroDefinition::Text(text.to_string()),
858 );
859 }
860
861 pub fn get_macro(&self, name: &str) -> Option<&MacroDefinition> {
862 self.macros.get(name)
863 }
864
865 pub fn expand_tokens(&mut self, tokens: Vec<Token>) -> ParseResult<Vec<Token>> {
867 let saved_stack = std::mem::take(&mut self.stack);
868 self.stack = tokens;
869
870 let mut result = Vec::new();
871 loop {
872 if self.stack.is_empty() {
873 break;
874 }
875 let expanded = self.expand_once(false)?;
876 if !expanded {
877 if let Some(tok) = self.stack.pop() {
878 if tok.is_eof() {
879 break;
880 }
881 result.push(tok);
882 }
883 }
884 }
885
886 self.stack = saved_stack;
887 result.reverse();
888 Ok(result)
889 }
890
891 pub fn switch_mode(&mut self, new_mode: Mode) {
892 self.mode = new_mode;
893 }
894
895 pub fn begin_group(&mut self) {
896 self.macros.begin_group();
897 }
898
899 pub fn end_group(&mut self) {
900 self.macros.end_group();
901 }
902
903 pub fn end_groups(&mut self) {
904 self.macros.end_groups();
905 }
906
907 pub fn future(&mut self) -> &Token {
909 if self.stack.is_empty() {
910 let tok = self.lexer.lex();
911 self.stack.push(tok);
912 }
913 self.stack.last().unwrap()
914 }
915
916 pub fn pop_token(&mut self) -> Token {
918 self.future();
919 self.stack.pop().unwrap()
920 }
921
922 pub fn set_top_text(&mut self, text: String) {
924 self.future();
925 if let Some(tok) = self.stack.last_mut() {
926 tok.text = text;
927 }
928 }
929
930 pub fn push_token(&mut self, token: Token) {
932 self.stack.push(token);
933 }
934
935 pub fn push_tokens(&mut self, tokens: Vec<Token>) {
937 self.stack.extend(tokens);
938 }
939
940 pub fn consume_spaces(&mut self) {
942 loop {
943 let is_space = self.future().text == " ";
944 if is_space {
945 self.stack.pop();
946 } else {
947 break;
948 }
949 }
950 }
951
952 fn expand_once(&mut self, expandable_only: bool) -> ParseResult<bool> {
955 let top_token = self.pop_token();
956 let name = &top_token.text;
957
958 if top_token.noexpand {
959 self.push_token(top_token);
960 return Ok(false);
961 }
962
963 if let Some(MacroDefinition::Function(handler)) = self.macros.get(name).cloned() {
965 self.count_expansion(1)?;
966 let tokens = handler(self)?;
967 self.stack.extend(tokens);
968 return Ok(true);
969 }
970
971 let expansion = self.get_expansion(name);
972 match expansion {
973 None => {
974 if expandable_only && name.starts_with('\\') && !self.is_defined(name) {
975 return Err(ParseError::new(
976 format!("Undefined control sequence: {}", name),
977 Some(&top_token),
978 ));
979 }
980 self.push_token(top_token);
981 Ok(false)
982 }
983 Some(exp) if expandable_only && exp.unexpandable => {
984 self.push_token(top_token);
985 Ok(false)
986 }
987 Some(exp) => {
988 self.count_expansion(1)?;
989 let mut tokens = exp.tokens;
990 if exp.num_args > 0 {
991 let args = self.consume_args(exp.num_args)?;
992 tokens = self.substitute_args(tokens, &args);
993 }
994 self.stack.extend(tokens);
995 Ok(true)
996 }
997 }
998 }
999
1000 fn substitute_args(&self, mut tokens: Vec<Token>, args: &[Vec<Token>]) -> Vec<Token> {
1001 let mut i = tokens.len();
1002 while i > 0 {
1003 i -= 1;
1004 if tokens[i].text == "#" && i > 0 {
1005 let next = &tokens[i - 1];
1006 if next.text == "#" {
1007 tokens.remove(i);
1008 i -= 1;
1009 } else if let Ok(n) = next.text.parse::<usize>() {
1010 if n >= 1 && n <= args.len() {
1011 tokens.remove(i);
1012 tokens.remove(i - 1);
1013 let arg_tokens = &args[n - 1];
1014 for (j, t) in arg_tokens.iter().enumerate() {
1015 tokens.insert(i - 1 + j, t.clone());
1016 }
1017 i = i.saturating_sub(1);
1018 }
1019 }
1020 }
1021 }
1022 tokens
1023 }
1024
1025 fn get_expansion(&self, name: &str) -> Option<MacroExpansion> {
1026 let def = self.macros.get(name)?;
1027
1028 if name.len() == 1 {
1029 let ch = name.chars().next().unwrap();
1030 let catcode = self.lexer_catcode(ch);
1031 if catcode != 0 && catcode != 13 {
1032 return None;
1033 }
1034 }
1035
1036 match def {
1037 MacroDefinition::Text(text) => {
1038 let mut num_args = 0;
1039 let stripped = text.replace("##", "");
1040 while stripped.contains(&format!("#{}", num_args + 1)) {
1041 num_args += 1;
1042 }
1043 let mut body_lexer = Lexer::new(text);
1044 let mut tokens = Vec::new();
1045 loop {
1046 let tok = body_lexer.lex();
1047 if tok.is_eof() {
1048 break;
1049 }
1050 tokens.push(tok);
1051 }
1052 tokens.reverse();
1053 Some(MacroExpansion {
1054 tokens,
1055 num_args,
1056 unexpandable: false,
1057 })
1058 }
1059 MacroDefinition::Tokens { tokens, num_args } => Some(MacroExpansion {
1060 tokens: tokens.clone(),
1061 num_args: *num_args,
1062 unexpandable: false,
1063 }),
1064 MacroDefinition::Function(_) => {
1065 Some(MacroExpansion {
1067 tokens: vec![],
1068 num_args: 0,
1069 unexpandable: false,
1070 })
1071 }
1072 }
1073 }
1074
1075 fn lexer_catcode(&self, ch: char) -> u8 {
1076 self.lexer.get_catcode(ch)
1077 }
1078
1079 fn count_expansion(&mut self, amount: usize) -> ParseResult<()> {
1080 self.expansion_count += amount;
1081 if self.expansion_count > self.max_expand {
1082 Err(ParseError::msg(
1083 "Too many expansions: infinite loop or need to increase maxExpand setting",
1084 ))
1085 } else {
1086 Ok(())
1087 }
1088 }
1089
1090 pub fn expand_next_token(&mut self) -> ParseResult<Token> {
1092 loop {
1093 let expanded = self.expand_once(false)?;
1094 if !expanded {
1095 let mut token = self.stack.pop().unwrap();
1096 if token.treat_as_relax {
1097 token.text = "\\relax".to_string();
1098 }
1099 return Ok(token);
1100 }
1101 }
1102 }
1103
1104 pub fn consume_arg(&mut self, delims: Option<&[&str]>) -> ParseResult<ConsumedArg> {
1106 let is_delimited = delims.is_some_and(|d| !d.is_empty());
1107 if !is_delimited {
1108 self.consume_spaces();
1109 }
1110
1111 let start = self.future().clone();
1112 let mut tokens = Vec::new();
1113 let mut depth: i32 = 0;
1114 let mut end_tok;
1115
1116 loop {
1117 let tok = self.pop_token();
1118 end_tok = tok.clone();
1119 tokens.push(tok.clone());
1120
1121 if tok.text == "{" {
1122 depth += 1;
1123 } else if tok.text == "}" {
1124 depth -= 1;
1125 if depth == -1 {
1126 return Err(ParseError::new("Extra }", Some(&tok)));
1127 }
1128 } else if tok.is_eof() {
1129 return Err(ParseError::new(
1130 "Unexpected end of input in a macro argument",
1131 Some(&tok),
1132 ));
1133 }
1134
1135 if depth == 0 && !is_delimited {
1136 break;
1137 }
1138
1139 if let Some(delims) = delims {
1140 if is_delimited && depth == 0 {
1141 if let Some(last) = delims.last() {
1142 if tok.text == *last {
1143 tokens.pop();
1144 break;
1145 }
1146 }
1147 }
1148 }
1149 }
1150
1151 if start.text == "{" && tokens.last().is_some_and(|t| t.text == "}") {
1152 tokens.pop();
1153 tokens.remove(0);
1154 }
1155
1156 tokens.reverse();
1157
1158 Ok(ConsumedArg {
1159 tokens,
1160 start,
1161 end: end_tok,
1162 })
1163 }
1164
1165 fn consume_args(&mut self, num_args: usize) -> ParseResult<Vec<Vec<Token>>> {
1167 let mut args = Vec::with_capacity(num_args);
1168 for _ in 0..num_args {
1169 let arg = self.consume_arg(None)?;
1170 args.push(arg.tokens);
1171 }
1172 Ok(args)
1173 }
1174
1175 pub fn scan_argument(&mut self, is_optional: bool) -> ParseResult<Option<Token>> {
1178 if is_optional {
1179 self.consume_spaces();
1180 if self.future().text != "[" {
1181 return Ok(None);
1182 }
1183 let start = self.pop_token();
1184 let arg = self.consume_arg(Some(&["]"]))?;
1185 let end = &arg.end;
1186 let end_loc = end.loc.clone();
1187
1188 self.push_token(Token::new("EOF", end_loc.start, end_loc.end));
1189 self.push_tokens(arg.tokens);
1190
1191 let result = Token {
1192 text: String::new(),
1193 loc: SourceLocation::range(&start.loc, &end_loc),
1194 noexpand: false,
1195 treat_as_relax: false,
1196 };
1197 Ok(Some(result))
1198 } else {
1199 let arg = self.consume_arg(None)?;
1200 let end_loc = arg.end.loc.clone();
1201
1202 self.push_token(Token::new("EOF", end_loc.start, end_loc.end));
1203 self.push_tokens(arg.tokens);
1204
1205 let result = Token {
1206 text: String::new(),
1207 loc: SourceLocation::range(&arg.start.loc, &end_loc),
1208 noexpand: false,
1209 treat_as_relax: false,
1210 };
1211 Ok(Some(result))
1212 }
1213 }
1214
1215 pub fn is_defined(&self, name: &str) -> bool {
1217 self.macros.has(name)
1218 || FUNCTIONS.contains_key(name)
1219 || is_known_symbol(name)
1220 || IMPLICIT_COMMANDS.contains(&name)
1221 }
1222
1223 pub fn is_expandable(&self, name: &str) -> bool {
1225 if let Some(_def) = self.macros.get(name) {
1226 return true;
1227 }
1228 if let Some(func) = FUNCTIONS.get(name) {
1229 return !func.primitive;
1230 }
1231 false
1232 }
1233}
1234
1235pub struct ConsumedArg {
1236 pub tokens: Vec<Token>,
1237 pub start: Token,
1238 pub end: Token,
1239}
1240
1241fn handle_newcommand(
1242 me: &mut MacroExpander,
1243 exists_ok: bool,
1244 nonexists_ok: bool,
1245) -> ParseResult<Vec<Token>> {
1246 let name_arg = me.consume_arg(None)?;
1247 let name = name_arg.tokens.last().map_or_else(String::new, |t| t.text.clone());
1249
1250 let exists = me.is_defined(&name);
1251 if exists && !exists_ok {
1252 return Err(ParseError::msg(format!(
1253 "\\newcommand{{{}}} attempting to redefine {}; use \\renewcommand",
1254 name, name
1255 )));
1256 }
1257 if !exists && !nonexists_ok {
1258 return Err(ParseError::msg(format!(
1259 "\\renewcommand{{{}}} when command {} does not yet exist; use \\newcommand",
1260 name, name
1261 )));
1262 }
1263
1264 me.consume_spaces();
1265 let mut num_args = 0usize;
1266 if me.future().text == "[" {
1267 me.pop_token();
1268 let narg_tok = me.pop_token();
1269 num_args = narg_tok.text.parse().unwrap_or(0);
1270 let close = me.pop_token();
1271 if close.text != "]" {
1272 return Err(ParseError::msg("Expected ] in \\newcommand"));
1273 }
1274 }
1275
1276 let body_arg = me.consume_arg(None)?;
1277 let tokens = body_arg.tokens;
1278
1279 me.set_macro(name, MacroDefinition::Tokens { tokens, num_args });
1280 Ok(vec![])
1281}
1282
1283fn is_known_symbol(name: &str) -> bool {
1284 use ratex_font::symbols;
1285 symbols::get_symbol(name, symbols::Mode::Math).is_some()
1286 || symbols::get_symbol(name, symbols::Mode::Text).is_some()
1287}