use std::collections::HashMap;
use std::sync::OnceLock;
use crate::tree::Class;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Symbol {
pub symbol: char,
pub class: Class,
}
const fn s(symbol: char, class: Class) -> Option<Symbol> {
Some(Symbol { symbol, class })
}
pub fn character(c: char) -> Option<Symbol> {
use Class::*;
match c {
'+' | '±' | '∓' | '×' | '÷' | '·' | '∗' | '∘' | '∪' | '∩' | '⊕' | '⊗' | '∧' | '∨' => s(c, Bin),
'-' | '−' | '–' => s('−', Bin),
'*' => s('∗', Bin),
'/' => s('/', Ord),
'=' | '<' | '>' | ':' | '≤' | '≥' | '≠' | '≈' | '≡' | '∼' | '≅' | '∝' | '→' | '←' | '↔' | '⇒' | '⇐' | '⇔' | '∈' | '∉' | '⊂' | '⊃' | '⊆' | '⊇' | '⇌' | '↑' | '↓' | '⟶'
| '∥' | '⊥' | '≃' | '≪' | '≫' => s(c, Rel),
'(' | '[' | '⟨' => s(c, Open),
')' | ']' | '⟩' | '!' | '?' => s(c, Close),
',' | ';' => s(c, Punct),
'.' | '|' | '\'' | '°' | '%' | '∞' | '∅' | '∂' | '∇' | '∀' | '∃' | '¬' | '△' | '∠' | '…' | '⋯' | '"' | '@' | '`' | '™' | '€' | '£' | '§' | '¶' | '•' | '★' | '✓' | '✗' => {
s(c, Ord)
}
_ => None,
}
}
const COMMANDS: &[(&str, char, Class)] = {
use Class::*;
&[
("cdot", '·', Bin),
("times", '×', Bin),
("div", '÷', Bin),
("pm", '±', Bin),
("mp", '∓', Bin),
("ast", '∗', Bin),
("star", '⋆', Bin),
("circ", '∘', Bin),
("bullet", '•', Bin),
("cup", '∪', Bin),
("cap", '∩', Bin),
("setminus", '∖', Bin),
("smallsetminus", '∖', Bin),
("oplus", '⊕', Bin),
("ominus", '⊖', Bin),
("otimes", '⊗', Bin),
("odot", '⊙', Bin),
("wedge", '∧', Bin),
("land", '∧', Bin),
("vee", '∨', Bin),
("lor", '∨', Bin),
("diamond", '⋄', Bin),
("bigcirc", '◯', Bin),
("triangleleft", '◁', Bin),
("triangleright", '▷', Bin),
("amalg", '⨿', Bin),
("uplus", '⊎', Bin),
("sqcup", '⊔', Bin),
("sqcap", '⊓', Bin),
("boxplus", '⊞', Bin),
("boxminus", '⊟', Bin),
("boxtimes", '⊠', Bin),
("boxdot", '⊡', Bin),
("circleddash", '⊝', Bin),
("circledast", '⊛', Bin),
("circledcirc", '⊚', Bin),
("bigtriangleup", '△', Bin),
("bigtriangledown", '▽', Bin),
("wr", '≀', Bin),
("intercal", '⊺', Bin),
("oslash", '⊘', Bin),
("ltimes", '⋉', Bin),
("rtimes", '⋊', Bin),
("leftthreetimes", '⋋', Bin),
("rightthreetimes", '⋌', Bin),
("barwedge", '⊼', Bin),
("veebar", '⊻', Bin),
("curlywedge", '⋏', Bin),
("curlyvee", '⋎', Bin),
("Cap", '⋒', Bin),
("doublecap", '⋒', Bin),
("Cup", '⋓', Bin),
("doublecup", '⋓', Bin),
("dotplus", '∔', Bin),
("divideontimes", '⋇', Bin),
("centerdot", '·', Bin),
("lhd", '⊲', Bin),
("rhd", '⊳', Bin),
("unlhd", '⊴', Bin),
("unrhd", '⊵', Bin),
("doublebarwedge", '⩞', Bin),
("le", '≤', Rel),
("leq", '≤', Rel),
("ge", '≥', Rel),
("geq", '≥', Rel),
("leqslant", '⩽', Rel),
("geqslant", '⩾', Rel),
("ne", '≠', Rel),
("neq", '≠', Rel),
("approx", '≈', Rel),
("coloneqq", '≔', Rel),
("coloneq", '≔', Rel),
("eqqcolon", '≕', Rel),
("eqcolon", '≕', Rel),
("Coloneqq", '⩴', Rel),
("equiv", '≡', Rel),
("sim", '∼', Rel),
("simeq", '≃', Rel),
("cong", '≅', Rel),
("propto", '∝', Rel),
("ll", '≪', Rel),
("gg", '≫', Rel),
("doteq", '≐', Rel),
("in", '∈', Rel),
("notin", '∉', Rel),
("ni", '∋', Rel),
("owns", '∋', Rel),
("subset", '⊂', Rel),
("supset", '⊃', Rel),
("subseteq", '⊆', Rel),
("supseteq", '⊇', Rel),
("subsetneq", '⊊', Rel),
("not\\subset", '⊈', Rel),
("nsubseteq", '⊈', Rel),
("perp", '⊥', Rel),
("parallel", '∥', Rel),
("nparallel", '∦', Rel),
("mid", '∣', Rel),
("nmid", '∤', Rel),
("models", '⊨', Rel),
("vdash", '⊢', Rel),
("asymp", '≍', Rel),
("prec", '≺', Rel),
("succ", '≻', Rel),
("triangleq", '≜', Rel),
("succeq", '⪰', Rel),
("preceq", '⪯', Rel),
("lesssim", '≲', Rel),
("gtrsim", '≳', Rel),
("lessgtr", '≶', Rel),
("vDash", '⊨', Rel),
("Vdash", '⊩', Rel),
("sqsubseteq", '⊑', Rel),
("sqsupseteq", '⊒', Rel),
("sqsubset", '⊏', Rel),
("sqsupset", '⊐', Rel),
("bowtie", '⋈', Rel),
("smile", '⌣', Rel),
("frown", '⌢', Rel),
("dashrightarrow", '⇢', Rel),
("dashleftarrow", '⇠', Rel),
("curvearrowright", '↷', Rel),
("curvearrowleft", '↶', Rel),
("hookleftarrow", '↩', Rel),
("twoheadrightarrow", '↠', Rel),
("twoheadleftarrow", '↞', Rel),
("rightrightarrows", '⇉', Rel),
("leftleftarrows", '⇇', Rel),
("circlearrowright", '↻', Rel),
("circlearrowleft", '↺', Rel),
("multimap", '⊸', Rel),
("dashv", '⊣', Rel),
("Join", '⨝', Rel),
("lessapprox", '⪅', Rel),
("gtrapprox", '⪆', Rel),
("lesseqgtr", '⋚', Rel),
("gtreqless", '⋛', Rel),
("gtrless", '≷', Rel),
("leqq", '≦', Rel),
("geqq", '≧', Rel),
("lll", '⋘', Rel),
("llless", '⋘', Rel),
("ggg", '⋙', Rel),
("gggtr", '⋙', Rel),
("divides", '∣', Rel),
("shortmid", '∣', Rel),
("shortparallel", '∥', Rel),
("vartriangleleft", '⊲', Rel),
("vartriangleright", '⊳', Rel),
("trianglelefteq", '⊴', Rel),
("trianglerighteq", '⊵', Rel),
("preccurlyeq", '≼', Rel),
("succcurlyeq", '≽', Rel),
("precsim", '≾', Rel),
("succsim", '≿', Rel),
("precapprox", '⪷', Rel),
("succapprox", '⪸', Rel),
("curlyeqprec", '⋞', Rel),
("curlyeqsucc", '⋟', Rel),
("eqslantless", '⪕', Rel),
("eqslantgtr", '⪖', Rel),
("lessdot", '⋖', Rel),
("gtrdot", '⋗', Rel),
("Vvdash", '⊪', Rel),
("VDash", '⊫', Rel),
("Subset", '⋐', Rel),
("Supset", '⋑', Rel),
("eqcirc", '≖', Rel),
("circeq", '≗', Rel),
("bumpeq", '≏', Rel),
("Bumpeq", '≎', Rel),
("thickapprox", '≈', Rel),
("thicksim", '∼', Rel),
("approxeq", '≊', Rel),
("backsim", '∽', Rel),
("backsimeq", '⋍', Rel),
("eqsim", '≂', Rel),
("risingdotseq", '≓', Rel),
("fallingdotseq", '≒', Rel),
("doteqdot", '≑', Rel),
("Doteq", '≑', Rel),
("between", '≬', Rel),
("pitchfork", '⋔', Rel),
("varpropto", '∝', Rel),
("smallsmile", '⌣', Rel),
("smallfrown", '⌢', Rel),
("supsetneq", '⊋', Rel),
("varsupsetneq", '⊋', Rel),
("varsubsetneq", '⊊', Rel),
("subsetneqq", '⫋', Rel),
("varsubsetneqq", '⫋', Rel),
("supsetneqq", '⫌', Rel),
("varsupsetneqq", '⫌', Rel),
("subseteqq", '⫅', Rel),
("supseteqq", '⫆', Rel),
("nless", '≮', Rel),
("ngtr", '≯', Rel),
("nleq", '≰', Rel),
("nleqslant", '≰', Rel),
("nleqq", '≰', Rel),
("ngeq", '≱', Rel),
("ngeqslant", '≱', Rel),
("ngeqq", '≱', Rel),
("lneq", '⪇', Rel),
("gneq", '⪈', Rel),
("lneqq", '≨', Rel),
("lvertneqq", '≨', Rel),
("gneqq", '≩', Rel),
("gvertneqq", '≩', Rel),
("lnsim", '⋦', Rel),
("gnsim", '⋧', Rel),
("lnapprox", '⪉', Rel),
("gnapprox", '⪊', Rel),
("nprec", '⊀', Rel),
("nsucc", '⊁', Rel),
("npreceq", '⋠', Rel),
("nsucceq", '⋡', Rel),
("precneqq", '⪵', Rel),
("succneqq", '⪶', Rel),
("precnsim", '⋨', Rel),
("succnsim", '⋩', Rel),
("precnapprox", '⪹', Rel),
("succnapprox", '⪺', Rel),
("nsim", '≁', Rel),
("ncong", '≇', Rel),
("nshortmid", '∤', Rel),
("nshortparallel", '∦', Rel),
("nvdash", '⊬', Rel),
("nvDash", '⊭', Rel),
("nVdash", '⊮', Rel),
("nVDash", '⊯', Rel),
("ntriangleleft", '⋪', Rel),
("ntriangleright", '⋫', Rel),
("ntrianglelefteq", '⋬', Rel),
("ntrianglerighteq", '⋭', Rel),
("nsupseteq", '⊉', Rel),
("nsupseteqq", '⊉', Rel),
("nsubseteqq", '⊈', Rel),
("nsubset", '⊄', Rel),
("nsupset", '⊅', Rel),
("nni", '∌', Rel),
("notni", '∌', Rel),
("nequiv", '≢', Rel),
("napprox", '≉', Rel),
("nsimeq", '≄', Rel),
("nasymp", '≭', Rel),
("nleftarrow", '↚', Rel),
("nrightarrow", '↛', Rel),
("nleftrightarrow", '↮', Rel),
("nLeftarrow", '⇍', Rel),
("nRightarrow", '⇏', Rel),
("nLeftrightarrow", '⇎', Rel),
("lt", '<', Rel),
("gt", '>', Rel),
("to", '→', Rel),
("rightarrow", '→', Rel),
("gets", '←', Rel),
("leftarrow", '←', Rel),
("leftrightarrow", '↔', Rel),
("Rightarrow", '⇒', Rel),
("implies", '⇒', Rel),
("Leftarrow", '⇐', Rel),
("impliedby", '⇐', Rel),
("Leftrightarrow", '⇔', Rel),
("iff", '⇔', Rel),
("longrightarrow", '⟶', Rel),
("longleftarrow", '⟵', Rel),
("longleftrightarrow", '⟷', Rel),
("Longrightarrow", '⟹', Rel),
("Longleftarrow", '⟸', Rel),
("Longleftrightarrow", '⟺', Rel),
("mapsto", '↦', Rel),
("longmapsto", '⟼', Rel),
("uparrow", '↑', Rel),
("downarrow", '↓', Rel),
("updownarrow", '↕', Rel),
("Uparrow", '⇑', Rel),
("Downarrow", '⇓', Rel),
("nearrow", '↗', Rel),
("searrow", '↘', Rel),
("nwarrow", '↖', Rel),
("swarrow", '↙', Rel),
("rightleftharpoons", '⇌', Rel),
("leftrightharpoons", '⇋', Rel),
("rightharpoonup", '⇀', Rel),
("leftharpoonup", '↼', Rel),
("rightleftarrows", '⇄', Rel),
("hookrightarrow", '↪', Rel),
("leadsto", '⇝', Rel),
("rightsquigarrow", '⇝', Rel),
("leftrightsquigarrow", '↭', Rel),
("leftrightarrows", '⇆', Rel),
("Lsh", '↰', Rel),
("Rsh", '↱', Rel),
("looparrowleft", '↫', Rel),
("looparrowright", '↬', Rel),
("rightarrowtail", '↣', Rel),
("leftarrowtail", '↢', Rel),
("upuparrows", '⇈', Rel),
("downdownarrows", '⇊', Rel),
("Lleftarrow", '⇚', Rel),
("Rrightarrow", '⇛', Rel),
("Updownarrow", '⇕', Rel),
("upharpoonright", '↾', Rel),
("restriction", '↾', Rel),
("upharpoonleft", '↿', Rel),
("downharpoonright", '⇂', Rel),
("downharpoonleft", '⇃', Rel),
("rightharpoondown", '⇁', Rel),
("leftharpoondown", '↽', Rel),
("colon", ':', Punct),
("lbrace", '{', Open),
("{", '{', Open),
("rbrace", '}', Close),
("}", '}', Close),
("langle", '⟨', Open),
("rangle", '⟩', Close),
("lfloor", '⌊', Open),
("rfloor", '⌋', Close),
("lceil", '⌈', Open),
("rceil", '⌉', Close),
("lvert", '|', Open),
("rvert", '|', Close),
("lVert", '‖', Open),
("rVert", '‖', Close),
("vert", '|', Ord),
("Vert", '‖', Ord),
("|", '‖', Ord),
("lbrack", '[', Open),
("llangle", '⟪', Open),
("rrangle", '⟫', Close),
("llbracket", '⟦', Open),
("lBrack", '⟦', Open),
("rrbracket", '⟧', Close),
("rBrack", '⟧', Close),
("rbrack", ']', Close),
("infty", '∞', Ord),
("partial", '∂', Ord),
("nabla", '∇', Ord),
("forall", '∀', Ord),
("exists", '∃', Ord),
("nexists", '∄', Ord),
("neg", '¬', Ord),
("lnot", '¬', Ord),
("emptyset", '∅', Ord),
("varnothing", '∅', Ord),
("angle", '∠', Ord),
("measuredangle", '∡', Ord),
("sphericalangle", '∢', Ord),
("Diamond", '◇', Ord),
("surd", '√', Ord),
("hslash", 'ℏ', Ord),
("triangledown", '▽', Ord),
("diagup", '╱', Ord),
("diagdown", '╲', Ord),
("backprime", '‵', Ord),
("Finv", 'Ⅎ', Ord),
("Bbbk", '𝕜', Ord),
("circledS", 'Ⓢ', Ord),
("standardstate", '⦵', Ord),
("stst", '⦵', Ord),
("triangle", '△', Ord),
("vartriangle", '△', Ord),
("square", '□', Ord),
("Box", '□', Ord),
("blacksquare", '■', Ord),
("degree", '°', Ord),
("prime", '′', Ord),
("hbar", 'ℏ', Ord),
("ell", 'ℓ', Ord),
("wp", '℘', Ord),
("Re", 'ℜ', Ord),
("Im", 'ℑ', Ord),
("aleph", 'ℵ', Ord),
("top", '⊤', Ord),
("bot", '⊥', Ord),
("dots", '…', Inner),
("ldots", '…', Inner),
("dotsc", '…', Inner),
("dotso", '…', Inner),
("cdots", '⋯', Inner),
("dotsb", '⋯', Inner),
("dotsm", '⋯', Inner),
("dotsi", '⋯', Inner),
("vdots", '⋮', Ord),
("ddots", '⋱', Inner),
("iddots", '⋰', Inner),
("adots", '⋰', Inner),
("hdots", '…', Inner),
("therefore", '∴', Rel),
("because", '∵', Rel),
("checkmark", '✓', Ord),
("S", '§', Ord),
("P", '¶', Ord),
("dag", '†', Bin),
("dagger", '†', Bin),
("ddag", '‡', Bin),
("ddagger", '‡', Bin),
("clubsuit", '♣', Ord),
("diamondsuit", '♢', Ord),
("heartsuit", '♡', Ord),
("spadesuit", '♠', Ord),
("flat", '♭', Ord),
("sharp", '♯', Ord),
("natural", '♮', Ord),
("%", '%', Ord),
("$", '$', Ord),
("&", '&', Ord),
("#", '#', Ord),
("_", '_', Ord),
("textbackslash", '\\', Ord),
("backslash", '\\', Ord),
("textdegree", '°', Ord),
("textdegreeC", '°', Ord),
("celsius", '℃', Ord),
("degreeCelsius", '℃', Ord),
("ohm", 'Ω', Ord),
("Omegaup", 'Ω', Ord),
("micro", 'µ', Ord),
("permil", '‰', Ord),
("textperthousand", '‰', Ord),
("euro", '€', Ord),
("texteuro", '€', Ord),
("yen", '¥', Ord),
("textcent", '¢', Ord),
("pounds", '£', Ord),
("textsterling", '£', Ord),
("copyright", '©', Ord),
("textcopyright", '©', Ord),
("textregistered", '®', Ord),
("textmu", 'µ', Ord),
("textless", '<', Rel),
("textgreater", '>', Rel),
("textepsilon", 'ε', Ord),
("Game", '⅁', Ord),
("complement", '∁', Ord),
("gimel", 'ℷ', Ord),
("beth", 'ℶ', Ord),
("daleth", 'ℸ', Ord),
("eth", 'ð', Ord),
("mho", '℧', Ord),
("bigstar", '★', Ord),
("blacktriangle", '▲', Ord),
("blacktriangledown", '▼', Ord),
("blacktriangleright", '▶', Ord),
("blacktriangleleft", '◀', Ord),
("lozenge", '◊', Ord),
("blacklozenge", '⧫', Ord),
("female", '♀', Ord),
("venus", '♀', Ord),
("male", '♂', Ord),
("mars", '♂', Ord),
("pentagon", '⬠', Ord),
("hexagon", '⬡', Ord),
("o", 'ø', Ord),
("O", 'Ø', Ord),
("AA", 'Å', Ord),
("aa", 'å', Ord),
("ss", 'ß', Ord),
("l", 'ł', Ord),
("smallint", '∫', Op),
]
};
type Table = (HashMap<&'static str, Symbol>, HashMap<char, Class>);
fn command_table() -> &'static Table {
static TABLE: OnceLock<Table> = OnceLock::new();
TABLE.get_or_init(|| {
let mut by_name = HashMap::new();
let mut by_char = HashMap::new();
for &(name, symbol, class) in COMMANDS {
by_name.entry(name).or_insert(Symbol { symbol, class });
by_char.entry(symbol).or_insert(class);
}
(by_name, by_char)
})
}
pub fn command(name: &str) -> Option<Symbol> {
command_table().0.get(name).copied()
}
pub fn class_of_char(c: char) -> Option<Class> {
character(c).map(|s| s.class).or_else(|| command_table().1.get(&c).copied())
}
pub fn greek(name: &str) -> Option<char> {
Some(match name {
"alpha" => 'α',
"beta" => 'β',
"gamma" => 'γ',
"delta" => 'δ',
"epsilon" => 'ϵ',
"varepsilon" => 'ε',
"zeta" => 'ζ',
"eta" => 'η',
"theta" => 'θ',
"vartheta" => 'ϑ',
"iota" => 'ι',
"kappa" => 'κ',
"lambda" => 'λ',
"mu" => 'μ',
"nu" => 'ν',
"xi" => 'ξ',
"omicron" => 'ο',
"pi" => 'π',
"varpi" => 'ϖ',
"rho" => 'ρ',
"varrho" => 'ϱ',
"sigma" => 'σ',
"varsigma" => 'ς',
"tau" => 'τ',
"upsilon" => 'υ',
"phi" => 'ϕ',
"varphi" => 'φ',
"chi" => 'χ',
"psi" => 'ψ',
"omega" => 'ω',
"Gamma" => 'Γ',
"Delta" => 'Δ',
"Theta" => 'Θ',
"Lambda" => 'Λ',
"Xi" => 'Ξ',
"Pi" => 'Π',
"Sigma" => 'Σ',
"Upsilon" => 'Υ',
"Phi" => 'Φ',
"Psi" => 'Ψ',
"Omega" => 'Ω',
"upmu" => 'μ',
"uppi" => 'π',
"upalpha" => 'α',
"upbeta" => 'β',
"updelta" => 'δ',
"upepsilon" => 'ε',
"uptheta" => 'θ',
"uplambda" => 'λ',
"upsigma" => 'σ',
"upomega" => 'ω',
"upphi" => 'φ',
"uprho" => 'ρ',
"uptau" => 'τ',
"upupsilon" => 'υ',
"upkappa" => 'κ',
"upeta" => 'η',
"upnu" => 'ν',
"upxi" => 'ξ',
"upchi" => 'χ',
"uppsi" => 'ψ',
"upzeta" => 'ζ',
"upiota" => 'ι',
"Nu" => 'Ν',
"Alpha" => 'Α',
"Beta" => 'Β',
"Epsilon" => 'Ε',
"Zeta" => 'Ζ',
"Eta" => 'Η',
"Iota" => 'Ι',
"Kappa" => 'Κ',
"Mu" => 'Μ',
"Omicron" => 'Ο',
"Rho" => 'Ρ',
"Tau" => 'Τ',
"Chi" => 'Χ',
"upgamma" => 'γ',
"digamma" => 'ϝ',
"Digamma" => 'Ϝ',
"varkappa" => 'ϰ',
_ => return None,
})
}
pub fn greek_upright(name: &str) -> bool {
name.starts_with("up") || name.chars().next().is_some_and(|c| c.is_ascii_uppercase())
}
pub fn function(name: &str) -> Option<(&'static str, bool)> {
Some(match name {
"sin" | "sen" => ("sin", false),
"cos" => ("cos", false),
"tan" | "tg" => ("tan", false),
"cot" | "cotg" => ("cot", false),
"sec" => ("sec", false),
"csc" | "cossec" | "cosec" => ("csc", false),
"arcsin" | "arcsen" => ("arcsin", false),
"arccos" => ("arccos", false),
"arctan" | "arctg" => ("arctan", false),
"sinh" | "senh" => ("sinh", false),
"cosh" => ("cosh", false),
"tanh" | "tgh" => ("tanh", false),
"coth" => ("coth", false),
"csch" => ("csch", false),
"sech" => ("sech", false),
"arccot" => ("arccot", false),
"arcsec" => ("arcsec", false),
"arccsc" => ("arccsc", false),
"log" => ("log", false),
"lg" => ("lg", false),
"ln" => ("ln", false),
"exp" => ("exp", false),
"arg" => ("arg", false),
"deg" => ("deg", false),
"dim" => ("dim", false),
"hom" => ("hom", false),
"ker" => ("ker", false),
"det" => ("det", true),
"gcd" | "mdc" => ("gcd", true),
"lcm" | "mmc" => ("lcm", true),
"max" => ("max", true),
"min" => ("min", true),
"sup" => ("sup", true),
"inf" => ("inf", true),
"lim" => ("lim", true),
"limsup" => ("lim sup", true),
"liminf" => ("lim inf", true),
"Pr" => ("Pr", true),
"argmax" => ("arg max", true),
"argmin" => ("arg min", true),
_ => return None,
})
}
pub fn large_operator(name: &str) -> Option<(char, bool)> {
Some(match name {
"sum" => ('∑', true),
"prod" => ('∏', true),
"coprod" => ('∐', true),
"bigcup" => ('⋃', true),
"bigcap" => ('⋂', true),
"bigoplus" => ('⨁', true),
"bigotimes" => ('⨂', true),
"bigodot" => ('⨀', true),
"bigvee" => ('⋁', true),
"bigwedge" => ('⋀', true),
"bigsqcup" => ('⨆', true),
"biguplus" => ('⨄', true),
"int" => ('∫', false),
"iint" => ('∬', false),
"iiint" => ('∭', false),
"oint" => ('∮', false),
"iiiint" => ('⨌', false),
"oiint" | "varoiint" => ('∯', false),
"oiiint" => ('∰', false),
"intclockwise" => ('∱', false),
"varointclockwise" => ('∲', false),
"ointctrclockwise" => ('∳', false),
"fint" => ('⨏', false),
"sqint" => ('⨖', false),
_ => return None,
})
}
pub fn delimiter_command(name: &str) -> Option<Option<char>> {
Some(Some(match name {
"{" | "lbrace" => '{',
"}" | "rbrace" => '}',
"langle" => '⟨',
"rangle" => '⟩',
"lfloor" => '⌊',
"rfloor" => '⌋',
"lceil" => '⌈',
"rceil" => '⌉',
"vert" | "lvert" | "rvert" | "mid" => '|',
"|" | "Vert" | "lVert" | "rVert" => '‖',
"lbrack" => '[',
"rbrack" => ']',
"llbracket" | "lBrack" => '⟦',
"rrbracket" | "rBrack" => '⟧',
"uparrow" => '↑',
"downarrow" => '↓',
"updownarrow" => '↕',
"backslash" => '\\',
_ => return None,
}))
}
pub fn delimiter_char(c: char) -> Option<Option<char>> {
match c {
'.' => Some(None),
'(' | ')' | '[' | ']' | '|' | '/' | '<' | '>' | '⟨' | '⟩' | '‖' => Some(Some(match c {
'<' => '⟨',
'>' => '⟩',
other => other,
})),
_ => None,
}
}
pub fn accent(name: &str) -> Option<(char, bool)> {
Some(match name {
"hat" => ('\u{0302}', false),
"widehat" => ('\u{0302}', true),
"check" => ('\u{030C}', false),
"widecheck" => ('\u{030C}', true),
"tilde" => ('\u{0303}', false),
"widetilde" => ('\u{0303}', true),
"bar" => ('\u{0304}', false),
"acute" => ('\u{0301}', false),
"grave" => ('\u{0300}', false),
"breve" => ('\u{0306}', false),
"dot" => ('\u{0307}', false),
"ddot" => ('\u{0308}', false),
"dddot" => ('\u{20DB}', false),
"ddddot" => ('\u{20DC}', false),
"mathring" => ('\u{030A}', false),
"Tilde" => ('\u{0303}', false),
"Hat" => ('\u{0302}', false),
"Bar" => ('\u{0304}', false),
"Vec" => ('\u{20D7}', false),
"Dot" => ('\u{0307}', false),
"Ddot" => ('\u{0308}', false),
"vec" => ('\u{20D7}', false),
"overrightarrow" => ('→', true),
"overleftarrow" => ('←', true),
"overleftrightarrow" => ('↔', true),
"overarc" | "wideparen" | "overparen" | "arc" => ('⏜', true),
"underparen" => ('⏝', true),
_ => return None,
})
}
pub fn text_accent(mark: char, letter: char) -> Option<char> {
let combining = text_combining(mark)?;
let base = if letter == 'i' { 'ı' } else { letter };
compose(base, combining).or_else(|| compose(letter, combining))
}
pub fn text_combining(mark: char) -> Option<char> {
Some(match mark {
'\'' => '\u{0301}',
'`' => '\u{0300}',
'^' => '\u{0302}',
'~' => '\u{0303}',
'"' => '\u{0308}',
'c' => '\u{0327}',
'=' => '\u{0304}',
'.' => '\u{0307}',
'u' => '\u{0306}',
'v' => '\u{030C}',
_ => return None,
})
}
fn compose(base: char, combining: char) -> Option<char> {
const TABLE: &[(char, char, char)] = &[
('a', '\u{0301}', 'á'),
('e', '\u{0301}', 'é'),
('ı', '\u{0301}', 'í'),
('i', '\u{0301}', 'í'),
('o', '\u{0301}', 'ó'),
('u', '\u{0301}', 'ú'),
('A', '\u{0301}', 'Á'),
('E', '\u{0301}', 'É'),
('I', '\u{0301}', 'Í'),
('O', '\u{0301}', 'Ó'),
('U', '\u{0301}', 'Ú'),
('a', '\u{0300}', 'à'),
('A', '\u{0300}', 'À'),
('a', '\u{0302}', 'â'),
('e', '\u{0302}', 'ê'),
('o', '\u{0302}', 'ô'),
('A', '\u{0302}', 'Â'),
('E', '\u{0302}', 'Ê'),
('O', '\u{0302}', 'Ô'),
('a', '\u{0303}', 'ã'),
('o', '\u{0303}', 'õ'),
('n', '\u{0303}', 'ñ'),
('A', '\u{0303}', 'Ã'),
('O', '\u{0303}', 'Õ'),
('u', '\u{0308}', 'ü'),
('o', '\u{0308}', 'ö'),
('a', '\u{0308}', 'ä'),
('U', '\u{0308}', 'Ü'),
('c', '\u{0327}', 'ç'),
('C', '\u{0327}', 'Ç'),
('e', '\u{0300}', 'è'),
('ı', '\u{0300}', 'ì'),
('o', '\u{0300}', 'ò'),
('u', '\u{0300}', 'ù'),
('ı', '\u{0302}', 'î'),
('u', '\u{0302}', 'û'),
('e', '\u{0308}', 'ë'),
('ı', '\u{0308}', 'ï'),
('a', '\u{0304}', 'ā'),
('e', '\u{0304}', 'ē'),
('ı', '\u{0304}', 'ī'),
('o', '\u{0304}', 'ō'),
('u', '\u{0304}', 'ū'),
('z', '\u{0307}', 'ż'),
('e', '\u{0307}', 'ė'),
('a', '\u{0306}', 'ă'),
('g', '\u{0306}', 'ğ'),
('s', '\u{030C}', 'š'),
('c', '\u{030C}', 'č'),
('z', '\u{030C}', 'ž'),
('e', '\u{030C}', 'ě'),
('r', '\u{030C}', 'ř'),
('n', '\u{030C}', 'ň'),
('S', '\u{030C}', 'Š'),
('C', '\u{030C}', 'Č'),
];
TABLE.iter().find(|(b, c, _)| *b == base && *c == combining).map(|(_, _, r)| *r)
}
pub fn unit(name: &str) -> Option<&'static str> {
Some(match name {
"meter" | "metre" => "m",
"second" => "s",
"gram" => "g",
"kilogram" => "kg",
"ampere" => "A",
"kelvin" => "K",
"mole" => "mol",
"candela" => "cd",
"newton" => "N",
"joule" => "J",
"watt" => "W",
"pascal" => "Pa",
"hertz" => "Hz",
"coulomb" => "C",
"volt" => "V",
"ohm" => "Ω",
"farad" => "F",
"tesla" => "T",
"weber" => "Wb",
"henry" => "H",
"siemens" => "S",
"liter" | "litre" => "L",
"hour" => "h",
"minute" => "min",
"day" => "d",
"degreeCelsius" | "celsius" => "°C",
"degree" => "°",
"electronvolt" => "eV",
"calorie" => "cal",
"bar" => "bar",
"atm" | "atmosphere" => "atm",
"percent" => "%",
"mmHg" => "mmHg",
"hectare" => "ha",
"tonne" => "t",
"angstrom" => "Å",
"radian" => "rad",
"steradian" => "sr",
"lumen" => "lm",
"lux" => "lx",
"becquerel" => "Bq",
"gray" => "Gy",
"sievert" => "Sv",
"katal" => "kat",
"dalton" => "Da",
"atomicmassunit" => "u",
"astronomicalunit" => "au",
"arcminute" => "′",
"arcsecond" => "″",
"bel" => "B",
"neper" => "Np",
"barn" => "b",
"knot" => "kn",
"nauticalmile" => "M",
"bit" => "bit",
"byte" => "B",
"molar" => "M",
"torr" => "Torr",
_ => return None,
})
}
pub fn prefix(name: &str) -> Option<&'static str> {
Some(match name {
"yotta" => "Y",
"zetta" => "Z",
"exa" => "E",
"peta" => "P",
"tera" => "T",
"giga" => "G",
"mega" => "M",
"kilo" => "k",
"hecto" => "h",
"deca" | "deka" => "da",
"deci" => "d",
"centi" => "c",
"milli" => "m",
"micro" => "µ",
"nano" => "n",
"pico" => "p",
"femto" => "f",
"atto" => "a",
"zepto" => "z",
"yocto" => "y",
_ => return None,
})
}