katex-parser 0.1.0

A port of the KaTeX parser: lexing and parsing LaTeX math expressions with macro expansion into a typed AST, plus a Unicode rendering backend
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
use std::collections::HashMap;
use std::sync::OnceLock;

use crate::ast::Mode;

#[allow(clippy::enum_variant_names)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub(crate) enum SymbolGroup {
    AccentTokenGroup,
    BinaryGroup,
    CloseGroup,
    InnerGroup,
    MathOrdGroup,
    OperatorTokenGroup,
    OpenGroup,
    PunctuationGroup,
    RelationGroup,
    SpacingGroup,
    TextOrdGroup,
}

#[derive(Clone, Debug)]
pub(crate) struct SymbolSpec {
    pub(crate) group: SymbolGroup,
    pub(crate) replacement: String,
}

pub(crate) struct SymbolRegistry {
    pub(crate) math: HashMap<String, SymbolSpec>,
    pub(crate) text: HashMap<String, SymbolSpec>,
}

impl SymbolRegistry {
    fn new() -> Self {
        SymbolRegistry {
            math: HashMap::new(),
            text: HashMap::new(),
        }
    }

    fn define_symbol(
        &mut self,
        mode: Mode,
        group: SymbolGroup,
        replacement: &str,
        name: &str,
        accept_unicode: bool,
    ) {
        let table = if mode == Mode::Math { &mut self.math } else { &mut self.text };
        let spec = SymbolSpec {
            group,
            replacement: replacement.to_string(),
        };
        table.insert(name.to_string(), spec.clone());
        if accept_unicode && !replacement.is_empty() {
            table.insert(replacement.to_string(), spec);
        }
    }
}

fn codepoint_string(codepoint: u32) -> String {
    char::from_u32(codepoint).unwrap().to_string()
}

