function tex = func2TeXtree(func)
% tex = func2TeXtree(func) convert a superposition of functions to TeX format
% 
% TeX usage:
% \usepackage{ecltree}
% \drawwith{\dottedline{1}}
% \setlength{\GapDepth}{1mm}
% \setlength{\GapWidth}{2mm}
% then insert the tex string
%
% Allowed names of functions {'g','c','l','q','w','m','u',} and
% {'d','p','t'} - see code below.
% Note: the leading \chunk{...} should be removed, if needed
%
% Examples
% y0= 'p[p[p[d[g[x],d[g[x],q[x]]],p[m[x],q[x]]],x],l[x]]'
% y1='p[p[g[x],g[x]],t[d[g[x],g[x]],g[x]]]';
% y2='d[p[p[p[g[x],g[x]],g[x]],x],l[x]]';
% y3='d[g[x],p[d[g[x],g[x]],q[x]]]';
% y4='p[t[p[d[g[x],c[x]],g[x]],x],g[x]]';
% y5='d[g[x],p[p[d[g[x],q[x]],g[x]],x]]';
% y6='p[g[x],p[p[g[x],g[x]],g[x]]]';
% y7='m[p[g[x],d[g[x],g[x]]],g[x]]';
% y8='p[p[g[x],p[g[x],g[x]]],g[x]]';
% y9='p[p[p[g[x],g[x]],g[x]],g[x]]';
%
% tex = func2TeXtree(y0)
%
% http://strijov.com

tex = f2t(func);
% Work notes
% the first element of a chunk is funcname
% the last element of a chunk is bracket
% a chunk can have one or two arguments, didvided by the ','
% pr was changed for w
% tn was changed for q
return

function tex = f2t(func)

head = beforebrackets(func);
[body, bnum] =  break2args(insidebrackets(func));

if ~isempty(func)
    switch head
        % no args-------------
        case 'x'    
            tex = '\chunk{$\x$}';
        % one arg-------------    
        case {'g','c','l','q','w','m','u',}            
            tex1= f2t(body{1}); %only one argument allowed
            tex = sprintf('\\chunk{\\begin{bundle}{%s}%s\\end{bundle}}',head,tex1);                       
        % two args-------------    
        case {'d','p','t'}
            switch head
                case 'd'
                    sgn = '$\div$';
                case 'p'    
                    sgn = '$+$';
                case 't'
                    sgn = '$\times$';
            end
            tex1= f2t(body{1}); %only two arguments allowed
            tex2= f2t(body{2});
            tex = sprintf('\\chunk{\\begin{bundle}{%s}%s%s\\end{bundle}}',sgn,tex1,tex2);                       
        otherwise
            tex = '';           
    end
else 
    tex='';
end
return

%==========================================================================
function inside = insidebrackets(func)
OPEN = '[';
CLOSE = ']';
if length(func) <= 2, inside = ''; return; end;

start = 0;
for i = 1:length(func)
    if func(i) == OPEN
        start = i+1;
        break
    end
end
if start == 0, error('bracket syntax error, no open bracket'); end;

brcount = -1;
for i = start+1:length(func)
    if func(i) == OPEN 
        brcount = brcount -1;
    elseif func(i) == CLOSE 
        brcount = brcount +1;
    end
    if brcount == 0
        stop = i-1;
        break
    end
end

if brcount < 0, error('bracket syntax error, no close bracket'); end;
inside = func(start:stop);
return

%==========================================================================
function before = beforebrackets (func)
OPEN = '[';
if length(func) == 0, before = ''; return; end;
before  = func;
for i=1:length(func)
    if func(i) == OPEN
        if i>1
            before = func(1:i-1);            
        else
            before = '';
        end
        break
    end    
end
return

%==========================================================================
function [args, argnum] = break2args(func)
OPEN = '[';
CLOSE = ']';
COMMA = ',';

ptr = 0;
args={};
argnum = 1;
ptrstart = 1;
while ptr<length(func)    
    ptr = ptr+1;
    switch func(ptr)
        case OPEN
            brcount = -1;
            for i = ptr+1:length(func)
                if func(i) == OPEN 
                    brcount = brcount -1;
                elseif func(i) == CLOSE 
                    brcount = brcount +1;
                end
                if brcount == 0
                    ptr = i;
                    break
                end
            end
            if brcount ~= 0, error('bracket syntax error, no close bracket'); end;
        case CLOSE
            error('bracket syntax error, extra close bracket');
        case COMMA
            ptrstop = ptr-1;
            if ptrstart>ptrstop, error('syntax error, double comma'); end
            args{argnum} = func(ptrstart:ptrstop);
            argnum = argnum + 1;
            ptrstart = ptr+1;
    end    
end
if ptrstart<=length(func), args{argnum} = func(ptrstart:length(func));  end
return