/* Zweck: Stelle Baumterme mit dem Programm /bin/dot graphisch dar.
   Autor: H.Leiss,                   28.7.2002, angepaßt an CL-2: 21.11.2005

   Siehe das Handbuch dazu unter Unix: man dot  ...

   Man bekommt dot von AT&T als Teil des Graphikpakets graphviz unter
      http://www.research.att.com/sw/tools/graphviz/download.html

   Ein Baumterm ist eine Liste [Cat|SubTrees], worin
   - Cat eine einfache Kategorie der Grammatik ist
     (Kategoriename als Funktionszeichen, Merkmale als Argumente),
   - SubTrees die Baumterme der direkten Teilbäume sind.

   Der Baum ordnet die Blätter auf einer Grundlinie entsprechend den Wörtern
   des Eingabeausdrucks an.

*/

:- module(display_tree,[displayTrees/1,displayTree/1]).
                        
/* Schreibe eine Liste <Terme> von Prolog-Termen als Bäume im .dot-Format auf die
   Datei <Datei>.tmp.dot : */

showTrees(Terme,Datei) :-
        concat(Datei,'.tmp.dot',File),
        tell(File),
        dot(Terme),
        told.

dot([Term|Terme]) :-
        nl,
        (ground(Term) ->
            write('digraph syntaxbaum {'),
            write('\ncenter=true; size=\"7.5,14\";\
                   \nratio=compress; ordering=out;\
                   \nedge[dir=none]; node[shape=plaintext];\n'),
            drawTree(Term),
            write('}')
        ; write(user,'Fehler: der darzustellende Term \"'),
            writeq(user,Term),
            write(user, '\" enthält freie Variable!\n')
        ),
        dot(Terme).
dot([]).
drawTree(Term) :-
    drawTree(Term,0,_,[],[],BlattfolgeR,[]),
    reverse(BlattfolgeR,Blattfolge),
    order(Blattfolge).

order(Blattfolge) :-
    write('{ rank=same ; '),
    write_list(Blattfolge,' ; '),
    write('};\n'),
    write('subgraph {edge[style=invis]; '), % Blaetter
    write_list(Blattfolge,' -> '),          % auf einer Linie
    write(' }\n').                          % anordnen

write_list([A,B|Bs],Atom) :-
    write(A),write(Atom),write_list([B|Bs],Atom).
write_list([A],_) :-
    write(A).
write_list([],_).

/* drawTree(+Term,+Wurzelnummer,-naechste unbenutzte Nummer,4 Akkumulatoren)  */

drawTree([Term],N,K,AkkL,AkkR,[N|AkkL],AkkR) :-
    atom(Term),
    !,
    write(N),
    write(' [fontcolor = blue, label = "'),write(Term),write('"];'),
    write('\n'),
    K is N+1.

drawTree([Kategorie,(Arg1,Arg2)],N,K,AkkL,_,NAkkL,NAkkR) :-
    !,
    write(N),
    write(' [label = "'),write(Kategorie),write('"];\n'),
    M is N+1,
    drawTrees([Arg1],N,M,L,AkkL,[],NAkkL,[]),
    drawTrees([Arg2],N,L,K,[],[],NAkkR,[]).

drawTree([Kategorie|Args],N,K,AkkL,AkkR,AkkLN,AkkRN) :-
    !,
    write(N),write(' [label = \"'),write(Kategorie),write('\"];\n'),
    M is N+1,
    drawTrees(Args,N,M,K,AkkL,AkkR,AkkLN,AkkRN).

list([]).
list([_|L]) :- list(L).

/* Nachfolger von Baum N, ab Nummer M bis Nummer K fuer deren Knoten */

drawTrees([Arg|Args],N,M,K,AkkL,AkkR,NAkkL,NAkkR) :-
    write(N), write(' -> '), write(M), write(' ;\n'),        
    drawTree(Arg,M,K1,AkkL,AkkR,NAkkL1,NAkkR1),
    drawTrees(Args,N,K1,K,NAkkL1,NAkkR1,NAkkL,NAkkR).

drawTrees([],_,M,M,AkkL,AkkR,AkkL,AkkR).

/* Anzeigen der Bäume am Bildschirm: */

displayTree(Term) :-
    displayTrees([Term]).

displayTrees(Terme) :-
    showTrees(Terme,testbaum),
    viewgraph(testbaum).

viewgraph(Datei) :-
    concat_atom(['dot -Tps ',Datei,'.tmp.dot ',' -o',Datei,'.tmp.ps '],Command1),
    % Kleiner: concat_atom(['gv -magstep -2 ',Datei,'.tmp.ps &\n'],Command2),
    concat_atom(['gv ',Datei,'.tmp.ps &\n'],Command2),
    shell(Command1),
    shell(Command2).

/* Beispiel: Baumkodierung wie in CL-2, nicht wie in Satzgrammatik

displayTree([np([def, 3, mask], [sg, nom]),
               [det([def], [mask, sg, nom]), [der]],
               [rn([mask], [sg, nom]), ['Planet']],
               [np([def, 3, fem], [sg, gen]),
                  [det([def], [fem, sg, gen]), [der]],
                  [en([fem], [sg, nom]), ['Venus']]]]).

*/