fn build_builtin_symbols() -> SymbolRegistry {
    let mut registry = SymbolRegistry::new();
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2261}", "\\equiv", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{227A}", "\\prec", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{227B}", "\\succ", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{223C}", "\\sim", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22A5}", "\\perp", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2AAF}", "\\preceq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2AB0}", "\\succeq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2243}", "\\simeq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2223}", "\\mid", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{226A}", "\\ll", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{226B}", "\\gg", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{224D}", "\\asymp", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2225}", "\\parallel", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22C8}", "\\bowtie", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2323}", "\\smile", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2291}", "\\sqsubseteq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2292}", "\\sqsupseteq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2250}", "\\doteq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2322}", "\\frown", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{220B}", "\\ni", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{221D}", "\\propto", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22A2}", "\\vdash", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22A3}", "\\dashv", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{220B}", "\\owns", false);
    registry.define_symbol(Mode::Math, SymbolGroup::PunctuationGroup, ".", "\\ldotp", false);
    registry.define_symbol(Mode::Math, SymbolGroup::PunctuationGroup, "\u{22C5}", "\\cdotp", false);
    registry.define_symbol(Mode::Math, SymbolGroup::PunctuationGroup, "\u{22C5}", "\u{B7}", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{22C5}", "\u{B7}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "#", "\\#", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "#", "\\#", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "&", "\\&", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "&", "\\&", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2135}", "\\aleph", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2200}", "\\forall", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{210F}", "\\hbar", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2203}", "\\exists", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2207}", "\\nabla", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{266D}", "\\flat", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2113}", "\\ell", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{266E}", "\\natural", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2663}", "\\clubsuit", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2118}", "\\wp", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{266F}", "\\sharp", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2662}", "\\diamondsuit", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{211C}", "\\Re", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2661}", "\\heartsuit", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2111}", "\\Im", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2660}", "\\spadesuit", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{A7}", "\\S", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{A7}", "\\S", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{B6}", "\\P", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{B6}", "\\P", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2020}", "\\dag", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{2020}", "\\dag", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{2020}", "\\textdagger", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2021}", "\\ddag", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{2021}", "\\ddag", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{2021}", "\\textdaggerdbl", false);
    registry.define_symbol(Mode::Math, SymbolGroup::CloseGroup, "\u{23B1}", "\\rmoustache", true);
    registry.define_symbol(Mode::Math, SymbolGroup::OpenGroup, "\u{23B0}", "\\lmoustache", true);
    registry.define_symbol(Mode::Math, SymbolGroup::CloseGroup, "\u{27EF}", "\\rgroup", true);
    registry.define_symbol(Mode::Math, SymbolGroup::OpenGroup, "\u{27EE}", "\\lgroup", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2213}", "\\mp", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2296}", "\\ominus", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{228E}", "\\uplus", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2293}", "\\sqcap", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2217}", "\\ast", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2294}", "\\sqcup", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{25EF}", "\\bigcirc", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2219}", "\\bullet", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2021}", "\\ddagger", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2240}", "\\wr", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2A3F}", "\\amalg", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "&", "\\And", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{27F5}", "\\longleftarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21D0}", "\\Leftarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{27F8}", "\\Longleftarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{27F6}", "\\longrightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21D2}", "\\Rightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{27F9}", "\\Longrightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2194}", "\\leftrightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{27F7}", "\\longleftrightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21D4}", "\\Leftrightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{27FA}", "\\Longleftrightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21A6}", "\\mapsto", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{27FC}", "\\longmapsto", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2197}", "\\nearrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21A9}", "\\hookleftarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21AA}", "\\hookrightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2198}", "\\searrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21BC}", "\\leftharpoonup", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21C0}", "\\rightharpoonup", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2199}", "\\swarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21BD}", "\\leftharpoondown", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21C1}", "\\rightharpoondown", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2196}", "\\nwarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21CC}", "\\rightleftharpoons", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{226E}", "\\nless", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{E010}", "\\@nleqslant", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{E011}", "\\@nleqq", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2A87}", "\\lneq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2268}", "\\lneqq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{E00C}", "\\@lvertneqq", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22E6}", "\\lnsim", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2A89}", "\\lnapprox", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2280}", "\\nprec", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22E0}", "\\npreceq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22E8}", "\\precnsim", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2AB9}", "\\precnapprox", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2241}", "\\nsim", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{E006}", "\\@nshortmid", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2224}", "\\nmid", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22AC}", "\\nvdash", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22AD}", "\\nvDash", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22EA}", "\\ntriangleleft", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22EC}", "\\ntrianglelefteq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{228A}", "\\subsetneq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{E01A}", "\\@varsubsetneq", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2ACB}", "\\subsetneqq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{E017}", "\\@varsubsetneqq", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{226F}", "\\ngtr", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{E00F}", "\\@ngeqslant", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{E00E}", "\\@ngeqq", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2A88}", "\\gneq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2269}", "\\gneqq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{E00D}", "\\@gvertneqq", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22E7}", "\\gnsim", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2A8A}", "\\gnapprox", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2281}", "\\nsucc", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22E1}", "\\nsucceq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22E9}", "\\succnsim", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2ABA}", "\\succnapprox", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2246}", "\\ncong", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{E007}", "\\@nshortparallel", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2226}", "\\nparallel", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22AF}", "\\nVDash", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22EB}", "\\ntriangleright", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22ED}", "\\ntrianglerighteq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{E018}", "\\@nsupseteqq", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{228B}", "\\supsetneq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{E01B}", "\\@varsupsetneq", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2ACC}", "\\supsetneqq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{E019}", "\\@varsupsetneqq", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22AE}", "\\nVdash", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2AB5}", "\\precneqq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2AB6}", "\\succneqq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{E016}", "\\@nsubseteqq", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22B4}", "\\unlhd", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22B5}", "\\unrhd", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{219A}", "\\nleftarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{219B}", "\\nrightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21CD}", "\\nLeftarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21CF}", "\\nRightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21AE}", "\\nleftrightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21CE}", "\\nLeftrightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{25B3}", "\\vartriangle", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{210F}", "\\hslash", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{25BD}", "\\triangledown", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{25CA}", "\\lozenge", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{24C8}", "\\circledS", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{AE}", "\\circledR", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{AE}", "\\circledR", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2221}", "\\measuredangle", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2204}", "\\nexists", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2127}", "\\mho", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2132}", "\\Finv", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2141}", "\\Game", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2035}", "\\backprime", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{25B2}", "\\blacktriangle", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{25BC}", "\\blacktriangledown", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{25A0}", "\\blacksquare", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{29EB}", "\\blacklozenge", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2605}", "\\bigstar", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2222}", "\\sphericalangle", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2201}", "\\complement", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{F0}", "\u{F0}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2571}", "\\diagup", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2572}", "\\diagdown", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{25A1}", "\\square", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{25A1}", "\\Box", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{25CA}", "\\Diamond", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{A5}", "\\yen", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2713}", "\\checkmark", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{2713}", "\\checkmark", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2136}", "\\beth", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2138}", "\\daleth", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2137}", "\\gimel", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{3DD}", "\\digamma", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{3F0}", "\\varkappa", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OpenGroup, "\u{250C}", "\\@ulcorner", true);
    registry.define_symbol(Mode::Math, SymbolGroup::CloseGroup, "\u{2510}", "\\@urcorner", true);
    registry.define_symbol(Mode::Math, SymbolGroup::OpenGroup, "\u{2514}", "\\@llcorner", true);
    registry.define_symbol(Mode::Math, SymbolGroup::CloseGroup, "\u{2518}", "\\@lrcorner", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2266}", "\\leqq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2A7D}", "\\leqslant", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2A95}", "\\eqslantless", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2272}", "\\lesssim", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2A85}", "\\lessapprox", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{224A}", "\\approxeq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22D6}", "\\lessdot", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22D8}", "\\lll", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2276}", "\\lessgtr", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22DA}", "\\lesseqgtr", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2A8B}", "\\lesseqqgtr", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2251}", "\\doteqdot", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2253}", "\\risingdotseq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2252}", "\\fallingdotseq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{223D}", "\\backsim", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22CD}", "\\backsimeq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2AC5}", "\\subseteqq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22D0}", "\\Subset", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{228F}", "\\sqsubset", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{227C}", "\\preccurlyeq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22DE}", "\\curlyeqprec", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{227E}", "\\precsim", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2AB7}", "\\precapprox", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22B2}", "\\vartriangleleft", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22B4}", "\\trianglelefteq", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22A8}", "\\vDash", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22AA}", "\\Vvdash", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2323}", "\\smallsmile", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2322}", "\\smallfrown", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{224F}", "\\bumpeq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{224E}", "\\Bumpeq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2267}", "\\geqq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2A7E}", "\\geqslant", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2A96}", "\\eqslantgtr", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2273}", "\\gtrsim", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2A86}", "\\gtrapprox", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22D7}", "\\gtrdot", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22D9}", "\\ggg", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2277}", "\\gtrless", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22DB}", "\\gtreqless", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2A8C}", "\\gtreqqless", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2256}", "\\eqcirc", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2257}", "\\circeq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{225C}", "\\triangleq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{223C}", "\\thicksim", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2248}", "\\thickapprox", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2AC6}", "\\supseteqq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22D1}", "\\Supset", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2290}", "\\sqsupset", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{227D}", "\\succcurlyeq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22DF}", "\\curlyeqsucc", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{227F}", "\\succsim", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2AB8}", "\\succapprox", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22B3}", "\\vartriangleright", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22B5}", "\\trianglerighteq", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22A9}", "\\Vdash", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2223}", "\\shortmid", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2225}", "\\shortparallel", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{226C}", "\\between", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22D4}", "\\pitchfork", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{221D}", "\\varpropto", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{25C0}", "\\blacktriangleleft", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2234}", "\\therefore", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{220D}", "\\backepsilon", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{25B6}", "\\blacktriangleright", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2235}", "\\because", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22D8}", "\\llless", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22D9}", "\\gggtr", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22B2}", "\\lhd", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22B3}", "\\rhd", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2242}", "\\eqsim", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22C8}", "\\Join", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2251}", "\\Doteq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2214}", "\\dotplus", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2216}", "\\smallsetminus", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22D2}", "\\Cap", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22D3}", "\\Cup", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2A5E}", "\\doublebarwedge", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{229F}", "\\boxminus", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{229E}", "\\boxplus", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22C7}", "\\divideontimes", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22C9}", "\\ltimes", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22CA}", "\\rtimes", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22CB}", "\\leftthreetimes", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22CC}", "\\rightthreetimes", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22CF}", "\\curlywedge", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22CE}", "\\curlyvee", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{229D}", "\\circleddash", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{229B}", "\\circledast", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22C5}", "\\centerdot", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22BA}", "\\intercal", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22D2}", "\\doublecap", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22D3}", "\\doublecup", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22A0}", "\\boxtimes", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21E2}", "\\dashrightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21E0}", "\\dashleftarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21C7}", "\\leftleftarrows", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21C6}", "\\leftrightarrows", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21DA}", "\\Lleftarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{219E}", "\\twoheadleftarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21A2}", "\\leftarrowtail", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21AB}", "\\looparrowleft", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21CB}", "\\leftrightharpoons", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21B6}", "\\curvearrowleft", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21BA}", "\\circlearrowleft", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21B0}", "\\Lsh", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21C8}", "\\upuparrows", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21BF}", "\\upharpoonleft", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21C3}", "\\downharpoonleft", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22B6}", "\\origof", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22B7}", "\\imageof", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22B8}", "\\multimap", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21AD}", "\\leftrightsquigarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21C9}", "\\rightrightarrows", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21C4}", "\\rightleftarrows", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21A0}", "\\twoheadrightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21A3}", "\\rightarrowtail", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21AC}", "\\looparrowright", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21B7}", "\\curvearrowright", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21BB}", "\\circlearrowright", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21B1}", "\\Rsh", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21CA}", "\\downdownarrows", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21BE}", "\\upharpoonright", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21C2}", "\\downharpoonright", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21DD}", "\\rightsquigarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21DD}", "\\leadsto", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21DB}", "\\Rrightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21BE}", "\\restriction", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2018}", "`", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "$", "\\$", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "$", "\\$", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "$", "\\textdollar", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "%", "\\%", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "%", "\\%", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "_", "\\_", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "_", "\\_", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "_", "\\textunderscore", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2220}", "\\angle", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{221E}", "\\infty", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2032}", "\\prime", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{25B3}", "\\triangle", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{393}", "\\Gamma", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{394}", "\\Delta", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{398}", "\\Theta", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{39B}", "\\Lambda", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{39E}", "\\Xi", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{3A0}", "\\Pi", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{3A3}", "\\Sigma", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{3A5}", "\\Upsilon", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{3A6}", "\\Phi", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{3A8}", "\\Psi", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{3A9}", "\\Omega", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "A", "\u{391}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "B", "\u{392}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "E", "\u{395}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "Z", "\u{396}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "H", "\u{397}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "I", "\u{399}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "K", "\u{39A}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "M", "\u{39C}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "N", "\u{39D}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "O", "\u{39F}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "P", "\u{3A1}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "T", "\u{3A4}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "X", "\u{3A7}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{AC}", "\\neg", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{AC}", "\\lnot", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{22A4}", "\\top", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{22A5}", "\\bot", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2205}", "\\emptyset", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2205}", "\\varnothing", false);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3B1}", "\\alpha", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3B2}", "\\beta", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3B3}", "\\gamma", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3B4}", "\\delta", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3F5}", "\\epsilon", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3B6}", "\\zeta", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3B7}", "\\eta", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3B8}", "\\theta", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3B9}", "\\iota", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3BA}", "\\kappa", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3BB}", "\\lambda", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3BC}", "\\mu", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3BD}", "\\nu", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3BE}", "\\xi", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3BF}", "\\omicron", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3C0}", "\\pi", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3C1}", "\\rho", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3C3}", "\\sigma", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3C4}", "\\tau", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3C5}", "\\upsilon", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3D5}", "\\phi", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3C7}", "\\chi", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3C8}", "\\psi", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3C9}", "\\omega", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3B5}", "\\varepsilon", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3D1}", "\\vartheta", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3D6}", "\\varpi", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3F1}", "\\varrho", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3C2}", "\\varsigma", true);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{3C6}", "\\varphi", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2217}", "*", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "+", "+", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2212}", "-", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22C5}", "\\cdot", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2218}", "\\circ", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{F7}", "\\div", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{B1}", "\\pm", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{D7}", "\\times", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2229}", "\\cap", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{222A}", "\\cup", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2216}", "\\setminus", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2227}", "\\land", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2228}", "\\lor", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2227}", "\\wedge", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2228}", "\\vee", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{221A}", "\\surd", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OpenGroup, "\u{27E8}", "\\langle", true);
    registry.define_symbol(Mode::Math, SymbolGroup::OpenGroup, "\u{2223}", "\\lvert", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OpenGroup, "\u{2016}", "\\lVert", false);
    registry.define_symbol(Mode::Math, SymbolGroup::CloseGroup, "?", "?", false);
    registry.define_symbol(Mode::Math, SymbolGroup::CloseGroup, "!", "!", false);
    registry.define_symbol(Mode::Math, SymbolGroup::CloseGroup, "\u{27E9}", "\\rangle", true);
    registry.define_symbol(Mode::Math, SymbolGroup::CloseGroup, "\u{2223}", "\\rvert", false);
    registry.define_symbol(Mode::Math, SymbolGroup::CloseGroup, "\u{2016}", "\\rVert", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "=", "=", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, ":", ":", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2248}", "\\approx", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2245}", "\\cong", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2265}", "\\ge", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2265}", "\\geq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2190}", "\\gets", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, ">", "\\gt", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2208}", "\\in", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{E020}", "\\@not", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2282}", "\\subset", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2283}", "\\supset", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2286}", "\\subseteq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2287}", "\\supseteq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2288}", "\\nsubseteq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2289}", "\\nsupseteq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{22A8}", "\\models", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2190}", "\\leftarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2264}", "\\le", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2264}", "\\leq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "<", "\\lt", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2192}", "\\rightarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2192}", "\\to", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2271}", "\\ngeq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2270}", "\\nleq", true);
    registry.define_symbol(Mode::Math, SymbolGroup::SpacingGroup, "\u{A0}", "\\ ", false);
    registry.define_symbol(Mode::Math, SymbolGroup::SpacingGroup, "\u{A0}", "\\space", false);
    registry.define_symbol(Mode::Math, SymbolGroup::SpacingGroup, "\u{A0}", "\\nobreakspace", false);
    registry.define_symbol(Mode::Text, SymbolGroup::SpacingGroup, "\u{A0}", "\\ ", false);
    registry.define_symbol(Mode::Text, SymbolGroup::SpacingGroup, "\u{A0}", " ", false);
    registry.define_symbol(Mode::Text, SymbolGroup::SpacingGroup, "\u{A0}", "\\space", false);
    registry.define_symbol(Mode::Text, SymbolGroup::SpacingGroup, "\u{A0}", "\\nobreakspace", false);
    registry.define_symbol(Mode::Math, SymbolGroup::SpacingGroup, "", "\\nobreak", false);
    registry.define_symbol(Mode::Math, SymbolGroup::SpacingGroup, "", "\\allowbreak", false);
    registry.define_symbol(Mode::Math, SymbolGroup::PunctuationGroup, ",", ",", false);
    registry.define_symbol(Mode::Math, SymbolGroup::PunctuationGroup, ";", ";", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22BC}", "\\barwedge", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22BB}", "\\veebar", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2299}", "\\odot", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2295}", "\\oplus", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2297}", "\\otimes", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2202}", "\\partial", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2298}", "\\oslash", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{229A}", "\\circledcirc", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22A1}", "\\boxdot", true);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{25B3}", "\\bigtriangleup", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{25BD}", "\\bigtriangledown", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{2020}", "\\dagger", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22C4}", "\\diamond", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{22C6}", "\\star", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{25C3}", "\\triangleleft", false);
    registry.define_symbol(Mode::Math, SymbolGroup::BinaryGroup, "\u{25B9}", "\\triangleright", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OpenGroup, "{", "\\{", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "{", "\\{", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "{", "\\textbraceleft", false);
    registry.define_symbol(Mode::Math, SymbolGroup::CloseGroup, "}", "\\}", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "}", "\\}", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "}", "\\textbraceright", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OpenGroup, "{", "\\lbrace", false);
    registry.define_symbol(Mode::Math, SymbolGroup::CloseGroup, "}", "\\rbrace", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OpenGroup, "[", "\\lbrack", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "[", "\\lbrack", true);
    registry.define_symbol(Mode::Math, SymbolGroup::CloseGroup, "]", "\\rbrack", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "]", "\\rbrack", true);
    registry.define_symbol(Mode::Math, SymbolGroup::OpenGroup, "(", "\\lparen", true);
    registry.define_symbol(Mode::Math, SymbolGroup::CloseGroup, ")", "\\rparen", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "<", "\\textless", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, ">", "\\textgreater", true);
    registry.define_symbol(Mode::Math, SymbolGroup::OpenGroup, "\u{230A}", "\\lfloor", true);
    registry.define_symbol(Mode::Math, SymbolGroup::CloseGroup, "\u{230B}", "\\rfloor", true);
    registry.define_symbol(Mode::Math, SymbolGroup::OpenGroup, "\u{2308}", "\\lceil", true);
    registry.define_symbol(Mode::Math, SymbolGroup::CloseGroup, "\u{2309}", "\\rceil", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\\", "\\backslash", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2223}", "|", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2223}", "\\vert", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "|", "\\textbar", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2016}", "\\|", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2016}", "\\Vert", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{2016}", "\\textbardbl", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "~", "\\textasciitilde", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\\", "\\textbackslash", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "^", "\\textasciicircum", false);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2191}", "\\uparrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21D1}", "\\Uparrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2193}", "\\downarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21D3}", "\\Downarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{2195}", "\\updownarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::RelationGroup, "\u{21D5}", "\\Updownarrow", true);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{2210}", "\\coprod", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{22C1}", "\\bigvee", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{22C0}", "\\bigwedge", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{2A04}", "\\biguplus", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{22C2}", "\\bigcap", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{22C3}", "\\bigcup", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{222B}", "\\int", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{222B}", "\\intop", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{222C}", "\\iint", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{222D}", "\\iiint", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{220F}", "\\prod", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{2211}", "\\sum", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{2A02}", "\\bigotimes", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{2A01}", "\\bigoplus", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{2A00}", "\\bigodot", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{222E}", "\\oint", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{222F}", "\\oiint", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{2230}", "\\oiiint", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{2A06}", "\\bigsqcup", false);
    registry.define_symbol(Mode::Math, SymbolGroup::OperatorTokenGroup, "\u{222B}", "\\smallint", false);
    registry.define_symbol(Mode::Text, SymbolGroup::InnerGroup, "\u{2026}", "\\textellipsis", false);
    registry.define_symbol(Mode::Math, SymbolGroup::InnerGroup, "\u{2026}", "\\mathellipsis", false);
    registry.define_symbol(Mode::Text, SymbolGroup::InnerGroup, "\u{2026}", "\\ldots", true);
    registry.define_symbol(Mode::Math, SymbolGroup::InnerGroup, "\u{2026}", "\\ldots", true);
    registry.define_symbol(Mode::Math, SymbolGroup::InnerGroup, "\u{22EF}", "\\@cdots", true);
    registry.define_symbol(Mode::Math, SymbolGroup::InnerGroup, "\u{22F1}", "\\ddots", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{22EE}", "\\varvdots", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{22EE}", "\\varvdots", false);
    registry.define_symbol(Mode::Math, SymbolGroup::AccentTokenGroup, "\u{2CA}", "\\acute", false);
    registry.define_symbol(Mode::Math, SymbolGroup::AccentTokenGroup, "\u{2CB}", "\\grave", false);
    registry.define_symbol(Mode::Math, SymbolGroup::AccentTokenGroup, "\u{A8}", "\\ddot", false);
    registry.define_symbol(Mode::Math, SymbolGroup::AccentTokenGroup, "~", "\\tilde", false);
    registry.define_symbol(Mode::Math, SymbolGroup::AccentTokenGroup, "\u{2C9}", "\\bar", false);
    registry.define_symbol(Mode::Math, SymbolGroup::AccentTokenGroup, "\u{2D8}", "\\breve", false);
    registry.define_symbol(Mode::Math, SymbolGroup::AccentTokenGroup, "\u{2C7}", "\\check", false);
    registry.define_symbol(Mode::Math, SymbolGroup::AccentTokenGroup, "^", "\\hat", false);
    registry.define_symbol(Mode::Math, SymbolGroup::AccentTokenGroup, "\u{20D7}", "\\vec", false);
    registry.define_symbol(Mode::Math, SymbolGroup::AccentTokenGroup, "\u{2D9}", "\\dot", false);
    registry.define_symbol(Mode::Math, SymbolGroup::AccentTokenGroup, "\u{2DA}", "\\mathring", false);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{E131}", "\\@imath", false);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "\u{E237}", "\\@jmath", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{131}", "\u{131}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{237}", "\u{237}", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{131}", "\\i", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{237}", "\\j", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{DF}", "\\ss", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{E6}", "\\ae", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{153}", "\\oe", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{F8}", "\\o", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{C6}", "\\AE", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{152}", "\\OE", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{D8}", "\\O", true);
    registry.define_symbol(Mode::Text, SymbolGroup::AccentTokenGroup, "\u{2CA}", "\\'", false);
    registry.define_symbol(Mode::Text, SymbolGroup::AccentTokenGroup, "\u{2CB}", "\\`", false);
    registry.define_symbol(Mode::Text, SymbolGroup::AccentTokenGroup, "\u{2C6}", "\\^", false);
    registry.define_symbol(Mode::Text, SymbolGroup::AccentTokenGroup, "\u{2DC}", "\\~", false);
    registry.define_symbol(Mode::Text, SymbolGroup::AccentTokenGroup, "\u{2C9}", "\\=", false);
    registry.define_symbol(Mode::Text, SymbolGroup::AccentTokenGroup, "\u{2D8}", "\\u", false);
    registry.define_symbol(Mode::Text, SymbolGroup::AccentTokenGroup, "\u{2D9}", "\\.", false);
    registry.define_symbol(Mode::Text, SymbolGroup::AccentTokenGroup, "\u{B8}", "\\c", false);
    registry.define_symbol(Mode::Text, SymbolGroup::AccentTokenGroup, "\u{2DA}", "\\r", false);
    registry.define_symbol(Mode::Text, SymbolGroup::AccentTokenGroup, "\u{2C7}", "\\v", false);
    registry.define_symbol(Mode::Text, SymbolGroup::AccentTokenGroup, "\u{A8}", "\\\"", false);
    registry.define_symbol(Mode::Text, SymbolGroup::AccentTokenGroup, "\u{2DD}", "\\H", false);
    registry.define_symbol(Mode::Text, SymbolGroup::AccentTokenGroup, "\u{25EF}", "\\textcircled", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{2013}", "--", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{2013}", "\\textendash", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{2014}", "---", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{2014}", "\\textemdash", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{2018}", "`", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{2018}", "\\textquoteleft", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{2019}", "'", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{2019}", "\\textquoteright", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{201C}", "``", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{201C}", "\\textquotedblleft", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{201D}", "''", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{201D}", "\\textquotedblright", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{B0}", "\\degree", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{B0}", "\\degree", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{B0}", "\\textdegree", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{A3}", "\\pounds", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{A3}", "\\mathsterling", true);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{A3}", "\\pounds", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{A3}", "\\textsterling", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{2720}", "\\maltese", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "\u{2720}", "\\maltese", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "C", "\u{2102}", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "C", "\u{2102}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "H", "\u{210D}", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "H", "\u{210D}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "N", "\u{2115}", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "N", "\u{2115}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "P", "\u{2119}", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "P", "\u{2119}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "Q", "\u{211A}", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "Q", "\u{211A}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "R", "\u{211D}", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "R", "\u{211D}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "Z", "\u{2124}", false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "Z", "\u{2124}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "h", "\u{210E}", false);
    registry.define_symbol(Mode::Text, SymbolGroup::MathOrdGroup, "h", "\u{210E}", false);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{F0}", "\\eth", true);
    registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, "\u{A5}", "\\yen", true);
    for ch in "0123456789/@.\"".chars() {
        let text = ch.to_string();
        registry.define_symbol(Mode::Math, SymbolGroup::TextOrdGroup, &text, &text, false);
    }
    for ch in "0123456789!@*()-=+\";:?/.,".chars() {
        let text = ch.to_string();
        registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, &text, &text, false);
    }
    let letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    for (index, ch) in letters.chars().enumerate() {
        let text = ch.to_string();
        registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, &text, &text, false);
        registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, &text, &text, false);
        for start in [
            0x1D400, 0x1D434, 0x1D468, 0x1D504, 0x1D56C, 0x1D5A0, 0x1D5D4, 0x1D608, 0x1D670,
        ] {
            let wide = codepoint_string(start + index as u32);
            registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, &text, &wide, false);
            registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, &text, &wide, false);
        }
        if index < 26 {
            for start in [0x1D538, 0x1D49C] {
                let wide = codepoint_string(start + index as u32);
                registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, &text, &wide, false);
                registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, &text, &wide, false);
            }
        }
    }
    let double_struck_k = codepoint_string(0x1D55C);
    registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, "k", &double_struck_k, false);
    registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, "k", &double_struck_k, false);
    for (index, ch) in "0123456789".chars().enumerate() {
        let text = ch.to_string();
        for start in [0x1D7CE, 0x1D7E2, 0x1D7EC, 0x1D7F6] {
            let wide = codepoint_string(start + index as u32);
            registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, &text, &wide, false);
            registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, &text, &wide, false);
        }
    }
    for ch in "ÐÞþ".chars() {
        let text = ch.to_string();
        registry.define_symbol(Mode::Math, SymbolGroup::MathOrdGroup, &text, &text, false);
        registry.define_symbol(Mode::Text, SymbolGroup::TextOrdGroup, &text, &text, false);
    }
    registry
}

static BUILTIN_SYMBOLS: OnceLock<SymbolRegistry> = OnceLock::new();

fn builtin_symbols() -> &'static SymbolRegistry {
    BUILTIN_SYMBOLS.get_or_init(build_builtin_symbols)
}

pub(crate) fn lookup_symbol(mode: Mode, name: &str) -> Option<&'static SymbolSpec> {
    let builtins = builtin_symbols();
    if mode == Mode::Math {
        builtins.math.get(name)
    } else {
        builtins.text.get(name)
    }
}

/// Returns a registered symbol's Unicode replacement, if it has one.
pub fn unicode_symbol(name: &str) -> Option<String> {
    let builtins = builtin_symbols();
    if let Some(symbol) = builtins.math.get(name)
        && !symbol.replacement.is_empty() {
            return Some(symbol.replacement.clone());
        }
    if let Some(symbol) = builtins.text.get(name)
        && !symbol.replacement.is_empty() {
            return Some(symbol.replacement.clone());
        }
    None
}

pub(crate) fn is_registered_symbol(name: &str) -> bool {
    let builtins = builtin_symbols();
    builtins.math.contains_key(name) || builtins.text.contains_key(name)
}