diff --git a/README.md b/README.md index a86643b..4d5350f 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@ py_asciimath is a simple yet powerful Python module that: -* converts an ASCIIMath string to LaTeX or MathML +* converts an ASCIIMath ex to LaTeX or MathML +* converts a LaTeX mathematical expression to ASCIIMath (soon also to MathML) * converts a MathML string to LaTeX (the conversion is done thank to the [XSLT MathML Library](https://sourceforge.net/projects/xsltml/). Please report any unexpected behavior) * exposes a single translation method `translate(exp, **kwargs)`, which semantic depends on the py_asciimath translator one wish to use * exposes a MathML parser @@ -36,6 +37,7 @@ from py_asciimath.translator.translator import ( ASCIIMath2MathML, ASCIIMath2Tex, MathML2Tex, + Tex2ASCIIMath ) @@ -68,6 +70,14 @@ if __name__ == "__main__": from_file=False, pprint=False, ) + + print(parsed, "\n\nLaTeX to ASCIIMath") + tex2asciimath = Tex2ASCIIMath(log=False, inplace=True) + parsed = tex2asciimath.translate( + parsed, + from_file=False, + pprint=False, + ) print(parsed) ``` @@ -113,7 +123,11 @@ $ {\displaystyle {e}^{x}>0\forall x\in \mathbb{R} }$ ASCIIMath to LaTeX INFO:Translating... -\[e^{x} > 0 \forall x \in \mathbb{R}\] +\[{e}^{x} > 0 \forall x \in \mathbb{R}\] + +LaTeX to ASCIIMath +INFO:Translating... +(e)^(x) > 0 AA x in RR ``` #### From the command line @@ -144,12 +158,12 @@ Usage: Options: --dstyle Add display style -i --input=ILANG Input language - Supported input language: asciimath, mathml + Supported input language: asciimath, latex, mathml --log Log the transformation process --network Works only with ILANG=mathnml or OLANG=mathml Use network to validate XML against DTD -o --output=OLANG Output language - Supported output language: latex, mathml + Supported output language: asciimath, latex, mathml --pprint Works only with OLANG=mathml. Pretty print --to-file=OPATH Save translation to OPATH file --version Show version @@ -222,7 +236,7 @@ $e^{x} > 0 \forall x \in \mathbb{R}$ ## ASCIIMath grammar -The grammar used to parse the input is: +The grammar used to parse an ASCIIMath input is: ``` start: i start* -> exp @@ -248,7 +262,42 @@ asciimath: {} // asciimath symbols QS: "\"" /(?<=").+(?=")/ "\"" // Quoted String ``` -For the complete list of symbols, please refer to http://asciimath.org/##syntax. The only symbol that I've added is `dstyle`, that stands for `displaystyle` as a unary function. +For the complete list of symbols, please refer to http://asciimath.org/#syntax. The only symbol that I've added is `dstyle`, that stands for `displaystyle` as a unary function. + +## LaTeX grammar + +The grammar used to parse a LaTeX input is: + +``` +start: "\[" exp "\]" -> exp + | "$$" exp "$$" -> exp + | "$" exp "$" -> exp + | exp -> exp +exp: i exp* -> exp +i: s -> exp_interm + | s "_" s -> exp_under + | s "^" s -> exp_super + | s "_" s "^" s -> exp_under_super +s: l exp? r -> exp_par + | "\left" (l | "." | "\vert" | "\mid") start? "\right" (r | "." | "\vert" | "\mid") -> exp_par + | "\begin{matrix}" row_mat ("\\" row_mat?)* "\end{matrix}" -> exp_mat + | "{" i+ "}" -> exp + | u "{" exp "}" -> exp_unary + | b "{" exp "}" "{" exp "}" -> exp_binary + | "\sqrt" "[" i+ "]" "{{" exp "}}" -> exp_binary + | latex -> symbol + | c -> const +c: NUMBER + | LETTER +row_mat: exp ("&" exp?)* -> row_mat +l: "(" | "[" | "\{" | "\langle" | "\lVert" // left parenthesis +r: ")" | "]" | "\}" | "\rangle" | "\rVert" // right parenthesis +b: {} // binary functions +u: {} // unary functions +latex: {} // LaTeX symbols +``` + +Be careful that not all the LaTeX symbols are included in the grammar: please fill in an issue if you find that some symbols are missing ## Rendering (matrices and systems of equations) diff --git a/docs/source/_static/images/py_asciimath_translations.drawio b/docs/source/_static/images/py_asciimath_translations.drawio index 8a0bd64..a80133d 100644 --- a/docs/source/_static/images/py_asciimath_translations.drawio +++ b/docs/source/_static/images/py_asciimath_translations.drawio @@ -1 +1 @@ -3Zldb5swFIZ/TaTtYhHgQMJlm2ZrpVaqlEpLLz1wwZvBkXG+9utng/kwJmmX0KZtLirOsX2w3/McG+gATJPtDwaX8R0NERk4VrgdgKuB40y8ifgrHbvCMfKcwhExHBYuu3bM8V+knJbyrnCIMq0jp5RwvNSdAU1TFHDNBxmjG73bEyX6XZcwQoZjHkBien/ikMdqWa5V+68RjuLyzralWhJYdlaOLIYh3TRcYDYAU0YpL66S7RQRqV2pSzHu+57WamIMpfwlA9ZObM9CfBNf+/4u5g/bVTr7pqKsIVmpBV/Mpzc3d3Lyxaz5rpRChBOqC+NyE2OO5ksYyJaNyLvwxTwhwrLFpYqJGEfbvZO1KwkEOogmiLOd6KIGgFJghY3tKXtTJ8EulY0bCZgoH1R5j6rQtTTiQqnzH0q5ph6hIEWZlPGYRjSFZFZ7LxldpSGSUS1h1X1uKV0qrX4jzncKe7jitEtJeaPDOop50RUL0IH5q7LjkEWIH+gHuvPCEIEcr/V59C6yY+AoSby7PSuL9lhnsWLsbCwCQ6Zb+IAWZ1XJBe9NpfIIachkKpSGF/KUEFZAYJbhQBcGbTFfNK4fZS0PXWVdbVVp58auNFIx+0XdUZqPzbZ6WG6V43os9vKkPLLYGylzOzJW+l68J6g73FMsFlIRM7J1Yiq7DFEsU41qnmztQJ4eCHitQIUORqCcqmrZJ4BmnqJHg2Z9TtCcs4I2aW1Nx4LmWa1A/huDZp6PBmjBiq3zR46cqueoqwkajZwmQ/bQssEzHOXWPWJYrAuxBqELDd7HBuLdIGec0T9oSgll+SKAlf9ESwizuFpNj9yCD8HtuTdIwQ7cNbotZYfswIS97gnXZVBE7LcozKehnorC1jbVeo/dVw6d5FsflPw9T3tvQ357owXjI8l3ABhawK9/Xiuu3dncc124vr4c23+Luhid/lSyH8+XEnk2gowz3x+6xzE0br//maFe+9x3T0+ltp98oryO/Z6y2g702jn1jJxyBtNMqIMyuUFTI8Xi5Zwfqs+UpvJd/wkT0nJBgqNUkiGSKJ/ULuWrPg4guVANCQ5Dsu9Dgf4Za3D6t4J2Esv9sMnQuIMhx9qPy2mfCsbPJ8MjUvxfTFxF8upLiNaI0GUiFv31FXJF0BN/d5lyRr6RqUk/mRJm/TG8qLL6Pwpg9g8= \ No newline at end of file +3Zldb9owFIZ/DdJ2MZTEJJDLlrK2UitVotLg0kvcxJuJkWO+9utnJ86HY6AsQGHlovI5dk7s9zzHTtIOGM7W9wzO42caItJxrHDdAXcdxxl4A/FXOja5o+f3ckfEcJi77Moxxn+QclrKu8AhSrWBnFLC8Vx3BjRJUMA1H2SMrvRhb5Tod53DCBmOcQCJ6f2BQx6rZblW5X9AOIqLO9uW6pnBYrBypDEM6armAqMOGDJKed6arYeISO0KXfLrvu/oLSfGUMIPuWDpxPYoxI/xg+9vYv66XiSjbyrKEpKFWvDNePj4+Cwnn8+abwopRDihujBuVzHmaDyHgexZibwLX8xnRFi2aJozK26DGEfrmkvN9B7RGeJsI4aoXlAIrLCxPWWvqiTYhbJxLQED5YMq71EZupJGNJQ6/6CUa+oRClKUSRmPaUQTSEaV95bRRRIiGdUSVjXmidK50uoX4nyjsIcLTg9UMqULFqA903VUrUAWIb5nHMjHybXszQtDBHK81Kvi5CI7Bo6SxOeni7Jo93UWS8YuxiIwZHqCr2hyUZVccG0qFUdITSZToSS8kaeEsAIC0xQHujBojfmk1p7KWu66yrpbq9LOjE1hJGL2k2qgNKf1vuqyzCqua1/sxcF4qmKvpczdkrHCd/CeoO7wQrFYWUlMz9aJKe0iRL5udVX9ZGsG8vRAwGsEyoUxAmVUlcs+AjTzFG0NmvUpQHOuC7RBY2tqC5pnNQL5HwyaeT4aoAULtsweOTKq3qOuIqjXc+oM2V3LBu9wlFkviGGxLsRqhE40eKc1xLeDnHJGf6MhJZRliwBW9hM9IUzjcjXtuQX/J7eX3iAFO3BTGzaXA9I9E/a2T7gqgzziaYvCfBo6UVHY2qZa7bG7ymEr+VZL8s8Pu31VsDf3VtBvCbsDQNcCfvXzGnHtrd0nLgXX15dj+x9RCr3jH0RaEHktBBnHvN912zHUb77ymaHOfdS7x6dSOzw/UV77/omy2gx07px6Rk45g0kq1EGp3LGpkWLx8s331WdCE/l6/4YJabggwVEiyRBZlQ9nt/JVHgeQ3KiOGQ5DsuvbgP7laichh38eaCax2A/rDPW3MORYu3E57utA//1keESK/5OJViRbX0K0RITOZ0KHr2fIFUFv/Ooy5fR8I1OD02RKmNX377zKqn8igNFf \ No newline at end of file diff --git a/docs/source/_static/images/py_asciimath_translations.png b/docs/source/_static/images/py_asciimath_translations.png index e8571d7..60c041f 100644 Binary files a/docs/source/_static/images/py_asciimath_translations.png and b/docs/source/_static/images/py_asciimath_translations.png differ diff --git a/examples/example2.py b/examples/example2.py index 4ccd4a8..dc1036a 100644 --- a/examples/example2.py +++ b/examples/example2.py @@ -2,6 +2,7 @@ ASCIIMath2MathML, ASCIIMath2Tex, MathML2Tex, + Tex2ASCIIMath ) @@ -34,4 +35,12 @@ from_file=False, pprint=False, ) + + print(parsed, "\n\nLaTeX to ASCIIMath") + tex2asciimath = Tex2ASCIIMath(log=False, inplace=True) + parsed = tex2asciimath.translate( + parsed, + from_file=False, + pprint=False, + ) print(parsed) diff --git a/py_asciimath/asciimath.py b/py_asciimath/asciimath.py new file mode 100644 index 0000000..74c9b7a --- /dev/null +++ b/py_asciimath/asciimath.py @@ -0,0 +1,442 @@ +import sys + + +def get_symbols_for(symbol_group, lang_to): # pragma: no cover + return { + k: ( + None + if lang_to is None + else ( + v[lang_to] + if not isinstance(v[lang_to], list) + else v[lang_to][0] + ) + ) + for k, v in getattr(sys.modules[__name__], symbol_group).items() + } + + +binary_functions = { + "frac": {"latex": "\\frac", "mathml": "{}{}"}, + "root": {"latex": "\\sqrt", "mathml": "{}{}"}, + "stackrel": {"latex": "\\stackrel", "mathml": "{}{}"}, + "overset": {"latex": "\\overset", "mathml": "{}{}"}, + "underset": {"latex": "\\underset", "mathml": "{}{}"}, + "color": { + "latex": "\\textcolor", + "mathml": "{}", + }, +} + +unary_functions = { + "sqrt": {"latex": "\\sqrt", "mathml": "{}"}, + "text": {"latex": "\\textrm", "mathml": "{}"}, + "abs": {"latex": "abs", "mathml": "|{}|"}, + "floor": { + "latex": "floor", + "mathml": "{}", + }, + "ceil": {"latex": "ceil", "mathml": "{}"}, + "norm": { + "latex": "norm", + "mathml": "{}", + }, + "ubrace": { + "latex": "\\underbrace", + "mathml": "{}", + }, + "underbrace": { + "latex": "\\underbrace", + "mathml": "{}", + }, + "obrace": { + "latex": "\\overbrace", + "mathml": "{}", + }, + "overbrace": { + "latex": "\\overbrace", + "mathml": "{}", + }, + "cancel": { + "latex": "\\cancel", + "mathml": "{}", + }, + "bb": { + "latex": "\\boldsymbol", + "mathml": "{}", + }, + "bbb": { + "latex": "\\mathbb", + "mathml": "{}", + }, + "cc": { + "latex": "\\mathcal", + "mathml": "{}", + }, + "tt": { + "latex": "\\texttt", + "mathml": "{}", + }, + "fr": { + "latex": "\\mathfrak", + "mathml": "{}", + }, + "sf": { + "latex": "\\textsf", + "mathml": "{}", + }, + "ul": { + "latex": "\\underline", + "mathml": "{}̲", + }, + "underline": { + "latex": "\\underline", + "mathml": "{}̲", + }, + "bar": { + "latex": "\\overline", + "mathml": "{}̲", + }, + "overline": { + "latex": "\\overline", + "mathml": "{}̲", + }, + "hat": {"latex": "\\hat", "mathml": "{}^"}, + "vec": { + "latex": "\\vec", + "mathml": "{}", + }, + "dot": { + "latex": "\\dot", + "mathml": "{}.", + }, + "ddot": { + "latex": "\\ddot", + "mathml": "{}..", + }, + "dstyle": { + "latex": "\\displaystyle", + "mathml": "{}", + }, +} + +operation_symbols = { + "+": {"latex": "+", "mathml": "+"}, + "*": {"latex": "\\cdot", "mathml": "⋅"}, + "-": {"latex": "-", "mathml": "-"}, + "cdot": {"latex": "\\cdot", "mathml": "⋅"}, + "**": {"latex": "\\ast", "mathml": "*"}, + "ast": {"latex": "\\ast", "mathml": "*"}, + "***": {"latex": "\\star", "mathml": "⋆"}, + "star": {"latex": "\\star", "mathml": "⋆"}, + "//": {"latex": "/", "mathml": "/"}, + r"\\": {"latex": "\\setminus", "mathml": "∖"}, + "setminus": {"latex": "\\setminus", "mathml": "∖"}, + "xx": {"latex": "\\times", "mathml": "×"}, + "times": {"latex": "\\times", "mathml": "×"}, + "-:": {"latex": "\\div", "mathml": "÷"}, + "div": {"latex": "\\div", "mathml": "÷"}, + "|><": {"latex": "\\ltimes", "mathml": "⋉"}, + "ltimes": {"latex": "\\ltimes", "mathml": "⋉"}, + "><|": {"latex": "\\rtimes", "mathml": "⋊"}, + "rtimes": {"latex": "\\rtimes", "mathml": "⋊"}, + "|><|": {"latex": "\\bowtie", "mathml": "⋈"}, + "bowtie": {"latex": "\\bowtie", "mathml": "⋈"}, + "@": {"latex": "\\circ", "mathml": "∘"}, + "circ": {"latex": "\\circ", "mathml": "∘"}, + "o+": {"latex": "\\oplus", "mathml": "⊕"}, + "oplus": {"latex": "\\oplus", "mathml": "⊕"}, + "ox": {"latex": "\\otimes", "mathml": "×"}, + "otimes": {"latex": "\\otimes", "mathml": "×"}, + "o.": {"latex": "\\odot", "mathml": "⊙"}, + "odot": {"latex": "\\odot", "mathml": "⊙"}, + "sum": {"latex": "\\sum", "mathml": "∑"}, + "prod": {"latex": "\\prod", "mathml": "∏"}, + "^^": {"latex": "\\wedge", "mathml": "∧"}, + "wedge": {"latex": "\\wedge", "mathml": "∧"}, + "^^^": {"latex": "\\bigwedge", "mathml": "⋀"}, + "bigwedge": {"latex": "\\bigwedge", "mathml": "⋀"}, + "vv": {"latex": "\\vee", "mathml": "∨"}, + "vee": {"latex": "\\vee", "mathml": "∨"}, + "vvv": {"latex": "\\bigvee", "mathml": "⋁"}, + "bigvee": {"latex": "\\bigvee", "mathml": "⋁"}, + "nn": {"latex": "\\cap", "mathml": "∩"}, + "cap": {"latex": "\\cap", "mathml": "∩"}, + "nnn": {"latex": "\\bigcap", "mathml": "⋂"}, + "bigcap": {"latex": "\\bigcap", "mathml": "⋂"}, + "uu": {"latex": "\\cup", "mathml": "∪"}, + "cup": {"latex": "\\cup", "mathml": "∪"}, + "uuu": {"latex": "\\bigcup", "mathml": "⋃"}, + "bigcup": {"latex": "\\bigcup", "mathml": "⋃"}, +} + +logical_symbols = { + "and": {"latex": "\\mathmr{and}", "mathml": "and"}, + "or": {"latex": "\\mathmr{and}", "mathml": "or"}, + "not": {"latex": "\\neg", "mathml": "¬"}, + "neg": {"latex": "\\neg", "mathml": "¬"}, + "=>": {"latex": "\\implies", "mathml": "⇒"}, + "implies": {"latex": "\\implies", "mathml": "⇒"}, + "if": {"latex": "\\mathmr{if}", "mathml": "if"}, + "<=>": {"latex": "\\iff", "mathml": "⇔"}, + "iff": {"latex": "\\iff", "mathml": "⇔"}, + "AA": {"latex": "\\forall", "mathml": "∀"}, + "forall": {"latex": "\\forall", "mathml": "∀"}, + "EE": {"latex": "\\exists", "mathml": "∃"}, + "exists": {"latex": "\\exists", "mathml": "∃"}, + "_|_": {"latex": "\\bot", "mathml": "⊥"}, + "bot": {"latex": "\\bot", "mathml": "⊥"}, + "TT": {"latex": "\\top", "mathml": "⊤"}, + "top": {"latex": "\\top", "mathml": "⊤"}, + "|--": {"latex": "\\vdash", "mathml": "⊢"}, + "vdash": {"latex": "\\vdash", "mathml": "⊢"}, + "|==": {"latex": "\\models", "mathml": "⊨"}, + "models": {"latex": "\\models", "mathml": "⊨"}, +} + +relation_symbols = { + "=": {"latex": "=", "mathml": "="}, + "!=": {"latex": "\\ne", "mathml": "≠"}, + "ne": {"latex": "\\ne", "mathml": "≠"}, + "<": {"latex": "<", "mathml": "<"}, + "lt": {"latex": "<", "mathml": "<"}, + ">": {"latex": ">", "mathml": ">"}, + "gt": {"latex": ">", "mathml": ">"}, + "<=": {"latex": "\\le", "mathml": "≤"}, + "le": {"latex": "\\le", "mathml": "≤"}, + ">=": {"latex": "\\ge", "mathml": "≥"}, + "ge": {"latex": "\\ge", "mathml": "≥"}, + "-<": {"latex": "\\prec", "mathml": "≺"}, + "prec": {"latex": "\\prec", "mathml": "≺"}, + "-<=": {"latex": "\\preceq", "mathml": "⪯"}, + "preceq": {"latex": "\\preceq", "mathml": "⪯"}, + ">-": {"latex": "\\succ", "mathml": "≻"}, + "succ": {"latex": "\\succ", "mathml": "≻"}, + ">-=": {"latex": "\\succeq", "mathml": "⪰"}, + "succeq": {"latex": "\\succeq", "mathml": "⪰"}, + "in": {"latex": "\\in", "mathml": "∈"}, + "!in": {"latex": "\\notin", "mathml": "∉"}, + "notin": {"latex": "\\notin", "mathml": "∉"}, + "sub": {"latex": "\\subset", "mathml": "⊂"}, + "subset": {"latex": "\\subset", "mathml": "⊂"}, + "sup": {"latex": "\\supset", "mathml": "⊃"}, + "supset": {"latex": "\\supset", "mathml": "⊃"}, + "sube": {"latex": "\\subseteq", "mathml": "⊆"}, + "subseteq": {"latex": "\\subseteq", "mathml": "⊆"}, + "supe": {"latex": "\\supseteq", "mathml": "⊇"}, + "supseteq": {"latex": "\\supseteq", "mathml": "⊇"}, + "-=": {"latex": "\\equiv", "mathml": "≡"}, + "equiv": {"latex": "\\equiv", "mathml": "≡"}, + "~=": {"latex": "\\cong", "mathml": "≅"}, + "cong": {"latex": "\\cong", "mathml": "≅"}, + "~~": {"latex": "\\approx", "mathml": "≈"}, + "approx": {"latex": "\\approx", "mathml": "≈"}, + "prop": {"latex": "\\propto", "mathml": "∝"}, + "propto": {"latex": "\\propto", "mathml": "∝"}, +} + +function_symbols = { + "sin": {"latex": "\\sin", "mathml": "sin"}, + "cos": {"latex": "\\cos", "mathml": "cos"}, + "tan": {"latex": "\\tan", "mathml": "tan"}, + "sec": {"latex": "\\sec", "mathml": "sec"}, + "csc": {"latex": "\\csc", "mathml": "csc"}, + "cot": {"latex": "\\cot", "mathml": "cot"}, + "arcsin": {"latex": "\\arcsin", "mathml": "arcsin"}, + "arccos": {"latex": "\\arccos", "mathml": "arccos"}, + "arctan": {"latex": "\\arctan", "mathml": "arctan"}, + "sinh": {"latex": "\\sinh", "mathml": "sinh"}, + "cosh": {"latex": "\\cosh", "mathml": "cosh"}, + "tanh": {"latex": "\\tanh", "mathml": "tanh"}, + "sech": {"latex": "\\sech", "mathml": "sech"}, + "csch": {"latex": "\\csch", "mathml": "csch"}, + "coth": {"latex": "\\coth", "mathml": "coth"}, + "exp": {"latex": "\\exp", "mathml": "exp"}, + "log": {"latex": "\\log", "mathml": "log"}, + "ln": {"latex": "\\ln", "mathml": "ln"}, + "det": {"latex": "\\det", "mathml": "det"}, + "dim": {"latex": "\\dim", "mathml": "dim"}, + "mod": {"latex": "\\mod", "mathml": "mod"}, + "gcd": {"latex": "\\gcd", "mathml": "gcd"}, + "lcm": {"latex": "\\lcm", "mathml": "lcm"}, + "lub": {"latex": "\\lub", "mathml": "lub"}, + "glb": {"latex": "\\glb", "mathml": "glb"}, + "min": {"latex": "\\min", "mathml": "min"}, + "max": {"latex": "\\max", "mathml": "max"}, + "lim": {"latex": "\\lim", "mathml": "lim"}, + "f": {"latex": "f", "mathml": "f"}, + "g": {"latex": "g", "mathml": "g"}, +} + +greek_letters = { + "alpha": {"latex": "\\alpha", "mathml": "α"}, + "beta": {"latex": "\\beta", "mathml": "β"}, + "gamma": {"latex": "\\gamma", "mathml": "γ"}, + "Gamma": {"latex": "\\Gamma", "mathml": "Γ"}, + "delta": {"latex": "\\delta", "mathml": "δ"}, + "Delta": {"latex": "\\Delta", "mathml": "Δ"}, + "epsilon": {"latex": "\\epsilon", "mathml": "ϵ"}, + "varepsilon": {"latex": "\\varepsilon", "mathml": "ϵ"}, + "zeta": {"latex": "\\zeta", "mathml": "ζ"}, + "eta": {"latex": "\\eta", "mathml": "η"}, + "theta": {"latex": "\\theta", "mathml": "θ"}, + "Theta": {"latex": "\\Theta", "mathml": "Θ"}, + "vartheta": {"latex": "\\vartheta", "mathml": "ϑ"}, + "iota": {"latex": "\\iota", "mathml": "ι"}, + "kappa": {"latex": "\\kappa", "mathml": "κ"}, + "lambda": {"latex": "\\lambda", "mathml": "λ"}, + "Lambda": {"latex": "\\Lambda", "mathml": "Λ"}, + "mu": {"latex": "\\mu", "mathml": "μ"}, + "nu": {"latex": "\\nu", "mathml": "ν"}, + "xi": {"latex": "\\xi", "mathml": "ξ"}, + "Xi": {"latex": "\\Xi", "mathml": "Ξ"}, + "pi": {"latex": "\\pi", "mathml": "π"}, + "Pi": {"latex": "\\Pi", "mathml": "Π"}, + "rho": {"latex": "\\rho", "mathml": "ρ"}, + "sigma": {"latex": "\\sigma", "mathml": "σ"}, + "Sigma": {"latex": "\\Sigma", "mathml": "Σ"}, + "tau": {"latex": "\\tau", "mathml": "τ"}, + "upsilon": {"latex": "\\upsilon", "mathml": "υ"}, + "phi": {"latex": "\\phi", "mathml": "φ"}, + "Phi": {"latex": "\\Phi", "mathml": "Φ"}, + "varphi": {"latex": "\\varphi", "mathml": "ϕ"}, + "chi": {"latex": "\\chi", "mathml": "χ"}, + "psi": {"latex": "\\psi", "mathml": "ψ"}, + "Psi": {"latex": "\\Psi", "mathml": "Ψ"}, + "omega": {"latex": "\\omega", "mathml": "ω"}, + "Omega": {"latex": "\\Omega", "mathml": "Ω"}, +} + +left_parenthesis = { + "(:": {"latex": "\\langle", "mathml": "⟨"}, + "(": {"latex": "(", "mathml": "("}, + "[": {"latex": "[", "mathml": "["}, + "{:": {"latex": ".", "mathml": ""}, + "{": {"latex": "\\{", "mathml": "{"}, + "|:": {"latex": "\\vert", "mathml": "∣"}, + "||:": {"latex": "\\lVert", "mathml": "∥"}, + "langle": {"latex": "\\langle", "mathml": "⟨"}, + "<<": {"latex": "\\langle", "mathml": "⟨"}, +} + +right_parenthesis = { + ":)": {"latex": "\\rangle", "mathml": "⟩"}, + ")": {"latex": ")", "mathml": ")"}, + "]": {"latex": "]", "mathml": "]"}, + ":}": {"latex": ".", "mathml": ""}, + "}": {"latex": "\\}", "mathml": "}"}, + ":|": {"latex": "\\vert", "mathml": "∣"}, + ":||": {"latex": "\\rVert", "mathml": "∥"}, + "rangle": {"latex": "\\rangle", "mathml": "⟩"}, + ">>": {"latex": "\\rangle", "mathml": "⟩"}, +} + +arrows = { + "uarr": {"latex": "\\uparrow", "mathml": "↑"}, + "uparrow": {"latex": "\\uparrow", "mathml": "↑"}, + "darr": {"latex": "\\downarrow", "mathml": "↓"}, + "downarrow": {"latex": "\\downarrow", "mathml": "↓"}, + "rarr": {"latex": "\\rightarrow", "mathml": "→"}, + "rArr": {"latex": "\\Rightarrow", "mathml": "⇒"}, + "rightarrow": {"latex": "\\rightarrow", "mathml": "→"}, + "->": {"latex": "\\to", "mathml": "→"}, + "to": {"latex": "\\to", "mathml": "→"}, + ">->": {"latex": "\\rightarrowtail", "mathml": "↣"}, + "rightarrowtail": { + "latex": "\\rightarrowtail", + "mathml": "↣", + }, + "->>": {"latex": "\\twoheadrightarrow", "mathml": "↠"}, + "twoheadrightarrow": { + "latex": "\\twoheadrightarrow", + "mathml": "↠", + }, + ">->>": {"latex": "\\twoheadrightarrowtail", "mathml": "⤖"}, + "twoheadrightarrowtail": { + "latex": "\\twoheadrightarrowtail", + "mathml": "⤖", + }, + "|->": {"latex": "\\mapsto", "mathml": "↦"}, + "mapsto": {"latex": "\\mapsto", "mathml": "↦"}, + "larr": {"latex": "\\leftarrow", "mathml": "←"}, + "leftarrow": {"latex": "\\leftarrow", "mathml": "←"}, + "harr": {"latex": "\\leftrightarrow", "mathml": "↔"}, + "leftrightarrow": { + "latex": "\\leftrightarrow", + "mathml": "↔", + }, + "lArr": {"latex": "\\Leftarrow", "mathml": "⇐"}, + "Leftarrow": {"latex": "\\Leftarrow", "mathml": "⇐"}, + "hArr": {"latex": "\\Leftrightarrow", "mathml": "⇔"}, + "Leftrightarrow": { + "latex": "\\Leftrightarrow", + "mathml": "⇔", + }, +} + +colors = { + "red": {"latex": "red", "mathml": "red"}, +} + +misc_symbols = { + "^": {"latex": "^", "mathml": "^"}, + ",": {"latex": ",", "mathml": ","}, + ".": {"latex": ".", "mathml": "."}, + "_": {"latex": "_", "mathml": "_"}, + "'": {"latex": "'", "mathml": "'"}, + "/": {"latex": "/", "mathml": "/"}, + "|": {"latex": ["|", "\\vert", "\\mid"], "mathml": "|"}, + ":": {"latex": ":", "mathml": ":"}, + "int": {"latex": "\\int", "mathml": "∫"}, + "integral": {"latex": "\\int", "mathml": "∫"}, + "oint": {"latex": "\\oint", "mathml": "∮"}, + "del": {"latex": "\\partial", "mathml": "∂"}, + "partial": {"latex": "\\partial", "mathml": "∂"}, + "grad": {"latex": "\\nabla", "mathml": "∇"}, + "nabla": {"latex": "\\nabla", "mathml": "∇"}, + "+-": {"latex": "\\pm", "mathml": "±"}, + "pm": {"latex": "\\pm", "mathml": "±"}, + "O/": {"latex": "\\emptyset", "mathml": "∅"}, + "emptyset": {"latex": "\\emptyset", "mathml": "∅"}, + "oo": {"latex": "\\infty", "mathml": "∞"}, + "infty": {"latex": "\\infty", "mathml": "∞"}, + "aleph": {"latex": "\\aleph", "mathml": "ℵ"}, + ":.": {"latex": "\\therefore", "mathml": "∴"}, + "therefore": {"latex": "\\therefore", "mathml": "∴"}, + ":'": {"latex": "\\because", "mathml": "∵"}, + "because": {"latex": "\\because", "mathml": "∵"}, + "...": {"latex": "\\ldots", "mathml": "..."}, + "ldots": {"latex": "\\ldots", "mathml": "..."}, + "cdots": {"latex": "\\cdots", "mathml": "⋯"}, + "vdots": {"latex": "\\vdots", "mathml": "⋮"}, + "ddots": {"latex": "\\ddots", "mathml": "⋱"}, + "quad": {"latex": "\\quad", "mathml": " "}, + "/_": {"latex": "\\angle", "mathml": "∠"}, + "angle": {"latex": "\\angle", "mathml": "∠"}, + "frown": {"latex": "\\frown", "mathml": "⌢"}, + r"/_\\": {"latex": "\\triangle", "mathml": "△"}, + "triangle": {"latex": "\\triangle", "mathml": "△"}, + "diamond": {"latex": "\\diamond", "mathml": "⋄"}, + "square": {"latex": "\\square", "mathml": "□"}, + "|__": {"latex": "\\lfloor", "mathml": "⌊"}, + "lfloor": {"latex": "\\lfloor", "mathml": "⌊"}, + "__|": {"latex": "\\rfloor", "mathml": "⌋"}, + "rfloor": {"latex": "\\rfloor", "mathml": "⌋"}, + "|~": {"latex": "\\lceiling", "mathml": "⌈"}, + "lceiling": {"latex": "\\lceiling", "mathml": "⌈"}, + "~|": {"latex": "\\rceiling", "mathml": "⌉"}, + "rceiling": {"latex": "\\rceiling", "mathml": "⌉"}, + "CC": {"latex": "\\mathbb{C}", "mathml": "ℂ"}, + "NN": {"latex": "\\mathbb{N}", "mathml": "ℕ"}, + "QQ": {"latex": "\\mathbb{Q}", "mathml": "ℚ"}, + "RR": {"latex": "\\mathbb{R}", "mathml": "ℝ"}, + "ZZ": {"latex": "\\mathbb{Z}", "mathml": "ℤ"}, +} + +# matrix2par = { +# "pmatrix": ["(", ")"], +# "bmatrix": ["[", "]"], +# "Bmatrix": ["\{", "\}"], +# "vmatrix": ["|", "|"], +# "Vmatrix": ["||", "||"], +# } diff --git a/py_asciimath/const.py b/py_asciimath/const.py deleted file mode 100644 index d1d31ca..0000000 --- a/py_asciimath/const.py +++ /dev/null @@ -1,448 +0,0 @@ -import sys - - -def get_symbols_for(symbol_group, translation): # pragma: no cover - if ( - translation == "latex" - or translation == "mathml" - or translation is None - ): - return { - k: ( - v[translation] - if translation == "latex" or translation == "mathml" - else None - ) - for k, v in getattr(sys.modules[__name__], symbol_group).items() - } - else: - raise NotImplementedError - - -binary_functions = { - '"frac"': {"latex": "\\frac", "mathml": "{}{}"}, - '"root"': {"latex": "\\sqrt", "mathml": "{}{}"}, - '"stackrel"': {"latex": "\\stackrel", "mathml": "{}{}"}, - '"overset"': {"latex": "\\overset", "mathml": "{}{}"}, - '"underset"': {"latex": "\\underset", "mathml": "{}{}"}, - '"color"': { - "latex": "\\textcolor", - "mathml": "{}", - }, -} - -unary_functions = { - '"sqrt"': {"latex": "\\sqrt", "mathml": "{}"}, - '"text"': {"latex": "\\textrm", "mathml": "{}"}, - '"abs"': {"latex": "abs", "mathml": "|{}|"}, - '"floor"': { - "latex": "floor", - "mathml": "{}", - }, - '"ceil"': { - "latex": "ceil", - "mathml": "{}", - }, - '"norm"': { - "latex": "norm", - "mathml": "{}", - }, - '"ubrace"': { - "latex": "\\underbrace", - "mathml": "{}", - }, - '"underbrace"': { - "latex": "\\underbrace", - "mathml": "{}", - }, - '"obrace"': { - "latex": "\\overbrace", - "mathml": "{}", - }, - '"overbrace"': { - "latex": "\\overbrace", - "mathml": "{}", - }, - '"cancel"': { - "latex": "\\cancel", - "mathml": "{}", - }, - '"bb"': { - "latex": "\\boldsymbol", - "mathml": "{}", - }, - '"bbb"': { - "latex": "\\mathbb", - "mathml": "{}", - }, - '"cc"': { - "latex": "\\mathcal", - "mathml": "{}", - }, - '"tt"': { - "latex": "\\texttt", - "mathml": "{}", - }, - '"fr"': { - "latex": "\\mathfrak", - "mathml": "{}", - }, - '"sf"': { - "latex": "\\textsf", - "mathml": "{}", - }, - '"ul"': { - "latex": "\\underline", - "mathml": "{}̲", - }, - '"underline"': { - "latex": "\\underline", - "mathml": "{}̲", - }, - '"bar"': { - "latex": "\\overline", - "mathml": "{}̲", - }, - '"overline"': { - "latex": "\\overline", - "mathml": "{}̲", - }, - '"hat"': {"latex": "\\hat", "mathml": "{}^"}, - '"vec"': { - "latex": "\\vec", - "mathml": "{}", - }, - '"dot"': { - "latex": "\\dot", - "mathml": "{}.", - }, - '"ddot"': { - "latex": "\\ddot", - "mathml": "{}..", - }, - '"dstyle"': { - "latex": "\\displaystyle", - "mathml": "{}", - }, -} - -operation_symbols = { - '"+"': {"latex": "+", "mathml": "+"}, - '"*"': {"latex": "\\cdot", "mathml": "⋅"}, - '"-"': {"latex": "-", "mathml": "-"}, - '"cdot"': {"latex": "\\cdot", "mathml": "⋅"}, - '"**"': {"latex": "\\ast", "mathml": "*"}, - '"ast"': {"latex": "\\ast", "mathml": "*"}, - '"***"': {"latex": "\\star", "mathml": "⋆"}, - '"star"': {"latex": "\\star", "mathml": "⋆"}, - '"//"': {"latex": "/", "mathml": "/"}, - r"/\\/": {"latex": "\\setminus", "mathml": "∖"}, - '"setminus"': {"latex": "\\setminus", "mathml": "∖"}, - '"xx"': {"latex": "\\times", "mathml": "×"}, - '"times"': {"latex": "\\times", "mathml": "×"}, - '"-:"': {"latex": "\\div", "mathml": "÷"}, - '"div"': {"latex": "\\div", "mathml": "÷"}, - '"|><"': {"latex": "\\ltimes", "mathml": "⋉"}, - '"ltimes"': {"latex": "\\ltimes", "mathml": "⋉"}, - '"><|"': {"latex": "\\rtimes", "mathml": "⋊"}, - '"rtimes"': {"latex": "\\rtimes", "mathml": "⋊"}, - '"|><|"': {"latex": "\\bowtie", "mathml": "⋈"}, - '"bowtie"': {"latex": "\\bowtie", "mathml": "⋈"}, - '"@"': {"latex": "\\circ", "mathml": "∘"}, - '"circ"': {"latex": "\\circ", "mathml": "∘"}, - '"o+"': {"latex": "\\oplus", "mathml": "⊕"}, - '"oplus"': {"latex": "\\oplus", "mathml": "⊕"}, - '"ox"': {"latex": "\\otimes", "mathml": "×"}, - '"otimes"': {"latex": "\\otimes", "mathml": "×"}, - '"o."': {"latex": "\\odot", "mathml": "⊙"}, - '"odot"': {"latex": "\\odot", "mathml": "⊙"}, - '"sum"': {"latex": "\\sum", "mathml": "∑"}, - '"prod"': {"latex": "\\prod", "mathml": "∏"}, - '"^^"': {"latex": "\\wedge", "mathml": "∧"}, - '"wedge"': {"latex": "\\wedge", "mathml": "∧"}, - '"^^^"': {"latex": "\\bigwedge", "mathml": "⋀"}, - '"bigwedge"': {"latex": "\\bigwedge", "mathml": "⋀"}, - '"vv"': {"latex": "\\vee", "mathml": "∨"}, - '"vee"': {"latex": "\\vee", "mathml": "∨"}, - '"vvv"': {"latex": "\\bigvee", "mathml": "⋁"}, - '"bigvee"': {"latex": "\\bigvee", "mathml": "⋁"}, - '"nn"': {"latex": "\\cap", "mathml": "∩"}, - '"cap"': {"latex": "\\cap", "mathml": "∩"}, - '"nnn"': {"latex": "\\bigcap", "mathml": "⋂"}, - '"bigcap"': {"latex": "\\bigcap", "mathml": "⋂"}, - '"uu"': {"latex": "\\cup", "mathml": "∪"}, - '"cup"': {"latex": "\\cup", "mathml": "∪"}, - '"uuu"': {"latex": "\\bigcup", "mathml": "⋃"}, - '"bigcup"': {"latex": "\\bigcup", "mathml": "⋃"}, -} - -logical_symbols = { - '"and"': {"latex": "\\mathmr{and}", "mathml": "and"}, - '"or"': {"latex": "\\mathmr{and}", "mathml": "or"}, - '"not"': {"latex": "\\neg", "mathml": "¬"}, - '"neg"': {"latex": "\\neg", "mathml": "¬"}, - '"=>"': {"latex": "\\implies", "mathml": "⇒"}, - '"implies"': {"latex": "\\implies", "mathml": "⇒"}, - '"if"': {"latex": "\\mathmr{if}", "mathml": "if"}, - '"<=>"': {"latex": "\\iff", "mathml": "⇔"}, - '"iff"': {"latex": "\\iff", "mathml": "⇔"}, - '"AA"': {"latex": "\\forall", "mathml": "∀"}, - '"forall"': {"latex": "\\forall", "mathml": "∀"}, - '"EE"': {"latex": "\\exists", "mathml": "∃"}, - '"exists"': {"latex": "\\exists", "mathml": "∃"}, - '"_|_"': {"latex": "\\bot", "mathml": "⊥"}, - '"bot"': {"latex": "\\bot", "mathml": "⊥"}, - '"TT"': {"latex": "\\top", "mathml": "⊤"}, - '"top"': {"latex": "\\top", "mathml": "⊤"}, - '"|--"': {"latex": "\\vdash", "mathml": "⊢"}, - '"vdash"': {"latex": "\\vdash", "mathml": "⊢"}, - '"|=="': {"latex": "\\models", "mathml": "⊨"}, - '"models"': {"latex": "\\models", "mathml": "⊨"}, -} - -relation_symbols = { - '"="': {"latex": "=", "mathml": "="}, - '"!="': {"latex": "\\ne", "mathml": "≠"}, - '"ne"': {"latex": "\\ne", "mathml": "≠"}, - '"<"': {"latex": "<", "mathml": "<"}, - '"lt"': {"latex": "<", "mathml": "<"}, - '">"': {"latex": ">", "mathml": ">"}, - '"gt"': {"latex": ">", "mathml": ">"}, - '"<="': {"latex": "\\le", "mathml": "≤"}, - '"le"': {"latex": "\\le", "mathml": "≤"}, - '">="': {"latex": "\\ge", "mathml": "≥"}, - '"ge"': {"latex": "\\ge", "mathml": "≥"}, - '"-<"': {"latex": "\\prec", "mathml": "≺"}, - '"prec"': {"latex": "\\prec", "mathml": "≺"}, - '"-<="': {"latex": "\\preceq", "mathml": "⪯"}, - '"preceq"': {"latex": "\\preceq", "mathml": "⪯"}, - '">-"': {"latex": "\\succ", "mathml": "≻"}, - '"succ"': {"latex": "\\succ", "mathml": "≻"}, - '">-="': {"latex": "\\succeq", "mathml": "⪰"}, - '"succeq"': {"latex": "\\succeq", "mathml": "⪰"}, - '"in"': {"latex": "\\in", "mathml": "∈"}, - '"!in"': {"latex": "\\notin", "mathml": "∉"}, - '"notin"': {"latex": "\\notin", "mathml": "∉"}, - '"sub"': {"latex": "\\subset", "mathml": "⊂"}, - '"subset"': {"latex": "\\subset", "mathml": "⊂"}, - '"sup"': {"latex": "\\supset", "mathml": "⊃"}, - '"supset"': {"latex": "\\supset", "mathml": "⊃"}, - '"sube"': {"latex": "\\subseteq", "mathml": "⊆"}, - '"subseteq"': {"latex": "\\subseteq", "mathml": "⊆"}, - '"supe"': {"latex": "\\supseteq", "mathml": "⊇"}, - '"supseteq"': {"latex": "\\supseteq", "mathml": "⊇"}, - '"-="': {"latex": "\\equiv", "mathml": "≡"}, - '"equiv"': {"latex": "\\equiv", "mathml": "≡"}, - '"~="': {"latex": "\\cong", "mathml": "≅"}, - '"cong"': {"latex": "\\cong", "mathml": "≅"}, - '"~~"': {"latex": "\\approx", "mathml": "≈"}, - '"approx"': {"latex": "\\approx", "mathml": "≈"}, - '"prop"': {"latex": "\\propto", "mathml": "∝"}, - '"propto"': {"latex": "\\propto", "mathml": "∝"}, -} - -function_symbols = { - '"sin"': {"latex": "\\sin", "mathml": "sin"}, - '"cos"': {"latex": "\\cos", "mathml": "cos"}, - '"tan"': {"latex": "\\tan", "mathml": "tan"}, - '"sec"': {"latex": "\\sec", "mathml": "sec"}, - '"csc"': {"latex": "\\csc", "mathml": "csc"}, - '"cot"': {"latex": "\\cot", "mathml": "cot"}, - '"arcsin"': {"latex": "\\arcsin", "mathml": "arcsin"}, - '"arccos"': {"latex": "\\arccos", "mathml": "arccos"}, - '"arctan"': {"latex": "\\arctan", "mathml": "arctan"}, - '"sinh"': {"latex": "\\sinh", "mathml": "sinh"}, - '"cosh"': {"latex": "\\cosh", "mathml": "cosh"}, - '"tanh"': {"latex": "\\tanh", "mathml": "tanh"}, - '"sech"': {"latex": "\\sech", "mathml": "sech"}, - '"csch"': {"latex": "\\csch", "mathml": "csch"}, - '"coth"': {"latex": "\\coth", "mathml": "coth"}, - '"exp"': {"latex": "\\exp", "mathml": "exp"}, - '"log"': {"latex": "\\log", "mathml": "log"}, - '"ln"': {"latex": "\\ln", "mathml": "ln"}, - '"det"': {"latex": "\\det", "mathml": "det"}, - '"dim"': {"latex": "\\dim", "mathml": "dim"}, - '"mod"': {"latex": "\\mod", "mathml": "mod"}, - '"gcd"': {"latex": "\\gcd", "mathml": "gcd"}, - '"lcm"': {"latex": "\\lcm", "mathml": "lcm"}, - '"lub"': {"latex": "\\lub", "mathml": "lub"}, - '"glb"': {"latex": "\\glb", "mathml": "glb"}, - '"min"': {"latex": "\\min", "mathml": "min"}, - '"max"': {"latex": "\\max", "mathml": "max"}, - '"lim"': {"latex": "\\lim", "mathml": "lim"}, - '"f"': {"latex": "f", "mathml": "f"}, - '"g"': {"latex": "g", "mathml": "g"}, -} - -greek_letters = { - '"alpha"': {"latex": "\\alpha", "mathml": "α"}, - '"beta"': {"latex": "\\beta", "mathml": "β"}, - '"gamma"': {"latex": "\\gamma", "mathml": "γ"}, - '"Gamma"': {"latex": "\\Gamma", "mathml": "Γ"}, - '"delta"': {"latex": "\\delta", "mathml": "δ"}, - '"Delta"': {"latex": "\\Delta", "mathml": "Δ"}, - '"epsilon"': {"latex": "\\epsilon", "mathml": "ϵ"}, - '"varepsilon"': {"latex": "\\varepsilon", "mathml": "ϵ"}, - '"zeta"': {"latex": "\\zeta", "mathml": "ζ"}, - '"eta"': {"latex": "\\eta", "mathml": "η"}, - '"theta"': {"latex": "\\theta", "mathml": "θ"}, - '"Theta"': {"latex": "\\Theta", "mathml": "Θ"}, - '"vartheta"': {"latex": "\\vartheta", "mathml": "ϑ"}, - '"iota"': {"latex": "\\iota", "mathml": "ι"}, - '"kappa"': {"latex": "\\kappa", "mathml": "κ"}, - '"lambda"': {"latex": "\\lambda", "mathml": "λ"}, - '"Lambda"': {"latex": "\\Lambda", "mathml": "Λ"}, - '"mu"': {"latex": "\\mu", "mathml": "μ"}, - '"nu"': {"latex": "\\nu", "mathml": "ν"}, - '"xi"': {"latex": "\\xi", "mathml": "ξ"}, - '"Xi"': {"latex": "\\Xi", "mathml": "Ξ"}, - '"pi"': {"latex": "\\pi", "mathml": "π"}, - '"Pi"': {"latex": "\\Pi", "mathml": "Π"}, - '"rho"': {"latex": "\\rho", "mathml": "ρ"}, - '"sigma"': {"latex": "\\sigma", "mathml": "σ"}, - '"Sigma"': {"latex": "\\Sigma", "mathml": "Σ"}, - '"tau"': {"latex": "\\tau", "mathml": "τ"}, - '"upsilon"': {"latex": "\\upsilon", "mathml": "υ"}, - '"phi"': {"latex": "\\phi", "mathml": "φ"}, - '"Phi"': {"latex": "\\Phi", "mathml": "Φ"}, - '"varphi"': {"latex": "\\varphi", "mathml": "ϕ"}, - '"chi"': {"latex": "\\chi", "mathml": "χ"}, - '"psi"': {"latex": "\\psi", "mathml": "ψ"}, - '"Psi"': {"latex": "\\Psi", "mathml": "Ψ"}, - '"omega"': {"latex": "\\omega", "mathml": "ω"}, - '"Omega"': {"latex": "\\Omega", "mathml": "Ω"}, -} - -left_parenthesis = { - '"(:"': {"latex": "\\langle ", "mathml": "⟨"}, - '"("': {"latex": "(", "mathml": "("}, - '"["': {"latex": "[", "mathml": "["}, - '"{:"': {"latex": ".", "mathml": ""}, - '"{"': {"latex": "\\{", "mathml": "{"}, - '"|:"': {"latex": "\\vert", "mathml": "∣"}, - '"||:"': {"latex": "\\lVert", "mathml": "∥"}, - '"langle"': {"latex": "\\langle ", "mathml": "⟨"}, - '"<<"': {"latex": "\\langle ", "mathml": "⟨"}, -} - -right_parenthesis = { - '":)"': {"latex": "\\rangle", "mathml": "⟩"}, - '")"': {"latex": ")", "mathml": ")"}, - '"]"': {"latex": "]", "mathml": "]"}, - '":}"': {"latex": ".", "mathml": ""}, - '"}"': {"latex": "\\}", "mathml": "}"}, - '":|"': {"latex": "\\vert", "mathml": "∣"}, - '":||"': {"latex": "\\rVert", "mathml": "∥"}, - '"rangle"': {"latex": "\\rangle", "mathml": "⟩"}, - '">>"': {"latex": "\\rangle", "mathml": "⟩"}, -} - -arrows = { - '"uarr"': {"latex": "\\uparrow", "mathml": "↑"}, - '"uparrow"': {"latex": "\\uparrow", "mathml": "↑"}, - '"darr"': {"latex": "\\downarrow", "mathml": "↓"}, - '"downarrow"': {"latex": "\\downarrow", "mathml": "↓"}, - '"rarr"': {"latex": "\\rightarrow", "mathml": "→"}, - '"rArr"': {"latex": "\\Rightarrow", "mathml": "⇒"}, - '"rightarrow"': {"latex": "\\rightarrow", "mathml": "→"}, - '"->"': {"latex": "\\to", "mathml": "→"}, - '"to"': {"latex": "\\to", "mathml": "→"}, - '">->"': {"latex": "\\rightarrowtail", "mathml": ""}, - '"rightarrowtail"': { - "latex": "\\rightarrowtail", - "mathml": "↣", - }, - '"->>"': {"latex": "\\twoheadrightarrow", "mathml": ""}, - '"twoheadrightarrow"': { - "latex": "\\twoheadrightarrow", - "mathml": "↠", - }, - '">->>"': {"latex": "\\twoheadrightarrowtail", "mathml": ""}, - '"twoheadrightarrowtail"': { - "latex": "\\twoheadrightarrowtail", - "mathml": "⤖", - }, - '"|->"': {"latex": "\\mapsto", "mathml": ""}, - '"mapsto"': {"latex": "\\mapsto", "mathml": "↦"}, - '"larr"': {"latex": "\\leftarrow", "mathml": "←"}, - '"leftarrow"': {"latex": "\\leftarrow", "mathml": "←"}, - '"harr"': {"latex": "\\leftrightarrow", "mathml": "↔"}, - '"leftrightarrow"': { - "latex": "\\leftrightarrow", - "mathml": "↔", - }, - '"lArr"': {"latex": "\\Leftarrow", "mathml": "⇐"}, - '"Leftarrow"': {"latex": "\\Leftarrow", "mathml": "⇐"}, - '"hArr"': {"latex": "\\Leftrightarrow", "mathml": "⇔"}, - '"Leftrightarrow"': { - "latex": "\\Leftrightarrow", - "mathml": "⇔", - }, -} - -colors = { - '"red"': {"latex": "red", "mathml": "red"}, -} - -misc_symbols = { - '"^"': {"latex": "^", "mathml": "^"}, - '","': {"latex": ",", "mathml": ","}, - '"."': {"latex": ".", "mathml": "."}, - '"_"': {"latex": "_", "mathml": "_"}, - '"\'"': {"latex": "'", "mathml": "'"}, - '"/"': {"latex": "/", "mathml": "/"}, - '"|"': {"latex": "|", "mathml": "|"}, - '":"': {"latex": ":", "mathml": ":"}, - '"int"': {"latex": "\\int", "mathml": "∫"}, - '"integral"': {"latex": "\\int", "mathml": "∫"}, - '"oint"': {"latex": "\\oint", "mathml": "∮"}, - '"del"': {"latex": "\\partial", "mathml": "∂"}, - '"partial"': {"latex": "\\partial", "mathml": "∂"}, - '"grad"': {"latex": "\\nabla", "mathml": "∇"}, - '"nabla"': {"latex": "\\nabla", "mathml": "∇"}, - '"+-"': {"latex": "\\pm", "mathml": "±"}, - '"pm"': {"latex": "\\pm", "mathml": "±"}, - '"O/"': {"latex": "\\emptyset", "mathml": "∅"}, - '"emptyset"': {"latex": "\\emptyset", "mathml": "∅"}, - '"oo"': {"latex": "\\infty", "mathml": "∞"}, - '"infty"': {"latex": "\\infty", "mathml": "∞"}, - '"aleph"': {"latex": "\\aleph", "mathml": "ℵ"}, - '":."': {"latex": "\\therefore", "mathml": "∴"}, - '"therefore"': {"latex": "\\therefore", "mathml": "∴"}, - '":\'"': {"latex": "\\because", "mathml": "∵"}, - '"because"': {"latex": "\\because", "mathml": "∵"}, - '"..."': {"latex": "\\ldots", "mathml": "..."}, - '"ldots"': {"latex": "\\ldots", "mathml": "..."}, - '"cdots"': {"latex": "\\cdots", "mathml": "⋯"}, - '"vdots"': {"latex": "\\vdots", "mathml": "⋮"}, - '"ddots"': {"latex": "\\ddots", "mathml": "⋱"}, - '"quad"': {"latex": "\\quad", "mathml": " "}, - '"/_"': {"latex": "\\angle", "mathml": "∠"}, - '"angle"': {"latex": "\\angle", "mathml": "∠"}, - '"frown"': {"latex": "\\frown", "mathml": "⌢"}, - r"/_\\/": {"latex": "\\triangle", "mathml": "△"}, - '"triangle"': {"latex": "\\triangle", "mathml": "△"}, - '"diamond"': {"latex": "\\diamond", "mathml": "⋄"}, - '"square"': {"latex": "\\square", "mathml": "□"}, - '"|__"': {"latex": "\\lfloor", "mathml": "⌊"}, - '"lfloor"': {"latex": "\\lfloor", "mathml": "⌊"}, - '"__|"': {"latex": "\\rfloor", "mathml": "⌋"}, - '"rfloor"': {"latex": "\\rfloor", "mathml": "⌋"}, - '"|~"': {"latex": "\\lceiling", "mathml": "⌈"}, - '"lceiling"': {"latex": "\\lceiling", "mathml": "⌈"}, - '"~|"': {"latex": "\\rceiling", "mathml": "⌉"}, - '"rceiling"': {"latex": "\\rceiling", "mathml": "⌉"}, - '"CC"': {"latex": "\\mathbb{C}", "mathml": "ℂ"}, - '"NN"': {"latex": "\\mathbb{N}", "mathml": "ℕ"}, - '"QQ"': {"latex": "\\mathbb{Q}", "mathml": "ℚ"}, - '"RR"': {"latex": "\\mathbb{R}", "mathml": "ℝ"}, - '"ZZ"': {"latex": "\\mathbb{Z}", "mathml": "ℤ"}, -} - -# matrix2par = { -# "pmatrix": ["(", ")"], -# "bmatrix": ["[", "]"], -# "Bmatrix": ["\{", "\}"], -# "vmatrix": ["|", "|"], -# "Vmatrix": ["||", "||"], -# } diff --git a/py_asciimath/grammar/asciimath_grammar.py b/py_asciimath/grammar/asciimath_grammar.py index ba4e5c3..08209d7 100644 --- a/py_asciimath/grammar/asciimath_grammar.py +++ b/py_asciimath/grammar/asciimath_grammar.py @@ -1,6 +1,6 @@ from itertools import islice -from ..const import get_symbols_for +from ..asciimath import get_symbols_for from ..utils.utils import alias_string unary_functions = get_symbols_for("unary_functions", None) diff --git a/py_asciimath/grammar/latex_grammar.py b/py_asciimath/grammar/latex_grammar.py new file mode 100644 index 0000000..707fd9a --- /dev/null +++ b/py_asciimath/grammar/latex_grammar.py @@ -0,0 +1,61 @@ +from itertools import islice + +from ..utils.utils import alias_string +from ..translation.latex2asciimath import ( + left_parenthesis, + right_parenthesis, + smb, + unary_functions, + binary_functions, +) + + +latex_grammar = r""" + %import common.WS + %import common.LETTER + %import common.NUMBER + %ignore WS + start: "\\[" exp "\\]" -> exp + | "$$" exp "$$" -> exp + | "$" exp "$" -> exp + | exp -> exp + exp: i exp* -> exp + i: s -> exp_interm + | s "_" s -> exp_under + | s "^" s -> exp_super + | s "_" s "^" s -> exp_under_super + s: _l exp? _r -> exp_par + | "\\left" (_l | /\./ | /\\vert/ | /\\mid/) start? "\\right" (_r | /\./ | /\\vert/ | /\\mid/) -> exp_par + | "\\begin{{matrix}}" row_mat (/\\\\/ row_mat?)* "\\end{{matrix}}" -> exp_mat + | /\\sqrt/ "[" i+ "]" "{{" exp "}}" -> exp_binary + | "{{" i+ "}}" -> exp + | _u "{{" exp "}}" -> exp_unary + | _b "{{" exp "}}" "{{" exp "}}" -> exp_binary + | _latex1 -> symbol + | _latex2 -> symbol + | _c -> const + !_c: NUMBER + | LETTER + !row_mat: exp ("&" exp?)* -> row_mat + !_l: {} // left parenthesis + !_r: {} // right parenthesis + !_b: {} // binary functions + !_u: {} // unary functions + !_latex1: {} + !_latex2: {} +""".format( + alias_string(left_parenthesis, alias=False, lang_from="latex"), + alias_string(right_parenthesis, alias=False, lang_from="latex"), + alias_string(binary_functions, alias=False, lang_from="latex"), + alias_string(unary_functions, alias=False, lang_from="latex"), + alias_string( + dict(islice(smb.items(), len(smb) // 2)), + alias=False, + lang_from="latex", + ), + alias_string( + dict(islice(smb.items(), len(smb) // 2, len(smb))), + alias=False, + lang_from="latex", + ), +) diff --git a/py_asciimath/latex.py b/py_asciimath/latex.py new file mode 100644 index 0000000..796fc5b --- /dev/null +++ b/py_asciimath/latex.py @@ -0,0 +1,356 @@ +import sys + + +def get_symbols_for(symbol_group, lang_to): # pragma: no cover + return { + k: ( + None + if lang_to is None + else ( + v[lang_to] + if not isinstance(v[lang_to], list) + else v[lang_to][0] + ) + ) + for k, v in getattr(sys.modules[__name__], symbol_group).items() + } + + +binary_functions = { + "\\frac": {"asciimath": "frac", "mathml": "{}{}"}, + # "\\sqrt": {"asciimath": "root", "mathml": "{}{}"}, + "\\stackrel": {"asciimath": "stackrel", "mathml": "{}{}"}, + "\\overset": {"asciimath": "overset", "mathml": "{}{}"}, + "\\underset": { + "asciimath": "underset", + "mathml": "{}{}", + }, + "\\textcolor": { + "asciimath": "color", + "mathml": "{}", + }, +} + +unary_functions = { + "\\sqrt": {"asciimath": "sqrt", "mathml": "{}"}, + "\\text": {"asciimath": "text", "mathml": "{}"}, + "\\textrm": {"asciimath": "text", "mathml": "{}"}, + "\\mathrm": {"asciimath": "text", "mathml": "{}"}, + "\\underbrace": { + "asciimath": ["ubrace", "underbrace"], + "mathml": "{}", + }, + "\\overbrace": { + "asciimath": ["obrace", "overbrace"], + "mathml": "{}", + }, + "\\cancel": { + "asciimath": "cancel", + "mathml": "{}", + }, + "\\boldsymbol": { + "asciimath": "bb", + "mathml": "{}", + }, + "\\mathbb": { + "asciimath": "bbb", + "mathml": "{}", + }, + "\\mathcal": { + "asciimath": "cc", + "mathml": "{}", + }, + "\\texttt": { + "asciimath": "tt", + "mathml": "{}", + }, + "\\mathfrak": { + "asciimath": "fr", + "mathml": "{}", + }, + "\\textsf": { + "asciimath": "sf", + "mathml": "{}", + }, + "\\underline": { + "asciimath": ["ul", "underline"], + "mathml": "{}̲", + }, + "\\overline": { + "asciimath": ["bar", "overline"], + "mathml": "{}̲", + }, + "\\hat": {"asciimath": "hat", "mathml": "{}^"}, + "\\vec": { + "asciimath": "vec", + "mathml": "{}", + }, + "\\dot": { + "asciimath": "dot", + "mathml": "{}.", + }, + "\\ddot": { + "asciimath": "ddot", + "mathml": "{}..", + }, + "\\displaystyle": { + "asciimath": "dstyle", + "mathml": "{}", + }, +} + +operation_symbols = { + "+": {"asciimath": "+", "mathml": "+"}, + "\\cdot": {"asciimath": ["*", "cdot"], "mathml": "⋅"}, + "-": {"asciimath": "-", "mathml": "-"}, + "*": {"asciimath": ["**", "ast"], "mathml": "*"}, + "\\ast": {"asciimath": ["**", "ast"], "mathml": "*"}, + "\\star": {"asciimath": ["***", "star"], "mathml": "⋆"}, + "/": {"asciimath": "//", "mathml": "/"}, + "\\setminus": {"asciimath": [r"\\", "setminus"], "mathml": "∖"}, + "\\times": {"asciimath": ["xx", "times"], "mathml": "×"}, + "\\div": {"asciimath": ["-:", "div"], "mathml": "÷"}, + "\\ltimes": {"asciimath": ["|><", "ltimes"], "mathml": "⋉"}, + "\\rtimes": {"asciimath": ["><|", "rtimes"], "mathml": "⋊"}, + "\\bowtie": {"asciimath": ["|><|", "bowtie"], "mathml": "⋈"}, + "\\circ": {"asciimath": ["@", "circ"], "mathml": "∘"}, + "\\oplus": {"asciimath": ["o+", "oplus"], "mathml": "⊕"}, + "\\otimes": {"asciimath": ["ox", "otimes"], "mathml": "×"}, + "\\odot": {"asciimath": ["o.", "odot"], "mathml": "⊙"}, + "\\sum": {"asciimath": "sum", "mathml": "∑"}, + "\\prod": {"asciimath": "prod", "mathml": "∏"}, + "\\wedge": {"asciimath": ["^^", "wedge"], "mathml": "∧"}, + "\\bigwedge": {"asciimath": ["^^^", "bigwedge"], "mathml": "⋀"}, + "\\vee": {"asciimath": ["vv", "vee"], "mathml": "∨"}, + "\\bigvee": {"asciimath": ["vvv", "bigvee"], "mathml": "⋁"}, + "\\cap": {"asciimath": ["nn", "cap"], "mathml": "∩"}, + "\\bigcap": {"asciimath": ["nnn", "bigcap"], "mathml": "⋂"}, + "\\cup": {"asciimath": ["uu", "cup"], "mathml": "∪"}, + "\\bigcup": {"asciimath": ["uuu", "bigcup"], "mathml": "⋃"}, +} + +logical_symbols = { + "\\mathmr{and}": {"asciimath": "and", "mathml": "and"}, + "\\mathmr{or}": {"asciimath": "or", "mathml": "or"}, + "\\neg": {"asciimath": ["not", "neg"], "mathml": "¬"}, + "\\implies": {"asciimath": ["=>", "implies"], "mathml": "⇒"}, + "\\mathmr{if}": {"asciimath": "if", "mathml": "if"}, + "\\iff": {"asciimath": ["<=>", "iff"], "mathml": "⇔"}, + "\\forall": {"asciimath": ["AA", "forall"], "mathml": "∀"}, + "\\exists": {"asciimath": ["EE", "exists"], "mathml": "∃"}, + "\\bot": {"asciimath": ["_|_", "bot"], "mathml": "⊥"}, + "\\top": {"asciimath": ["TT", "top"], "mathml": "⊤"}, + "\\vdash": {"asciimath": ["|--", "vdash"], "mathml": "⊢"}, + "\\models": {"asciimath": ["|==", "models"], "mathml": "⊨"}, +} + +relation_symbols = { + "=": {"asciimath": "=", "mathml": "="}, + "\\ne": {"asciimath": ["!=", "ne"], "mathml": "≠"}, + "<": {"asciimath": ["<", "lt"], "mathml": "<"}, + ">": {"asciimath": [">", "gt"], "mathml": ">"}, + "\\le": {"asciimath": ["<=", "le"], "mathml": "≤"}, + "\\ge": {"asciimath": [">=", "ge"], "mathml": "≥"}, + "\\prec": {"asciimath": ["-<", "prec"], "mathml": "≺"}, + "\\preceq": {"asciimath": ["-<=", "preceq"], "mathml": "⪯"}, + "\\succ": {"asciimath": [">-", "succ"], "mathml": "≻"}, + "\\succeq": {"asciimath": [">-=", "succeq"], "mathml": "⪰"}, + "\\in": {"asciimath": "in", "mathml": "∈"}, + "\\notin": {"asciimath": ["!in", "notin"], "mathml": "∉"}, + "\\subset": {"asciimath": ["sub", "subset"], "mathml": "⊂"}, + "\\supset": {"asciimath": ["sup", "supset"], "mathml": "⊃"}, + "\\subseteq": { + "asciimath": ["sube", "subseteq"], + "mathml": "⊆", + }, + "\\supseteq": { + "asciimath": ["supe", "supseteq"], + "mathml": "⊇", + }, + "\\equiv": {"asciimath": ["-=", "equiv"], "mathml": "≡"}, + "\\cong": {"asciimath": ["~=", "cong"], "mathml": "≅"}, + "\\approx": {"asciimath": ["~~", "approx"], "mathml": "≈"}, + "\\propto": {"asciimath": ["prop", "propto"], "mathml": "∝"}, +} + +function_symbols = { + "\\sin": {"asciimath": "sin", "mathml": "sin"}, + "\\cos": {"asciimath": "cos", "mathml": "cos"}, + "\\tan": {"asciimath": "tan", "mathml": "tan"}, + "\\sec": {"asciimath": "sec", "mathml": "sec"}, + "\\csc": {"asciimath": "csc", "mathml": "csc"}, + "\\cot": {"asciimath": "cot", "mathml": "cot"}, + "\\arcsin": {"asciimath": "arcsin", "mathml": "arcsin"}, + "\\arccos": {"asciimath": "arccos", "mathml": "arccos"}, + "\\arctan": {"asciimath": "arctan", "mathml": "arctan"}, + "\\sinh": {"asciimath": "sinh", "mathml": "sinh"}, + "\\cosh": {"asciimath": "cosh", "mathml": "cosh"}, + "\\tanh": {"asciimath": "tanh", "mathml": "tanh"}, + "\\sech": {"asciimath": "sech", "mathml": "sech"}, + "\\csch": {"asciimath": "csch", "mathml": "csch"}, + "\\coth": {"asciimath": "coth", "mathml": "coth"}, + "\\exp": {"asciimath": "exp", "mathml": "exp"}, + "\\log": {"asciimath": "log", "mathml": "log"}, + "\\ln": {"asciimath": "ln", "mathml": "ln"}, + "\\det": {"asciimath": "det", "mathml": "det"}, + "\\dim": {"asciimath": "dim", "mathml": "dim"}, + "\\mod": {"asciimath": "mod", "mathml": "mod"}, + "\\gcd": {"asciimath": "gcd", "mathml": "gcd"}, + "\\lcm": {"asciimath": "lcm", "mathml": "lcm"}, + "\\lub": {"asciimath": "lub", "mathml": "lub"}, + "\\glb": {"asciimath": "glb", "mathml": "glb"}, + "\\min": {"asciimath": "min", "mathml": "min"}, + "\\max": {"asciimath": "max", "mathml": "max"}, + "\\lim": {"asciimath": "lim", "mathml": "lim"}, + "f": {"asciimath": "f", "mathml": "f"}, + "g": {"asciimath": "g", "mathml": "g"}, +} + +greek_letters = { + "\\alpha": {"asciimath": "alpha", "mathml": "α"}, + "\\beta": {"asciimath": "beta", "mathml": "β"}, + "\\gamma": {"asciimath": "gamma", "mathml": "γ"}, + "\\Gamma": {"asciimath": "Gamma", "mathml": "Γ"}, + "\\delta": {"asciimath": "delta", "mathml": "δ"}, + "\\Delta": {"asciimath": "Delta", "mathml": "Δ"}, + "\\epsilon": {"asciimath": "epsilon", "mathml": "ϵ"}, + "\\varepsilon": {"asciimath": "varepsilon", "mathml": "ϵ"}, + "\\zeta": {"asciimath": "zeta", "mathml": "ζ"}, + "\\eta": {"asciimath": "eta", "mathml": "η"}, + "\\theta": {"asciimath": "theta", "mathml": "θ"}, + "\\Theta": {"asciimath": "Theta", "mathml": "Θ"}, + "\\vartheta": {"asciimath": "vartheta", "mathml": "ϑ"}, + "\\iota": {"asciimath": "iota", "mathml": "ι"}, + "\\kappa": {"asciimath": "kappa", "mathml": "κ"}, + "\\lambda": {"asciimath": "lambda", "mathml": "λ"}, + "\\Lambda": {"asciimath": "Lambda", "mathml": "Λ"}, + "\\mu": {"asciimath": "mu", "mathml": "μ"}, + "\\nu": {"asciimath": "nu", "mathml": "ν"}, + "\\xi": {"asciimath": "xi", "mathml": "ξ"}, + "\\Xi": {"asciimath": "Xi", "mathml": "Ξ"}, + "\\pi": {"asciimath": "pi", "mathml": "π"}, + "\\Pi": {"asciimath": "Pi", "mathml": "Π"}, + "\\rho": {"asciimath": "rho", "mathml": "ρ"}, + "\\sigma": {"asciimath": "sigma", "mathml": "σ"}, + "\\Sigma": {"asciimath": "Sigma", "mathml": "Σ"}, + "\\tau": {"asciimath": "tau", "mathml": "τ"}, + "\\upsilon": {"asciimath": "upsilon", "mathml": "υ"}, + "\\phi": {"asciimath": "phi", "mathml": "φ"}, + "\\Phi": {"asciimath": "Phi", "mathml": "Φ"}, + "\\varphi": {"asciimath": "varphi", "mathml": "ϕ"}, + "\\chi": {"asciimath": "chi", "mathml": "χ"}, + "\\psi": {"asciimath": "psi", "mathml": "ψ"}, + "\\Psi": {"asciimath": "Psi", "mathml": "Ψ"}, + "\\omega": {"asciimath": "omega", "mathml": "ω"}, + "\\Omega": {"asciimath": "Omega", "mathml": "Ω"}, +} + +left_parenthesis = { + "(": {"asciimath": "(", "mathml": "("}, + "[": {"asciimath": "[", "mathml": "["}, + # ".": {"asciimath": "{:", "mathml": ""}, + "\\{": {"asciimath": "{", "mathml": "{"}, + # "\\vert": {"asciimath": "|:", "mathml": "∣"}, + "\\lVert": {"asciimath": "||:", "mathml": "∥"}, + "\\langle": {"asciimath": ["langle", "<<", "(:"], "mathml": "⟨"}, +} + +right_parenthesis = { + ")": {"asciimath": ")", "mathml": ")"}, + "]": {"asciimath": "]", "mathml": "]"}, + # ".": {"asciimath": ":}", "mathml": ""}, + "\\}": {"asciimath": "}", "mathml": "}"}, + # "\\vert": {"asciimath": ":|", "mathml": "∣"}, + "\\rVert": {"asciimath": ":||", "mathml": "∥"}, + "\\rangle": {"asciimath": ["rangle", ">>", ":)"], "mathml": "⟩"}, +} + +arrows = { + "\\uparrow": {"asciimath": ["uarr", "uparrow"], "mathml": "↑"}, + "\\downarrow": {"asciimath": ["darr", "downarrow"], "mathml": "↓"}, + "\\rightarrow": { + "asciimath": ["rarr", "rArr", "rightarrow"], + "mathml": "→", + }, + "\\to": {"asciimath": ["->", "to"], "mathml": "→"}, + "\\rightarrowtail": { + "asciimath": [">->", "rightarrowtail"], + "mathml": "↣", + }, + "\\twoheadrightarrow": { + "asciimath": ["->>", "twoheadrightarrow"], + "mathml": "↠", + }, + "\\twoheadrightarrowtail": { + "asciimath": [">->>", "twoheadrightarrowtail"], + "mathml": "⤖", + }, + "\\mapsto": {"asciimath": ["|->", "mapsto"], "mathml": ""}, + "\\leftarrow": {"asciimath": ["larr", "leftarrow"], "mathml": "←"}, + "\\leftrightarrow": { + "asciimath": ["harr", "leftrightarrow"], + "mathml": "↔", + }, + "\\Leftarrow": {"asciimath": ["lArr", "Leftarrow"], "mathml": "⇐"}, + "\\Leftrightarrow": { + "asciimath": ["hArr", "Leftrightarrow"], + "mathml": "⇔", + }, +} + +colors = { + "red": {"asciimath": "red", "mathml": "red"}, +} + +misc_symbols = { + "^": {"asciimath": "^", "mathml": "^"}, + ",": {"asciimath": ",", "mathml": ","}, + ".": {"asciimath": ".", "mathml": "."}, + "_": {"asciimath": "_", "mathml": "_"}, + "'": {"asciimath": "'", "mathml": "'"}, + "/": {"asciimath": "/", "mathml": "/"}, + "|": {"asciimath": "|", "mathml": "|"}, + "\\vert": {"asciimath": "|", "mathml": "|"}, + "\\mid": {"asciimath": "|", "mathml": "|"}, + ":": {"asciimath": ":", "mathml": ":"}, + "\\int": {"asciimath": ["int", "integral"], "mathml": "∫"}, + "\\oint": {"asciimath": "oint", "mathml": "∮"}, + "\\partial": {"asciimath": ["del", "partial"], "mathml": "∂"}, + "\\nabla": {"asciimath": ["grad", "nabla"], "mathml": "∇"}, + "\\pm": {"asciimath": ["+-", "pm"], "mathml": "±"}, + "\\emptyset": {"asciimath": ["O/", "emptyset"], "mathml": "∅"}, + "\\infty": {"asciimath": ["oo", "infty"], "mathml": "∞"}, + "\\aleph": {"asciimath": "aleph", "mathml": "ℵ"}, + "\\therefore": {"asciimath": [":.", "therefore"], "mathml": "∴"}, + "\\because": {"asciimath": [":'", "because"], "mathml": "∵"}, + "\\ldots": {"asciimath": ["...", "ldots"], "mathml": "..."}, + "\\cdots": {"asciimath": "cdots", "mathml": "⋯"}, + "\\vdots": {"asciimath": "vdots", "mathml": "⋮"}, + "\\ddots": {"asciimath": "ddots", "mathml": "⋱"}, + "\\quad": {"asciimath": "quad", "mathml": " "}, + "\\angle": {"asciimath": ["/_", "angle"], "mathml": "∠"}, + "\\frown": {"asciimath": "frown", "mathml": "⌢"}, + "\\triangle": { + "asciimath": [r"/_\\", "triangle"], + "mathml": "△", + }, + "\\diamond": {"asciimath": "diamond", "mathml": "⋄"}, + "\\square": {"asciimath": "square", "mathml": "□"}, + "\\lfloor": {"asciimath": ["|__", "lfloor"], "mathml": "⌊"}, + "\\rfloor": {"asciimath": ["__|", "rfloor"], "mathml": "⌋"}, + "\\lceiling": {"asciimath": ["|~", "lceiling"], "mathml": "⌈"}, + "\\rceiling": {"asciimath": ["~|", "rceiling"], "mathml": "⌉"}, + "\\mathbb{C}": {"asciimath": "CC", "mathml": "ℂ"}, + "\\mathbb{N}": {"asciimath": "NN", "mathml": "ℕ"}, + "\\mathbb{Q}": {"asciimath": "QQ", "mathml": "ℚ"}, + "\\mathbb{R}": {"asciimath": "RR", "mathml": "ℝ"}, + "\\mathbb{Z}": {"asciimath": "ZZ", "mathml": "ℤ"}, +} + +# matrix2par = { +# "pmatrix": ["(", ")"], +# "bmatrix": ["[", "]"], +# "Bmatrix": ["\{", "\}"], +# "vmatrix": ["|", "|"], +# "Vmatrix": ["||", "||"], +# } diff --git a/py_asciimath/py_asciimath.py b/py_asciimath/py_asciimath.py index f63b05d..96c1e42 100644 --- a/py_asciimath/py_asciimath.py +++ b/py_asciimath/py_asciimath.py @@ -23,7 +23,7 @@ Options: --dstyle Add display style -i --input=ILANG Input language - Supported input language: asciimath, mathml + Supported input language: asciimath, latex, mathml --log Log the transformation process --network Works only with ILANG=mathnml or OLANG=mathml Use network to validate XML against DTD @@ -43,10 +43,15 @@ from docopt import docopt from . import __version__ -from .translator.translator import ASCIIMath2MathML, ASCIIMath2Tex, MathML2Tex +from .translator.translator import ( + ASCIIMath2MathML, + ASCIIMath2Tex, + MathML2Tex, + Tex2ASCIIMath, +) -_supported_ilang = ["asciimath", "mathml"] -_supported_olang = ["latex", "mathml"] +_supported_ilang = ["asciimath", "latex", "mathml"] +_supported_olang = ["asciimath", "latex", "mathml"] def main(): @@ -65,10 +70,15 @@ def main(): print("Same input and output language. Nothing to do") sys.exit(0) elif ilang not in _supported_ilang: - print("Supported : 'asciimath', 'mathml'") + print("Supported : 'asciimath', 'latex', 'mathml'") sys.exit(1) elif olang not in _supported_olang: - print("Supported : 'latex', 'mathml'") + print("Supported : 'asciimath', 'latex', 'mathml'") + sys.exit(1) + elif ilang == "latex" and olang == "mathml": + print( + "Translation from 'latex' to 'mathml' is still under development" + ) sys.exit(1) exp = ( "".join(arguments[""]) @@ -106,6 +116,17 @@ def main(): to_file=arguments["--to-file"], ) ) + elif ilang == "latex": + if olang == "asciimath": + parser = Tex2ASCIIMath(log=arguments["--log"], inplace=True) + print( + parser.translate( + exp, + from_file=arguments["from-file"], + pprint=False, + to_file=arguments["--to-file"], + ) + ) elif ilang == "mathml": parser = MathML2Tex() print( diff --git a/py_asciimath/transformer/transformer.py b/py_asciimath/transformer/transformer.py index ba9efe1..75edaf6 100644 --- a/py_asciimath/transformer/transformer.py +++ b/py_asciimath/transformer/transformer.py @@ -4,19 +4,24 @@ from lark import Transformer -from ..translation.latex import binary_functions as latex_bin -from ..translation.latex import left_parenthesis as latex_left -from ..translation.latex import right_parenthesis as latex_right -from ..translation.latex import smb as latex_smb -from ..translation.latex import unary_functions as latex_una -from ..translation.mathml import binary_functions as mathml_bin -from ..translation.mathml import colors -from ..translation.mathml import left_parenthesis as mathml_left -from ..translation.mathml import right_parenthesis as mathml_right -from ..translation.mathml import smb as mathml_smb -from ..translation.mathml import unary_functions as mathml_una +from ..translation.asciimath2latex import binary_functions as latex_bin +from ..translation.asciimath2latex import left_parenthesis as latex_left +from ..translation.asciimath2latex import right_parenthesis as latex_right +from ..translation.asciimath2latex import smb as latex_smb +from ..translation.asciimath2latex import unary_functions as latex_una +from ..translation.asciimath2mathml import binary_functions as mathml_bin +from ..translation.asciimath2mathml import colors +from ..translation.asciimath2mathml import left_parenthesis as mathml_left +from ..translation.asciimath2mathml import right_parenthesis as mathml_right +from ..translation.asciimath2mathml import smb as mathml_smb +from ..translation.asciimath2mathml import unary_functions as mathml_una +from ..translation.latex2asciimath import binary_functions as l2mml_bin +from ..translation.latex2asciimath import left_parenthesis as l2mml_left +from ..translation.latex2asciimath import right_parenthesis as l2mml_right +from ..translation.latex2asciimath import smb as l2mml_smb +from ..translation.latex2asciimath import unary_functions as l2mml_una from ..utils.log import Log -from ..utils.utils import UtilsMat, concat, encapsulate_mrow +from ..utils.utils import UtilsMat, encapsulate_mrow # standard_library.install_aliases() logging.basicConfig(format="%(levelname)s:%(message)s", level=logging.DEBUG) @@ -27,18 +32,22 @@ def __init__(self): pass """ +# ["\\(", "\\(:", "\\[", "\\{", "\\{:"] +# ["\\)", ":\\)", "\\]", "\\}", ":\\}"] -class ASCIIMathTransformer(Transformer): # pragma: no cover + +class MathTransformer(Transformer): # pragma: no cover def __init__( - self, log=True, start_end_par_pattern="{}{}", visit_tokens=False + self, + log=True, + start_end_par_pattern="{}{}", + left_par=[], + right_par=[], + visit_tokens=False, ): Transformer.__init__(self, visit_tokens=visit_tokens) - formatted_left_parenthesis = "|".join( - ["\\(", "\\(:", "\\[", "\\{", "\\{:"] - ) - formatted_right_parenthesis = "|".join( - ["\\)", ":\\)", "\\]", "\\}", ":\\}"] - ) + formatted_left_parenthesis = "|".join(left_par) + formatted_right_parenthesis = "|".join(right_par) self.start_end_par_pattern = re.compile( start_end_par_pattern.format( formatted_left_parenthesis, formatted_right_parenthesis, @@ -98,52 +107,50 @@ def q_str(self, items): raise NotImplementedError -class LatexTransformer(ASCIIMathTransformer): +class ASCIIMath2TexTransformer(MathTransformer): """Trasformer class, read `lark.Transformer`.""" def __init__(self, log=True, visit_tokens=False): - ASCIIMathTransformer.__init__( + MathTransformer.__init__( self, log, r"^(?:\\left(?:(?:\\)?({})))(.*?)(?:\\right(?:(?:\\)?({})))$", + ["\\(", "\\(:", "\\[", "\\{", "\\{:"], + ["\\)", ":\\)", "\\]", "\\}", ":\\}"], visit_tokens, ) - @ASCIIMathTransformer.log - def remove_parenthesis(self, s): - return ASCIIMathTransformer.remove_parenthesis(self, s) - - @ASCIIMathTransformer.log + @MathTransformer.log def exp(self, items): return " ".join(items) - @ASCIIMathTransformer.log + @MathTransformer.log def exp_interm(self, items): return items[0] - @ASCIIMathTransformer.log + @MathTransformer.log def exp_frac(self, items): items[0] = self.remove_parenthesis(items[0]) items[1] = self.remove_parenthesis(items[1]) return "\\frac{" + items[0] + "}{" + items[1] + "}" - @ASCIIMathTransformer.log + @MathTransformer.log def exp_under(self, items): items[1] = self.remove_parenthesis(items[1]) - return items[0] + "_{" + items[1] + "}" + return "{" + items[0] + "}_{" + items[1] + "}" - @ASCIIMathTransformer.log + @MathTransformer.log def exp_super(self, items): items[1] = self.remove_parenthesis(items[1]) - return items[0] + "^{" + items[1] + "}" + return "{" + items[0] + "}^{" + items[1] + "}" - @ASCIIMathTransformer.log + @MathTransformer.log def exp_under_super(self, items): items[1] = self.remove_parenthesis(items[1]) items[2] = self.remove_parenthesis(items[2]) - return items[0] + "_{" + items[1] + "}^{" + items[2] + "}" + return "{" + items[0] + "}_{" + items[1] + "}^{" + items[2] + "}" - @ASCIIMathTransformer.log + @MathTransformer.log def exp_par(self, items): yeah_mat = False s = ", ".join(items[1:-1]) @@ -151,17 +158,21 @@ def exp_par(self, items): yeah_mat, row_par = UtilsMat.check_mat(s) if yeah_mat: s = UtilsMat.get_latex_mat(s, row_par) - lpar = "\\left" + latex_left[concat(items[0])] - rpar = "\\right" + latex_right[concat(items[-1])] + lpar = ( + "\\left" + + latex_left[items[0]] + + (" " if items[0] == "langle" else "") + ) + rpar = "\\right" + latex_right[items[-1]] return ( lpar + ("\\begin{matrix}" + s + "\\end{matrix}" if yeah_mat else s) + rpar ) - @ASCIIMathTransformer.log + @MathTransformer.log def exp_unary(self, items): - unary = latex_una[concat(items[0])] + unary = latex_una[items[0]] items[1] = self.remove_parenthesis(items[1]) if unary == "norm": return "\\left\\lVert " + items[1] + " \\right\\rVert" @@ -174,9 +185,9 @@ def exp_unary(self, items): else: return unary + "{" + items[1] + "}" - @ASCIIMathTransformer.log + @MathTransformer.log def exp_binary(self, items): - binary = latex_bin[concat(items[0])] + binary = latex_bin[items[0]] items[1] = self.remove_parenthesis(items[1]) items[2] = self.remove_parenthesis(items[2]) if binary == "\\sqrt": @@ -184,28 +195,30 @@ def exp_binary(self, items): else: return binary + "{" + items[1] + "}" + "{" + items[2] + "}" - @ASCIIMathTransformer.log + @MathTransformer.log def symbol(self, items): - if concat(items[0]) == '"\\"': + if items[0] == "\\": return "\\setminus" - return latex_smb[concat(items[0])] + elif items[0] == "/_\\": + return "\\triangle" + return latex_smb[items[0]] - @ASCIIMathTransformer.log + @MathTransformer.log def const(self, items): if len(items[0].value) == 2 and items[0].value[0] == "d": return "\\mathrm{" + items[0].value + "}" return items[0].value - @ASCIIMathTransformer.log + @MathTransformer.log def q_str(self, items): return "\\text{" + items[0].strip('"') + "}" -class MathMLTransformer(ASCIIMathTransformer): +class ASCIIMath2MathMLTransformer(MathTransformer): """Trasformer class, read `lark.Transformer`.""" def __init__(self, log=True, visit_tokens=False): - ASCIIMathTransformer.__init__( + MathTransformer.__init__( self, log, r"^(?:)?" @@ -213,22 +226,20 @@ def __init__(self, log=True, visit_tokens=False): r"(.*?)" r"(?:(?:({})))" r"(?:)?$", + ["\\(", "\\(:", "\\[", "\\{", "\\{:"], + ["\\)", ":\\)", "\\]", "\\}", ":\\}"], visit_tokens, ) - @ASCIIMathTransformer.log - def remove_parenthesis(self, s): - return ASCIIMathTransformer.remove_parenthesis(self, s) - - @ASCIIMathTransformer.log + @MathTransformer.log def exp(self, items): return "".join(items) - @ASCIIMathTransformer.log + @MathTransformer.log def exp_interm(self, items): return items[0] - @ASCIIMathTransformer.log + @MathTransformer.log def exp_frac(self, items): items[0] = self.remove_parenthesis(items[0]) items[1] = self.remove_parenthesis(items[1]) @@ -239,7 +250,7 @@ def exp_frac(self, items): + "" ) - @ASCIIMathTransformer.log + @MathTransformer.log def exp_under(self, items): items[1] = self.remove_parenthesis(items[1]) return encapsulate_mrow( @@ -249,7 +260,7 @@ def exp_under(self, items): + "" ) - @ASCIIMathTransformer.log + @MathTransformer.log def exp_super(self, items): items[1] = self.remove_parenthesis(items[1]) return encapsulate_mrow( @@ -259,7 +270,7 @@ def exp_super(self, items): + "" ) - @ASCIIMathTransformer.log + @MathTransformer.log def exp_under_super(self, items): items[1] = self.remove_parenthesis(items[1]) items[2] = self.remove_parenthesis(items[2]) @@ -271,7 +282,7 @@ def exp_under_super(self, items): + "" ) - @ASCIIMathTransformer.log + @MathTransformer.log def exp_par(self, items): yeah_mat = False s = ", ".join(items[1:-1]) @@ -285,8 +296,8 @@ def exp_par(self, items): + UtilsMat.get_mathml_mat(s, row_par) + "" ) - lpar = mathml_left[concat(items[0])] - rpar = mathml_right[concat(items[-1])] + lpar = mathml_left[items[0]] + rpar = mathml_right[items[-1]] return encapsulate_mrow( "" + lpar @@ -297,18 +308,18 @@ def exp_par(self, items): + "" ) - @ASCIIMathTransformer.log + @MathTransformer.log def exp_unary(self, items): - unary = mathml_una[concat(items[0])] + unary = mathml_una[items[0]] items[1] = self.remove_parenthesis(items[1]) return encapsulate_mrow(unary.format(encapsulate_mrow(items[1]))) - @ASCIIMathTransformer.log + @MathTransformer.log def exp_binary(self, items): - binary = mathml_bin[concat(items[0])] + binary = mathml_bin[items[0]] items[1] = self.remove_parenthesis(items[1]) items[2] = self.remove_parenthesis(items[2]) - if concat(items[1][6:-7]) in colors: + if items[1][6:-7] in colors: s = binary.format(items[1][6:-7], encapsulate_mrow(items[2])) elif items[0] != "root": s = binary.format( @@ -320,22 +331,137 @@ def exp_binary(self, items): ) return encapsulate_mrow(s) - @ASCIIMathTransformer.log + @MathTransformer.log def symbol(self, items): - if concat(items[0]) in colors: - return mathml_smb[concat(items[0])] - elif concat(items[0]) == '"\\"': + if items[0] in colors: + return items[0] + elif items[0] == "\\": return "" else: - return "" + mathml_smb[concat(items[0])] + "" + return "" + mathml_smb[items[0]] + "" - @ASCIIMathTransformer.log + @MathTransformer.log def const(self, items): if items[0].isnumeric(): return "" + items[0].value + "" else: return "" + items[0].value + "" - @ASCIIMathTransformer.log + @MathTransformer.log def q_str(self, items): return "" + items[0].strip('"') + "" + + +class Tex2ASCIIMathTransformer(MathTransformer): # pragma: no cover + def __init__(self, log=True, visit_tokens=False): + MathTransformer.__init__( + self, + log, + r"^(?:(?:(?:\\)?({})))(.*?)(?:(?:(?:\\)?({})))$", + [r"\(", r"\[", r"\{", r"\\\{", r"\\langle", r"\\lVert"], + [r"\)", r"\]", r"\}", r"\\\}", r"\\rangle", r"\\rVert"], + visit_tokens=visit_tokens, + ) + + def log(f): + @wraps(f) + def decorator(*args, **kwargs): + self = args[0] + return self._logger.__call__(f)(*args, **kwargs) + + return decorator + + @log + def exp(self, items): + return " ".join(items) + + @log + def exp_interm(self, items): + return items[0] + + @log + def exp_frac(self, items): + items[0] = self.remove_parenthesis(items[0]) + items[1] = self.remove_parenthesis(items[1]) + return "(" + items[0] + ")/(" + items[1] + ")" + + @log + def exp_under(self, items): + items[0] = self.remove_parenthesis(items[0]) + items[1] = self.remove_parenthesis(items[1]) + return "(" + items[0] + ")_(" + items[1] + ")" + + @log + def exp_super(self, items): + items[0] = self.remove_parenthesis(items[0]) + items[1] = self.remove_parenthesis(items[1]) + return "(" + items[0] + ")^(" + items[1] + ")" + + @log + def exp_under_super(self, items): + items[0] = self.remove_parenthesis(items[0]) + items[1] = self.remove_parenthesis(items[1]) + items[1] = self.remove_parenthesis(items[2]) + return "(" + items[0] + ")^(" + items[1] + ")_(" + items[2] + ")" + + @log + def exp_par(self, items): + left = items[0].value + right = items[-1].value + if left == ".": + left = "{:" + elif left in ["\\vert", "\\mid"]: + left = "|:" + elif left != "[": + left = l2mml_left[items[0].value] + if right == ".": + right = ":}" + elif right in ["\\vert", "\\mid"]: + right = ":|" + elif right != "]": + right = l2mml_right[items[-1].value] + return left + " ".join(items[1:-1]) + right + + @log + def exp_unary(self, items): + items[1] = self.remove_parenthesis(items[1]) + return l2mml_una[items[0]] + "(" + items[1] + ")" + + @log + def exp_binary(self, items): + items[1] = self.remove_parenthesis(items[1]) + items[2] = self.remove_parenthesis(items[2]) + if items[0].startswith("\\sqrt"): + return "root(" + "".join(items[1:-1]) + ")(" + items[-1] + ")" + return l2mml_bin[items[0]] + "(" + items[1] + ")(" + items[2] + ")" + + @log + def symbol(self, items): + return l2mml_smb[items[0]] + + @log + def const(self, items): + return items[0] + + @log + def q_str(self, items): + return items + + def _get_row(self, items, sep="&", mat=False): + s = "" + for i in items: + if i == sep: + i = "," + s = s + i + if mat: + return "{:" + s + ":}" + else: + return "[" + s + "]" + + @log + def exp_mat(self, items): + return self._get_row(items, sep="\\\\", mat=True) + + @log + def row_mat(self, items): + return self._get_row(items, sep="&") diff --git a/py_asciimath/translation/latex.py b/py_asciimath/translation/asciimath2latex.py similarity index 94% rename from py_asciimath/translation/latex.py rename to py_asciimath/translation/asciimath2latex.py index 1b22728..0a57c8f 100644 --- a/py_asciimath/translation/latex.py +++ b/py_asciimath/translation/asciimath2latex.py @@ -1,4 +1,4 @@ -from ..const import get_symbols_for +from ..asciimath import get_symbols_for unary_functions = get_symbols_for("unary_functions", "latex") binary_functions = get_symbols_for("binary_functions", "latex") diff --git a/py_asciimath/translation/mathml.py b/py_asciimath/translation/asciimath2mathml.py similarity index 95% rename from py_asciimath/translation/mathml.py rename to py_asciimath/translation/asciimath2mathml.py index 7414714..7cbc13e 100644 --- a/py_asciimath/translation/mathml.py +++ b/py_asciimath/translation/asciimath2mathml.py @@ -1,4 +1,4 @@ -from ..const import get_symbols_for +from ..asciimath import get_symbols_for unary_functions = get_symbols_for("unary_functions", "mathml") binary_functions = get_symbols_for("binary_functions", "mathml") diff --git a/py_asciimath/translation/latex2asciimath.py b/py_asciimath/translation/latex2asciimath.py new file mode 100644 index 0000000..55f7a6a --- /dev/null +++ b/py_asciimath/translation/latex2asciimath.py @@ -0,0 +1,16 @@ +from ..latex import get_symbols_for + +unary_functions = get_symbols_for("unary_functions", "asciimath") +binary_functions = get_symbols_for("binary_functions", "asciimath") +left_parenthesis = get_symbols_for("left_parenthesis", "asciimath") +right_parenthesis = get_symbols_for("right_parenthesis", "asciimath") + +smb = get_symbols_for("misc_symbols", "asciimath") +smb.update(get_symbols_for("function_symbols", "asciimath")) +smb.update(get_symbols_for("colors", "asciimath")) +smb.update(get_symbols_for("relation_symbols", "asciimath")) +smb.update(get_symbols_for("logical_symbols", "asciimath")) +smb.update(get_symbols_for("operation_symbols", "asciimath")) +smb.update(get_symbols_for("greek_letters", "asciimath")) +smb.update(get_symbols_for("arrows", "asciimath")) +smb = dict(sorted(smb.items(), key=lambda x: (-len(x[0]), x[0]))) diff --git a/py_asciimath/translator/translator.py b/py_asciimath/translator/translator.py index d86f10c..c49a02a 100644 --- a/py_asciimath/translator/translator.py +++ b/py_asciimath/translator/translator.py @@ -6,8 +6,13 @@ from lark import Lark from .. import PROJECT_ROOT from ..grammar.asciimath_grammar import asciimath_grammar +from ..grammar.latex_grammar import latex_grammar from ..parser.parser import MathMLParser -from ..transformer.transformer import LatexTransformer, MathMLTransformer +from ..transformer.transformer import ( + ASCIIMath2TexTransformer, + ASCIIMath2MathMLTransformer, + Tex2ASCIIMathTransformer, +) from ..utils.utils import check_connection logging.basicConfig(format="%(levelname)s:%(message)s", level=logging.DEBUG) @@ -64,14 +69,15 @@ def translate(self, exp, from_file=False, to_file=None, **kwargs): return exp -class ASCIIMathTranslator(Translator): - """Class that handle the translation from ASCIIMath. +class LarkTranslator(Translator): + """Class that handle the translation from a Lark parsed + language to the one specified by a Transformer. - An ASCIIMathTranslator translates an ASCIIMath string into another + A LarkTranslator translates a string, parsed with Lark, into another language, specified by the `transformer` parameter Args: - grammar (str): ASCIIMath grammar + grammar (str): BNF grammar to parse the input transformer (lark.Transformer): A transformer instance to transform parsed input. See :class:`~lark.Transformer` inplace (bool, optional): If True, parse the input inplace. @@ -92,7 +98,7 @@ def __init__( parser="lalr", **kwargs ): - super(ASCIIMathTranslator, self).__init__() + super(LarkTranslator, self).__init__() self.inplace = inplace self.grammar = grammar self.transformer = transformer @@ -128,12 +134,12 @@ def translate( Returns: str: Translated expression """ - return super(ASCIIMathTranslator, self).translate( + return super(LarkTranslator, self).translate( exp, from_file=from_file, to_file=to_file, pprint=pprint, **kwargs ) -class ASCIIMath2Tex(ASCIIMathTranslator): +class ASCIIMath2Tex(LarkTranslator): """Class that handle the translation from ASCIIMath to LaTeX Args: @@ -150,7 +156,7 @@ class ASCIIMath2Tex(ASCIIMathTranslator): def __init__(self, log=False, **kwargs): super(ASCIIMath2Tex, self).__init__( - asciimath_grammar, LatexTransformer(log=log), **kwargs + asciimath_grammar, ASCIIMath2TexTransformer(log=log), **kwargs ) def _translate(self, exp, displaystyle=False, pprint=False): @@ -201,7 +207,7 @@ def translate( ) -class ASCIIMath2MathML(ASCIIMathTranslator): +class ASCIIMath2MathML(LarkTranslator): """Class that handle the translation from ASCIIMath to MathML Args: @@ -218,7 +224,7 @@ class ASCIIMath2MathML(ASCIIMathTranslator): def __init__(self, log=False, **kwargs): super(ASCIIMath2MathML, self).__init__( - asciimath_grammar, MathMLTransformer(log=log), **kwargs + asciimath_grammar, ASCIIMath2MathMLTransformer(log=log), **kwargs ) self.__output = ["string", "etree"] @@ -348,6 +354,52 @@ def translate( ) +class Tex2ASCIIMath(LarkTranslator): + """Class that handle the translation from LaTeX to ASCIIMath + + Args: + inplace (bool, optional): If True, parse the input inplace. + See :class:`~lark.Lark`. Defaults to True. + lexer (str, optional): Lexer used during parsing. See :class:`~lark.Lark`. + Defaults to "contextual". + log (bool, optional): If True log the parsing process. + Defaults to False. + parser (str, optional): Parser algorithm. See :class:`~lark.Lark`. + Defaults to "lalr". + **kwargs: Additional keyword arguments to the :class:`~lark.Lark` class. + """ + + def __init__(self, log=False, **kwargs): + super(Tex2ASCIIMath, self).__init__( + latex_grammar, Tex2ASCIIMathTransformer(log=log), **kwargs + ) + + def _translate(self, exp, pprint=False): + return super(Tex2ASCIIMath, self)._translate(exp, pprint=pprint) + + def translate( + self, exp, from_file=False, pprint=False, to_file=None, + ): + """Translates an ASCIIMath string to LaTeX + + Args: + exp (str): String to translate. If from_file is True, then s + must represent the file's path + from_file (bool, optional): If True, load the string to translate + from the file specified by s. Defaults to False. + pprint (bool, optional): Abstract Syntax Tree pretty print. + Defaults to False. + to_file (str, optional): If specified, save the translation to + `to_file`. Defaults to None. + + Returns: + str: LaTeX translated expression + """ + return super(Tex2ASCIIMath, self).translate( + exp, from_file=from_file, pprint=pprint, to_file=to_file, + ) + + class MathML2Tex(Translator): # pragma: no cover """Class that handle the translation from MathML to LaTeX diff --git a/py_asciimath/utils/utils.py b/py_asciimath/utils/utils.py index ebf6473..6390238 100644 --- a/py_asciimath/utils/utils.py +++ b/py_asciimath/utils/utils.py @@ -15,13 +15,21 @@ logging.basicConfig(format="%(levelname)s:%(message)s", level=logging.DEBUG) -def alias_string(mapping, init=False, alias=True, prefix=""): +def alias_string(mapping, init=False, alias=True, prefix="", lang_from=None): mapping = list(mapping.items()) s = ( "|" if init else "" - + mapping[0][0] + + ( + '"' + mapping[0][0] + '"' + if lang_from != "latex" + else ( + '/' + mapping[0][0].encode("unicode-escape").decode() + '/' + if mapping[0][0].startswith("\\") + else '"' + mapping[0][0] + '"' + ) + ) + ( " -> " + (prefix + "_" if prefix != "" else "") + mapping[0][1] if alias @@ -32,7 +40,15 @@ def alias_string(mapping, init=False, alias=True, prefix=""): s = ( s + "\n\t| " - + k + + ( + '"' + k + '"' + if lang_from != "latex" + else ( + '/' + k.encode("unicode-escape").decode() + '/' + if k.startswith("\\") + else '"' + k + '"' + ) + ) + ( " -> " + (prefix + "_" if prefix != "" else "") + v if alias diff --git a/tests/test_ASCIIMath2MathML.py b/tests/test_ASCIIMath2MathML.py index 0b198d7..180b57f 100644 --- a/tests/test_ASCIIMath2MathML.py +++ b/tests/test_ASCIIMath2MathML.py @@ -5,10 +5,10 @@ from py_asciimath import PROJECT_ROOT from py_asciimath.grammar.asciimath_grammar import asciimath_grammar -from py_asciimath.transformer.transformer import MathMLTransformer +from py_asciimath.transformer.transformer import ASCIIMath2MathMLTransformer from py_asciimath.translator.translator import ( ASCIIMath2MathML, - ASCIIMathTranslator, + LarkTranslator, MathML2Tex, ) @@ -226,11 +226,11 @@ def test_asciimath2mathml_from_to_file_2(self): FileNotFoundError, MathML2Tex().translate, "$a+b$", from_file=True, ) - def test_asciimath2mathml_as_asciimathtranslator_1(self): + def test_asciimath2mathml_as_LarkTranslator_1(self): self.assertEqual( "a+b", - ASCIIMathTranslator( - asciimath_grammar, MathMLTransformer(log=False) + LarkTranslator( + asciimath_grammar, ASCIIMath2MathMLTransformer(log=False) ).translate("a + b"), ) diff --git a/tests/test_ASCIIMath2Tex.py b/tests/test_ASCIIMath2Tex.py index 35a2aaa..1681da2 100644 --- a/tests/test_ASCIIMath2Tex.py +++ b/tests/test_ASCIIMath2Tex.py @@ -28,7 +28,7 @@ def test_asciimath2tex_ok_2(self): self.assertEqual( s, r"\[\left(\left(1 , 2\right)\right) \int \sin " - r"\frac{x^{2}}{4} \pi \mathrm{dx} \sqrt[5]{x_{1}^{2} + x_{2}^{2}}\]", + r"\frac{{x}^{2}}{4} \pi \mathrm{dx} \sqrt[5]{{x}_{1}^{2} + {x}_{2}^{2}}\]", ) def test_asciimath2tex_ok_3(self): @@ -37,8 +37,8 @@ def test_asciimath2tex_ok_3(self): ).translate("lim_(N->oo) sum_(i=0)^N int_0^1 f(x)dx 3.14") self.assertEqual( s, - r"$\lim_{N \to \infty} \sum_{i = 0}^{N} " - r"\int_{0}^{1} f \left(x\right) \mathrm{dx} 3.14$", + r"${\lim}_{N \to \infty} {\sum}_{i = 0}^{N} " + r"{\int}_{0}^{1} f \left(x\right) \mathrm{dx} 3.14$", ) def test_asciimath2tex_ok_4(self): @@ -53,8 +53,8 @@ def test_asciimath2tex_ok_4(self): ) self.assertEqual( s, - r"$\bigcup_{2 \left(x + 1\right) = 1}^{n} " - r"\min \left\{2 x | x^{y + 2} \in \mathbb{N} \wedge " + r"${\bigcup}_{2 \left(x + 1\right) = 1}^{n} " + r"\min \left\{2 x | {x}^{y + 2} \in \mathbb{N} \wedge " r"\arccos \sqrt[3]{\frac{1}{3 x}} < i \rightarrow " r"\Omega < b , 5 = x\right\}$", ) @@ -71,8 +71,8 @@ def test_asciimath2tex_ok_5(self): ) self.assertEqual( s, - r"$\bigcup_{2 \left(x + 1\right) = 1}^{n} " - r"\min \left\{2 x | x^{y + 2} \in \mathbb{N} \wedge " + r"${\bigcup}_{2 \left(x + 1\right) = 1}^{n} " + r"\min \left\{2 x | {x}^{y + 2} \in \mathbb{N} \wedge " r"\arccos \sqrt[3]{\frac{1}{3 x}} < i \rightarrow " r"\Omega < b , 5 = x\right\}$", ) @@ -84,8 +84,8 @@ def test_asciimath2tex_ok_6(self): ) self.assertEqual( s, - r"$\left[\begin{matrix}1 & 2 \\ 2^{\left\vert3\right\vert} " - r"& \left(\displaystyle{\int} x^{2 \left(x - n\right)}\right) " + r"$\left[\begin{matrix}1 & 2 \\ {2}^{\left\vert3\right\vert} " + r"& \left(\displaystyle{\int} {x}^{2 \left(x - n\right)}\right) " r"\\ 2 & 4\end{matrix}\right]$", ) diff --git a/tests/test_Tex2ASCIIMath.py b/tests/test_Tex2ASCIIMath.py new file mode 100644 index 0000000..fdd08a8 --- /dev/null +++ b/tests/test_Tex2ASCIIMath.py @@ -0,0 +1,116 @@ +import unittest + +from py_asciimath.translator.translator import Tex2ASCIIMath + + +class TestTex2ASCIIMath(unittest.TestCase): + def setUp(self): + self.maxDiff = None + + def test_tex2asciimath_ok_1(self): + s = Tex2ASCIIMath( + inplace=True, parser="lalr", lexer="contextual", + ).translate( + r"$\left[\begin{matrix}" + r"\int x \mathrm{dx} \\ \log \left(x + 1\right)" + r"\end{matrix}\right]$", + ) + self.assertEqual(s, "[{:[int x text(d x)],[log (x + 1)]:}]") + + # def test_tex2asciimath_ok_2(self): + # s = Tex2ASCIIMath( + # inplace=True, parser="lalr", lexer="contextual", + # ).translate( + # "((1,2))int sin{x^2}/4pidxroot(5)(x_1^2+x_2^2)", displaystyle=True + # ) + # self.assertEqual( + # s, + # r"\[\left(\left(1 , 2\right)\right) \int \sin " + # r"\frac{{x}^{2}}{4} \pi \mathrm{dx} \sqrt[5]{{x}_{1}^{2} + {x}_{2}^{2}}\]", + # ) + + # def test_tex2asciimath_ok_3(self): + # s = Tex2ASCIIMath( + # inplace=True, parser="lalr", lexer="contextual", + # ).translate("lim_(N->oo) sum_(i=0)^N int_0^1 f(x)dx 3.14") + # self.assertEqual( + # s, + # r"${\lim}_{N \to \infty} {\sum}_{i = 0}^{N} " + # r"{\int}_{0}^{1} f \left(x\right) \mathrm{dx} 3.14$", + # ) + + # def test_tex2asciimath_ok_4(self): + # s = Tex2ASCIIMath( + # inplace=True, parser="lalr", lexer="contextual", + # ).translate( + # """uuu_{2(x+1)=1)^{n} + # min{ + # 2x|x^{y+2} in bbb(N) wedge arccos root(3}(frac{1}{3x}) < i + # rarr Omega < b, 5=x + # }""" + # ) + # self.assertEqual( + # s, + # r"${\bigcup}_{2 \left(x + 1\right) = 1}^{n} " + # r"\min \left\{2 x | {x}^{y + 2} \in \mathbb{N} \wedge " + # r"\arccos \sqrt[3]{\frac{1}{3 x}} < i \rightarrow " + # r"\Omega < b , 5 = x\right\}$", + # ) + + # def test_tex2asciimath_ok_5(self): + # parser = Tex2ASCIIMath() + # s = parser.translate( + # """uuu_{2(x+1)=1)^{n} + # min{ + # 2x|x^{y+2} in bbb(N) wedge arccos root(3}(frac{1}{3x}) < i + # rarr Omega < b, 5=x + # }""", + # pprint=True, + # ) + # self.assertEqual( + # s, + # r"${\bigcup}_{2 \left(x + 1\right) = 1}^{n} " + # r"\min \left\{2 x | {x}^{y + 2} \in \mathbb{N} \wedge " + # r"\arccos \sqrt[3]{\frac{1}{3 x}} < i \rightarrow " + # r"\Omega < b , 5 = x\right\}$", + # ) + + # def test_tex2asciimath_ok_6(self): + # parser = Tex2ASCIIMath(log=True) + # s = parser.translate( + # "[(1,2), (2^|: 3 :|, (dstyle int x^{2(x-n)})), (2,4)]" + # ) + # self.assertEqual( + # s, + # r"$\left[\begin{matrix}1 & 2 \\ {2}^{\left\vert3\right\vert} " + # r"& \left(\displaystyle{\int} {x}^{2 \left(x - n\right)}\right) " + # r"\\ 2 & 4\end{matrix}\right]$", + # ) + + # def test_tex2asciimath_ok_7(self): + # parser = Tex2ASCIIMath(log=True) + # s = parser.translate("langle [1,2], [2,int[3(x+1)]dx]:}") + # self.assertEqual( + # s, + # r"$\left\langle \begin{matrix}1 & 2 \\ 2 " + # r"& \int \left[3 \left(x + 1\right)\right] " + # r"\mathrm{dx}\end{matrix}\right.$", + # ) + + # def test_tex2asciimath_ok_8(self): + # parser = Tex2ASCIIMath(log=False) + # s = parser.translate("norm(x*y)<=norm(x)*norm(y)") + # self.assertEqual( + # s, + # r"$\left\lVert x \cdot y \right\rVert \le " + # r"\left\lVert x \right\rVert \cdot \left\lVert y \right\rVert$", + # ) + + # def test_tex2asciimath_ok_9(self): + # parser = Tex2ASCIIMath(log=False) + # s = parser.translate('A \\ B "setminus"') + # self.assertEqual(s, r"$A \setminus B \text{setminus}$") + + +if __name__ == "__main__": + unittest.main()