% --- Eingabeaufforderung und Parseaufrufe   H.Leiss, 2008
% Änderungen im Tokenizer 19.11.2015 (bei Satzende, ?!. )
% Ergänzt 25.11.2016 parsed/1

:- module(tokenizer,[read_sentence/3,tokenize/2,
                     satzende/0,parse/0,parsed/0,parse/1,parsed/1]).

parse :-
    write('Beende die Eingabe mit <!|?|.| .><Return>'),
    nl,read_sentence(user,Sentence,[]),
    tokenize(Sentence,Atomlist),
    startsymbol(S),
    addTree:translate1(S,Term,Baum),  
    addDifflists:translate(Term,TermExp,Atomlist,[]),
    nl,write('Aufruf: '), portray_clause(TermExp),
    call(TermExp), 
    write('Baum:   '), nl,showTree(Baum,8),nl,
    fail.
parse.

parsed :-
    write('Beende die Eingabe mit <Punkt><Return>'),
    nl,read_sentence(user,Sentence,[]),
    tokenize(Sentence,Atomlist),
    setof(Baum, parse(Atomlist, Baum), Trees),
    displayTrees(Trees).

parse(Atomlist,Baum) :-
    startsymbol(S),
    addTree:translate1(S,Term,Baum),
    addDifflists:translate(Term,Exp,Atomlist,[]),
    call(Exp).

% read_sentence(+Stream,-Sentence,+Seen)
read_sentence(Stream,Sentence,Seen) :-
    get0(Stream,Char),  
    read_sentence(Stream,Sentence,Char,Seen).

read_sentence(Stream,Sentence,Char,Seen) :-
    (Char = -1  % Dateiende
    -> reverse(Seen,Sentence)
    ; multiple_blanks(Char,Seen)
    -> read_sentence(Stream,Sentence,Seen)
    ; (Seen = [C|Cs], satzende([C,Char]))
    -> ((C = 63 ; C = 33) % ? und ! als Token abtrennen
       -> (Cs = [32|_] % falls vorher kein Leerzeichen
          -> reverse([C|Cs],Sentence)
          ; reverse([C,32|Cs],Sentence))
       ; ((C = 46, Cs = [32|_])
         -> reverse([C|Cs],Sentence) % Punkt als Token
         ; reverse(Cs,Sentence))     % Punkt weglassen 
       )
    ; Char = 10 % Zeilenumbruch als Leerzeichen lesen
    -> read_sentence(Stream,Sentence,[32|Seen]) 
    ; Char = 37 % Kommentar weglassen
    -> ignore_comment(Stream,Sentence,Seen)
    ; read_sentence(Stream,Sentence,[Char|Seen])).

ignore_comment(Stream,Sentence,Seen) :-
    get0(Stream,Char),
    ((Char = 10 ; Char = -1) % Zeilen-/Dateiende
    -> read_sentence(Stream,Sentence,Seen)
    ; ignore_comment(Stream,Sentence,Seen) 
    ).

multiple_blanks(Char,Seen) :-
    (Char = 32 ; Char = 10), % Leer|Newline
    (Seen = [32|_Cs] ; Seen = []).
                                
satzende([46,10]).  % <Punkt><Return>
satzende([63,10]).  % <Fragezeichen><Return>
satzende([33,10]).  % <Ausrufzeichen><Return>

% Für parse/1: damit man  Beispielsatz. % Kommentar
% in der Beispieldatei haben kann
satzende([46,32]).  % <Punkt><Leerzeichen> 
                    
% tokenize(+String,-Atomlist).
tokenize(String,Atomlist) :-
    name(Atom,String),
    concat_atom(AtomlistK,' ',Atom),
    entferne_komma(AtomlistK,Atomlist).

entferne_komma([AtomK|AtomeK],[Atom|Atome]) :-
    (atom_concat(Atom,',',AtomK)
    -> true
    ; Atom = AtomK),
    entferne_komma(AtomeK,Atome).
entferne_komma([],[]).

satzende :-
    write('Beende die Eingabe mit <Punkt><Return>'),
    nl,read_sentence(user,Sentence,[]),
    name(Satz,Sentence),
    nl,write('Eingabe:   '),writeq(Satz),
    tokenize(Sentence,Atomlist),
    nl,write('Atomliste: '),writeq(user,Atomlist).
    
parse(Dateiname) :-
   % atom_concat(Dateiname,'.aus',Ausgabe),
   % tell(Ausgabe), % ggf. Ausgabedatei öffnen
   open(Dateiname,read,Strom),
   parsen(Strom),
   close(Strom),
   % told,          % ggf. Ausgabedatei schließen
   nl,write('Fertig.').

parsen(Strom) :-
   read_sentence(Strom, Satz, []),
   (Satz = [] -> true  % Dateiende 
   ; tokenize(Satz,Atome),
       nl,writeq(Atome),nl,
       (setof(Baum,parse(Atome,Baum),Trees)
       -> showTrees(Trees,3), nl
       ; nl, tab(3),
           write('* keine Analysen gefunden *'),
           nl),
       parsen(Strom)   % weitere Sätze
   ).

parsed(Dateiname) :-
   tell('syntaxbaeume.tmp.dot'), % Ausgabedatei öffnen
   open(Dateiname,read,Strom),
   parsedn(Strom),
   close(Strom),
   told,          % Ausgabedatei schließen
   display_tree:viewgraph(syntaxbaeume),
   nl,write('\nBaumausgabe in \'syntaxbaeume.tmp.dot/ps\'.').

parsedn(Strom) :-
   read_sentence(Strom, Satz, []),
   (Satz = [] -> true  % Dateiende 
   ; tokenize(Satz,Atome),
       nl, 
       (setof(Baum,parse(Atome,Baum),Trees)
       -> display_tree:dot(Trees), nl 
       ; nl, write(user,'\n keine Analysen für: '),
           writeq(user,Atome), nl
       ),
       parsedn(Strom)   % weitere Sätze
   ).

