Translate in-line equations to TeX code (Any Package?)
This is an unusual answer, because, while it does convert the OP's code into LaTeX code, that code is stored in a way to be read by the computer and not the human eye. Thus, a more appropriate way to characterize this answer is that it provides an interpreter, written in LaTeX, to convert and present equations provided in a non-LaTeX format. However, the most recent update now has the ability to convert that internal code into a detokenized translation of the relevant LaTeX code.
THIS ANSWER HAS BEEN MUCH UPDATED:
EDITED so that select math operators and greek letters may be parsed without being escaped (e.g., cos x = beta
is parsed properly). More can be added.
EDITED so that square bracketes [...]
may be used as non-visible grouping characters.
Re-EDITED to automatically convert /
into \frac
style (thanks to David's description of \over
at Practical consequences of using \over vs. \frac?).
EDITED to provide automation.
EDITED to provide translation, as well as interpretive rendering.
INTERPRETING EQUATIONS
This answer automates the process of using a LaTeX macro to interpret equations expressed in a non-LaTeX user syntax. I provide the LaTeX macro \interpreteq{}
in which a non-latex equation is passed, parsed in 7 stages, reconstituted, and presented as a LaTeX equation.
The really neat thing about this approach is that the equation input, in the user's non-LaTeX format is parsed into the mathematical "genes" that make up an equation according to the order of operations. Then, each gene is converted into LaTeX format, and the resulting genes are automatically reconstituted into a DNA strand of executable LaTeX code.
However, that DNA strand of executable code is indirectly expressed in the internal representation of the listofitems
package, which was used to mathematically slice up the original non-LaTeX equation. This internal representation of the equation (which is quite bizarre to look at), can be displayed, as proof of the method, by way of \detokenize\expandafter{\Z}
at the conclusion of the \interpreteq
. This will provide the tokens that are actually executed to present to LaTeX form of the equation.
So, for example, take, the user-formatted (non-LaTeX) equation:
x = a_avg + ([x-1] /b_trans)^(-y^[-x])
This string of tokens is parsed by the listofitems
package into the \Q
list, using the following parsing heirarchy:
\setsepchar[@]{=@(||)||[||]@^@/||*@+||-@_@alpha||beta||pi||cos||sin||tan}
The first layer of parsing is to find instances of =
. All code to the left of the =
is stored in \Q[1]
, and all code to the right of [the 1st] =
(and to the left of the 2nd =
) is stored in \Q[2]
. The separator at this level (i.e., the =
) is stored in \Qsep[1]
.
For each piece, \Q[1]
and \Q[2]
, the second level of parsing occurs which looks for all instances of (
, )
, [
, and ]
. So, for example, \Q[2,3]
indicates that strand of the [non-LaTeX] DNA to the right of the =
and prior to the 3rd instance of the paren or bracket separators.
This procedure continues to 7+ levels of parsing according to a PEMDAS order of operations:
=
(
,)
,[
, and]
^
/
and*
+
and-
_
alpha
,beta
,pi
,cos
,sin
,tan
and other functions, as needed
Anything that is not one of the parsable separators will end up in some low-level \Q[.,.,...]
gene entry. However, all the parsable separators will end up in a \Qsep[.,.,...]
separator-gene entry. And it is these \Qsep
entries that require conversion into LaTeX format, and this procedure is carried out by the \QS
macro:
\def\QS[#1]{%
\if+\Qsep[#1]+\else%
\if-\Qsep[#1]-\else%
\if/\Qsep[#1]\over\else%
\if=\Qsep[#1]=\else%
\if^\Qsep[#1]^\else%
\if(\Qsep[#1]\bgroup\left(\else%
\if)\Qsep[#1]\right)\egroup\else%
\if[\Qsep[#1]\bgroup\else%
\if]\Qsep[#1]\egroup\else%
\if*\Qsep[#1]\cdot\else%
\if_\Qsep[#1]\expandafter\theund\else%
\csname \Qsep[#1]\endcsname\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi%
}
The DNA is then reconstituted as a string of calls to an indexed succession of \Q[]
and \QS[]
(converted \Qsep[]
) genes. They all appear in the original order as sliced. So, for instance, the user-format equation (x = a_avg + ([x-1] /b_trans)^(-y^[-x])
), once sliced and converted by \interpreteq
, is reconstituted as a DNA strand by way of the following expression:
\Q [1,1,1,1,1,1,1]\QS [1]\Q [2,1,1,1,1,1,1]\QS [2,1,1,1,1,1]\Q [2,1,1,1,1,2,1]\QS
[2,1,1,1,1]\Q [2,1,1,1,2,1,1]\QS [2,1]\Q [2,2,1,1,1,1,1]\QS [2,2]\Q [2,3,1,1,1,1,1]\QS
[2,3,1,1,1]\Q [2,3,1,1,2,1,1]\QS [2,3]\Q [2,4,1,1,1,1,1]\QS [2,4,1,1]\Q [2,4,1,2,1,1,1]\QS
[2,4,1,2,1,1]\Q [2,4,1,2,1,2,1]\QS [2,4]\Q [2,5,1,1,1,1,1]\QS [2,5,1]\Q [2,5,2,1,1,1,1]\QS
[2,5]\Q [2,6,1,1,1,1,1]\QS [2,6,1,1,1]\Q [2,6,1,1,2,1,1]\QS [2,6,1]\Q [2,6,2,1,1,1,1]\QS
[2,6]\Q [2,7,1,1,1,1,1]\QS [2,7,1,1,1]\Q [2,7,1,1,2,1,1]\QS [2,7]\Q [2,8,1,1,1,1,1]\QS
[2,8]\Q [2,9,1,1,1,1,1]
And, based on the genes that are in \Q
and \QS
, the result looks like that desired, namely
TRANSLATING EQUATIONS
Translation is achieved either in macro form, \translateeq{}
or by way of a translation environment of space separated equations
\begin{translateeqs}% NO BLANK LINE IS PERMITTED HERE
EQ1
EQ2
...
EQn
\end{translateeqs}% NO BLANK LINE IS PERMITTED BEFORE HERE
This was achieved merely by temporarily redefining several key macros in the process and using \protected@edef
to expand the \Q
and \QS
genes into their relevant LaTeX code. Then the resulting equations are not rendered as before, but instead presented as detokenized LaTeX code.
The translations can, in practice, be done in a separate document, with the results being copied and pasted from the resulting PDF into a target source document.
THE MWE
The 5 equations that you will see in the MWE below, both interpreted and translated, are input in non-LaTeX form. Notable highlights of the conversion process include the handling of multi-character subscripts without grouping, recognizing a number of textual (not macro) mathematical functions and greek letter names (more can be added), auto-converting /
into fractions, auto-sizing parens, converting *
into \cdot
, etc. Here are the 5 equations:
cos(1/s) = f*g
f(x) = y^(2*x) =beta
f(x) = pi * y^[((2/x)^3 + [B/x_i])^n] =(z/B)^(2/x_i)
f(x) = pi * y^[((2/x)^3 + B/x_i )^n] =(z/B)^(2/x_i)
x = a_avg + ([x-1] /b_trans)^(-y^[-x])
Here is the MWE:
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{listofitems,ifthen}
\def\QS[#1]{%
\if+\Qsep[#1]+\else%
\if-\Qsep[#1]-\else%
\if/\Qsep[#1]\over\else%
\if=\Qsep[#1]=\else%
\if^\Qsep[#1]^\else%
\if(\Qsep[#1]\bgroup\left(\else%
\if)\Qsep[#1]\right)\egroup\else%
\if[\Qsep[#1]\bgroup\else%
\if]\Qsep[#1]\egroup\else%
\if*\Qsep[#1]\cdot\else%
\if_\Qsep[#1]\expandafter\theund\else%
\csname \Qsep[#1]\endcsname\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi%
}%
\def\theund#1[#2]{_{\mathrm{#1[#2]}}}%
\setsepchar[@]{=@(||)||[||]@^@/||*@+||-@_@alpha||beta||pi||cos||sin||tan}
\makeatletter
\def\gQ[#1]{\edef\tmp{#1}\expandafter\g@addto@macro\expandafter\Z%
\expandafter{\expandafter\Q\expandafter[\tmp]}}
\def\gQS[#1]{\edef\tmp{#1}\expandafter\g@addto@macro\expandafter\Z%
\expandafter{\expandafter\QS\expandafter[\tmp]}}
\makeatother
\newcommand\interpreteq[1]{%
\def\Z{}%
\greadlist*\Q{#1}%
\presentQ%
\Z%
}
\newcounter{lindex}
\def\presentQ{% =
\setcounter{lindex}{0}%
\whiledo{\value{lindex}<\listlen\Q[]}{%
\stepcounter{lindex}%
\presentQA[\thelindex]%
\ifnum\value{lindex}<\listlen\Q[]\relax%
\gQS[\thelindex]%
\fi%
}%
}
\newcounter{lindexA}
\def\presentQA[#1]{% ()
\setcounter{lindexA}{0}%
\whiledo{\value{lindexA}<\listlen\Q[#1]}{%
\stepcounter{lindexA}%
\presentQB[#1,\thelindexA]%
\ifnum\value{lindexA}<\listlen\Q[#1]\relax%
\gQS[#1,\thelindexA]%
\fi%
}
}
\newcounter{lindexB}
\def\presentQB[#1]{% ^
\setcounter{lindexB}{0}%
\whiledo{\value{lindexB}<\listlen\Q[#1]}{%
\stepcounter{lindexB}%
\presentQC[#1,\thelindexB]%
\ifnum\value{lindexB}<\listlen\Q[#1]\relax%
\gQS[#1,\thelindexB]%
\fi%
}
}
\newcounter{lindexC}
\def\presentQC[#1]{% /*
\setcounter{lindexC}{0}%
\whiledo{\value{lindexC}<\listlen\Q[#1]}{%
\stepcounter{lindexC}%
\presentQD[#1,\thelindexC]%
\ifnum\value{lindexC}<\listlen\Q[#1]\relax%
\gQS[#1,\thelindexC]%
\fi%
}
}
\newcounter{lindexD}
\def\presentQD[#1]{% +-
\setcounter{lindexD}{0}%
\whiledo{\value{lindexD}<\listlen\Q[#1]}{%
\stepcounter{lindexD}%
\presentQE[#1,\thelindexD]%
\ifnum\value{lindexD}<\listlen\Q[#1]\relax%
\gQS[#1,\thelindexD]%
\fi%
}
}
\newcounter{lindexE}
\def\presentQE[#1]{% _
\setcounter{lindexE}{0}%
\whiledo{\value{lindexE}<\listlen\Q[#1]}{%
\stepcounter{lindexE}%
\presentQF[#1,\thelindexE]%
\ifnum\value{lindexE}<\listlen\Q[#1]\relax%
\gQS[#1,\thelindexE]%
\fi%
}
}
\newcounter{lindexF}
\def\presentQF[#1]{% alpha beta pi cos sin tan
\setcounter{lindexF}{0}%
\whiledo{\value{lindexF}<\listlen\Q[#1]}{%
\stepcounter{lindexF}%
\gQ[#1,\thelindexF]%
\ifnum\value{lindexF}<\listlen\Q[#1]\relax%
\gQS[#1,\thelindexF]%
\fi%
}
}
% THESE ARE THE REDEFITIIONS FOR TRANSLATION
\usepackage{environ}
\def\QSALT[#1]{%
\if+\Qsep[#1]+\else%
\if-\Qsep[#1]-\else%
\if/\Qsep[#1]\over\else%
\if=\Qsep[#1]=\else%
\if^\Qsep[#1]^\else%
\if(\Qsep[#1]{\left(\else%
\if)\Qsep[#1]\right)}\else%
\if[\Qsep[#1]{\else%
\if]\Qsep[#1]}\else%
\if*\Qsep[#1]\cdot\else%
\if_\Qsep[#1]\expandafter\theundALT\else%
\expandafter\noexpand\csname \Qsep[#1]\endcsname\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi%
}%
\def\theundALT#1[#2]{_{\noexpand\mathrm{#1[#2]}}}%
\makeatletter
\newcommand\translateeq[1]{%
\bgroup%
\let\QS\QSALT%
\def\Z{}%
\greadlist*\Q{#1}%
\presentQ%
\protected@edef\ZZ{\Z}
\par\medskip\noindent%
\parbox{\linewidth}{\detokenize\expandafter{\ZZ}}%
\par\medskip%
\egroup%
}
\makeatother
\NewEnviron{translateeqs}{\expandafter\nexteqn\BODY\par\relax}
\long\def\nexteqn#1\par#2\relax{%
\translateeq{#1}\ifx\relax#2\else\nexteqn#2\relax\fi%
}
\begin{document}
\textbf{INTERPRETATING EQUATIONS}
\[
\interpreteq{cos(1/s) = f*g}
\]
\[
\interpreteq{f(x) = y^(2*x) =beta}
\]
\[
\interpreteq{f(x) = pi * y^[((2/x)^3 + [B/x_i])^n] =(z/B)^(2/x_i)}
\]
\[
\interpreteq{f(x) = pi * y^[((2/x)^3 + B/x_i )^n] =(z/B)^(2/x_i)}
\]
\[
\interpreteq{x = a_avg + ([x-1] /b_trans)^(-y^[-x])}
\]
This is the code ``DNA'' that expresses the above equation:
\detokenize\expandafter{\Z}% COPY/PASTE RESULT OF THIS FROM PDF TO BELOW
See? I copied/pasted it into equation mode and get the same result.
\[
\Q [1,1,1,1,1,1,1]\QS [1]\Q [2,1,1,1,1,1,1]\QS [2,1,1,1,1,1]\Q [2,1,1,1,1,2,1]\QS
[2,1,1,1,1]\Q [2,1,1,1,2,1,1]\QS [2,1]\Q [2,2,1,1,1,1,1]\QS [2,2]\Q [2,3,1,1,1,1,1]\QS
[2,3,1,1,1]\Q [2,3,1,1,2,1,1]\QS [2,3]\Q [2,4,1,1,1,1,1]\QS [2,4,1,1]\Q [2,4,1,2,1,1,1]\QS
[2,4,1,2,1,1]\Q [2,4,1,2,1,2,1]\QS [2,4]\Q [2,5,1,1,1,1,1]\QS [2,5,1]\Q [2,5,2,1,1,1,1]\QS
[2,5]\Q [2,6,1,1,1,1,1]\QS [2,6,1,1,1]\Q [2,6,1,1,2,1,1]\QS [2,6,1]\Q [2,6,2,1,1,1,1]\QS
[2,6]\Q [2,7,1,1,1,1,1]\QS [2,7,1,1,1]\Q [2,7,1,1,2,1,1]\QS [2,7]\Q [2,8,1,1,1,1,1]\QS
[2,8]\Q [2,9,1,1,1,1,1]
\]
\textbf{TRANSLATING EQUATIONS}
\begin{translateeqs}% NO BLANK LINE IS PERMITTED HERE
cos(1/s) = f*g
f(x) = y^(2*x) =beta
f(x) = pi * y^[((2/x)^3 + [B/x_i])^n] =(z/B)^(2/x_i)
f(x) = pi * y^[((2/x)^3 + B/x_i )^n] =(z/B)^(2/x_i)
x = a_avg + ([x-1] /b_trans)^(-y^[-x])
\end{translateeqs}% NO BLANK LINE IS PERMITTED BEFORE HERE
\translateeq{x = a_avg + ([x-1] /b_trans)^(-y^[-x])}
\end{document}
if eq.txt contains lines like
x = a_avg + ((x-1)/b_trans)^(-y^(-x))
then a simple edit line such as
sed -e 's/(/{(/g' -e 's/)/)}/g' -e 's/\//\\over /g' -e 's/_\([a-z]*\)/_{\\mathrm{\1}}/g' -e 's/.*/$\0$/' eq.txt
will output
$x = a_{\mathrm{avg}} + {({(x-1)}\over b_{\mathrm{trans}})}^{(-y^{(-x)})}$
for each line
which when typeset as
\documentclass{article}
\begin{document}
$x = a_{\mathrm{avg}} + {({(x-1)}\over b_{\mathrm{trans}})}^{(-y^{(-x)})}$
\end{document}
produces
I used sed here but you could use perl or lua or your editor search/replace.
Actually you need to work a bit harder with the regex on the brackets (note one )
slipped down... ) but this is I hope enough to show the basic idea.