Repetitive replacement for expressing fractions in LaTeX I am converting natural math expressions with fractions to Latex code.

What I have done seems to work on examples I've tested, but I'm not sure if the algorithm is safe. And maybe the string part could be improved.

Maybe a better approach could be replace the / from left to right, but how in my case target the next?


By a generic pattern that matches the 3 cases at once.
By selecting specific / and passing tests on it and remplacing it after.


I don't know how to make that.

Some examples

((a)/(b))/(c)   -&gt;   \dfrac{\dfrac{a}{b}}{c}
(a)/((b)/(c))   -&gt;   \dfrac{a}{\dfrac{b}{c}}
(a)/(b)/(c)/(d)    -&gt;   \dfrac{\dfrac{\dfrac{a}{b}}{c}}{d}
((a)/(b))/((c)/(d)) -&gt;    \dfrac{\dfrac{a}{b}}{\dfrac{c}{d}}


My try :

function ToFrac (s)
    while s:find ("/") ~= nil
    do

    -- Remplace : \dfrac{}{}/() -&gt; \dfrac{\dfrac...}{}
    if ( s:find ( '\\dfrac%b{}%b{}/%b()' , j ) ~= nil )
    then
    x,y,num,den = s:find( '(\\dfrac%b{}%b{})/(%b())' )
    den = den:gsub( '.(.+).' , '%1' )
    s = s:gsub( '(\\dfrac%b{}%b{})/(%b())',
                            "\\dfrac{"..num.."}{"..den.."}" , 1 )
    end

    print ('### -- ', s)

    -- Remplace : ()/\dfrac{}{} -&gt; \dfrac{()}{\dfrac...}
    if ( s:find ( '(%b()/\\dfrac%b{}%b{}' ) ~= nil )
    then
    x,y,num,den = s:find( '((%b())/(\\dfrac%b{}%b{})' )
    num = num:gsub( '.(.+).' , '%1' )
    s = s:gsub( '((%b())/()\\dfrac%b{}%b{})',
                            "\\dfrac{"..num.."}{"..den.."}" , 1 )
    end

    print ('### -- ', s)

    -- Remplace : ()/() -&gt; \dfrac{}{}
    if ( s:find ( '%b()/%b()' , 1 ) ~= nil )
    then
        x,y,num,den = s:find( '(%b())/(%b())' )
        num = num:gsub( '.(.+).' , '%1' )
        den = den:gsub( '.(.+).' , '%1' )
        s = s:gsub( '(%b())/(%b())',
                        "\\dfrac{"..num.."}{"..den.."}" , 1 )
    end

    print ('### -- ', s)

    end -- while

    return (s)

end

s = "((a)/(b))/(c)"
print (s, ToFrac(s))

s = "(a)/((b)/(c))"
print (s, ToFrac(s))

s = "(a)/(b)/(c)/(d)"
print (s, ToFrac(s))

s = "((a)/(b))/((c)/(d))"
print (s, ToFrac(s))
You can use a recursive function with the pattern %b() as follows:

function ToFrac( sInput )
    local tStack = {}
    for sOperand in sInput:gmatch "%b()" do
        table.insert( tStack, sOperand:sub(2, -2) )
    end
    while true do
        if #tStack &lt;= 1 then break end
        local sNumerator = table.remove( tStack, 1 )
        if sNumerator:find '/' then sNumerator = ToFrac( sNumerator ) end
        local sDenominator = table.remove( tStack, 1 )
        if sDenominator:find '/' then sDenominator = ToFrac( sDenominator ) end
        table.insert( tStack, 1, ([[\dfrac{%s}{%s}]]):format(sNumerator, sDenominator) )
    end
    return tStack[1]
end


Here, I'm storing the operands as nodes in a stack. I tested the above function for the inputs:

local s = {
    "((a)/(b))/(c)",
    "(a)/((b)/(c))",
    "(a)/((b)/(c))/(d)",
    "(a)/(b)/(c)/(d)",
    "((a)/(b))/((c)/(d))",
}

for k, v in pairs(s) do
    print( v, ToFrac(v) )
end


The final results were:

((a)/(b))/(c)   \dfrac{\dfrac{a}{b}}{c}
(a)/((b)/(c))   \dfrac{a}{\dfrac{b}{c}}
(a)/((b)/(c))/(d)   \dfrac{\dfrac{a}{\dfrac{b}{c}}}{d}
(a)/(b)/(c)/(d) \dfrac{\dfrac{\dfrac{a}{b}}{c}}{d}
((a)/(b))/((c)/(d)) \dfrac{\dfrac{a}{b}}{\dfrac{c}{d}}