[Tex/LaTex] Converting C-like math expressions to LaTeX

math-modepackagestools

Is there any (open source) solution for converting math expressions from a C-like expression syntax to LaTeX? When I say "solution", I mean either from outside LaTeX (i.e: an external program that makes the conversion and outputs LaTeX syntax), or from within LaTeX (i.e: some package that takes C-like math and displays it in formula format on-the-fly).

As an example, I'm asking for converting from 3*c/(a+2) to \frac{3 c}{a + 2} and yes, I know the conversion is not unique, as 3 \frac{c}{a + 2} would also be a legal conversion.

I know some open source CAS packages, such as Maxima or SymPy can do this, but I was wondering if there's any other simpler solution with a lower overhead, not needing to install a full CAS system.

Best Answer

(I rewrote the code to make it consist of three separate files: A driver tex file that produces the screenshot; a style file (loaded by the driver file) that sets up the main user macro, called \prettymath; and a lua file (loaded from the style file via a dofile instruction) that performs the actual work.)

The following LuaLaTeX-based solution should not be viewed as a full-blown tool. For now, it's mainly intended to showcase the usefulness and versatility of some of Lua's string functions for the purpose of tackling the problem at hand.

It processes ** exponential notation, deletes single * instances, converts the roman-letter representations of selected lowercase Greek letters (e.g., alpha and pi) to their "native" Greek-character glyphs, and pretty-prints integral expressions, selected three-letter mathop functions (sin, cos, tan, and det -- it should be straightforward to extend this list) as well as square roots and fractions. It can handle nested fractions and square roots. Naturally, this list is far from complete. Hopefully, the code shown below is reasonably self-explanatory so that (I hope) it's not too difficult to handle other cases.

enter image description here


The driver file:

% !TeX program = lualatex
% Test file to check out operation of 'cmath2latex' package
\documentclass{article}
\usepackage{cmath2latex} 

% set up three test strings
\newcommand\mystringa{sqrt(3**(x)*(a*sin(exp(theta)) 
  *cos(2*pi)) / (det (A)*tan(gamma)) ) }
\newcommand\mystringb{3*c/(a+2), 1/pi, pi/2, 2*pi/3, a/b, 
  x/(y+z), (x+y)/z, (a/b)/(c/d)}
\newcommand\mystringc{sqrt( sqrt(sqrt(256))), Integral 
  (sqrt((2**(y))/(y)) , y )}

\begin{document}
\everymath{\displaystyle} % just for this example

\verb&sqrt(3**(x)*(a*sin(exp(theta))*cos(2*pi)) / (det (A)*tan(gamma)) )&

\prettymath{\mystringa}

\bigskip
\verb&3*c/(a+2), 1/pi, pi/2, 2*pi/3, a/b, x/(y+z), (x+y)/z, (a/b)/(c/d)&

\prettymath{\mystringb}

\bigskip
\verb&sqrt( sqrt(sqrt(256))), Integral (sqrt((2**(y))/y) , y )&

\prettymath{\mystringc}
\end{document}

The style file; I suggest you call it cmath2latex.sty:

% !TeX program = lualatex
\ProvidesPackage{cmath2latex}[2017/01/09, version 0.01]

\usepackage{luacode} % for "\luastring" macro
\usepackage{amsmath} % for "\ensuremath" macro

%% Load the Lua code
\directlua{dofile("cmath2latex.lua")} 

%% The LaTeX macro "\prettymath" calls the Lua function
%% "prettymath" and outputs the result in math mode
\newcommand\prettymath[1]{\ensuremath{\directlua{%
    tex.sprint(prettymath(\luastring{#1}))}}}

The file that contains the Lua code; I suggest you call it "cmath2latex.lua":

-- cmath2latex.lua
-- This file is loaded by cmath2latex.sty via a dofile call

-- "prettymath" is called by the "\prettymath" LaTeX macro
-- (which is defined in "prettymath.sty")

function prettymath ( s )

-- exponential notation
  s = s:gsub ( "%*%*%s-(%b())" , do_exp )

-- multiplication: delete all single instances of "*"
  s = s:gsub ( "%*" , "" )

-- integrals
  s = s:gsub ( "Integral%s-(%b())", do_integral )

-- some Greek letters
  s = s:gsub ( "alpha" , do_gr_letter )
  s = s:gsub ( "beta"  , do_gr_letter )
  s = s:gsub ( "gamma" , do_gr_letter )
  s = s:gsub ( "Gamma" , do_gr_letter )
  s = s:gsub ( "delta" , do_gr_letter )
  s = s:gsub ( "Delta" , do_gr_letter )
  s = s:gsub ( "theta" , do_gr_letter )
  s = s:gsub ( "pi"    , do_gr_letter )
  s = s:gsub ( "Pi"    , do_gr_letter )

-- some pre-defined 3-letter operators w/ args in parens
  s = s:gsub ( "(cos)%s-(%b())" , do_mathop )
  s = s:gsub ( "(det)%s-(%b())" , do_mathop )
  s = s:gsub ( "(exp)%s-(%b())" , do_mathop )
  s = s:gsub ( "(lim)%s-(%b())" , do_mathop )
  s = s:gsub ( "(sin)%s-(%b())" , do_mathop )
  s = s:gsub ( "(tan)%s-(%b())" , do_mathop )

-- sqrt function
  for i=1,3 do  -- allow for nested sqrt expressions
    s = s:gsub ( "sqrt%s-(%b())", do_sqrt )
  end

-- fraction expressions
  s = s:gsub ( "(%b())%s-/%s-(%b())" ,    do_frac_2parens )
  s = s:gsub ( "([\\%w]+)%s-/%s-(%b())" , do_frac_1parens_numer )
  s = s:gsub ( "(%b())%s-/%s-([\\%w]+)" , do_frac_1parens_denom )
  s = s:gsub ( "([\\%w]+)%s-/%s-([\\%w]+)", "\\frac{%1}{%2}" )

-- Feel free to add more string.gsub ops as needed...

-- Return the modified string
return s

end -- end of 'prettymath' function


-- Finally, set up the helper Lua functions

function strip ( x ) -- remove first and last char of string "x"
  return x:sub(2,-2)
end
function do_exp ( u )
  return ( "^{" .. strip(u) .. "}"  )
end
function do_gr_letter ( u )
  return ( "\\"..u )
end
function do_mathop ( u , v )
  return ( "\\" .. u .. v )
end
function do_integral ( u )
  u = strip(u)
  return ( "\\int\\! " ..  u:gsub ( "^(.*),(.*)$" ,
      "%1 \\,\\mathrm{d} %2" ) )
end
function do_sqrt ( u )
  return ( "\\sqrt{" .. strip(u) .. "}" )
end

-- process expressions involving fractions

function do_frac_1parens_numer ( u , v )
  return ( "\\frac{" .. u .. "}{" .. strip(v) .. "}" )
end
function do_frac_1parens_denom ( u , v )
  return ( "\\frac{" .. strip(u) .. "}{" .. v .. "}" )
end
function do_frac_2parens ( u , v )
  return ( "\\frac{" .. strip(u) .. "}{" .. strip(v) .."}" )
end
Related Question