:- module(flexion_slex,[erzeuge_vollformenlexikon/1]).
:- use_module([wortformen]). 

flektiere(Stammform,Vollform) :-
    lex(Stammform,Wortart,_,Flexionsklasse),
    form(Wortart,Formmerkmale),
    beuge(Wortart,Flexionsklasse,Stammform,
          Formmerkmale,Vollform).

beuge(v,Flexionsklasse,Stammform,Form,Vollform) :-
    konjugiere(Flexionsklasse,Stammform,Form,Vollform).
beuge(Wortart,Flexionsklasse,Stammform,Form,Vollform) :-
    (Wortart = n ; Wortart = rn ; Wortart = en),
    dekliniere(Flexionsklasse,Stammform,Form,Vollform).

flexion(Stammform) :-
    ( lex(Stammform,v,_,Flexionsklasse)        % Verbstamm?
    ->  verbflexion(Flexionsklasse,Stammform)
    ; lex(Stammform,Wortart,_,Flexionsklasse), % Nomenstamm?
        member(Wortart,[n,rn,en])
    ->  nomenflexion(Flexionsklasse,Stammform) 
    ; nl, 
        write('Das Stammlexikon hat keinen Eintrag zu: '),
        write(Stammform)
    ).
        
% verbflexion(+Konjugationsklasse,+Stammform)
verbflexion(Konjugationsklasse,Stammform) :-
    form(vfin,Formmerkmale),
    konjugiere(Konjugationsklasse,Stammform,
               Formmerkmale,Vollform),
    write(Formmerkmale),write(': '),write(Vollform),nl,
    fail.              % weitere Formmerkmale suchen
verbflexion(_,_).      % fertig.
% konjugiere(+Konjugationsklasse,+Infinitiv,
%            ?[Pers,Num,Temp,Mod],-Vollform)

% --- Regelmaessige Konjugation (Finite Formen) ---

konjugiere(rg(_),Infinitiv,[Pers,Num,Temp,Mod],Vollf) :-  
    concat(Stamm,'en',Infinitiv),
    (dentalstamm(Stamm)
    -> konjugation(rge,[Pers,Num,Temp,Mod],Endung)  
    ;  konjugation(rg, [Pers,Num,Temp,Mod],Endung)
    ),
    concat(Stamm,Endung,Vollf).

dentalstamm(Stamm) :- 
    concat(_,'d',Stamm) ; concat(_,'t',Stamm).

% -- regelmaessige Konjugation --

konjugation(rg,[1,sg,praes,ind], 'e').
konjugation(rg,[1,sg,praes,konj],'e').
konjugation(rg,[1,sg,praet,ind], 'te').
konjugation(rg,[1,sg,praet,konj],'te').

konjugation(rg,[1,pl,praes,ind], 'en').
konjugation(rg,[1,pl,praes,konj],'en').
konjugation(rg,[1,pl,praet,ind], 'ten').
konjugation(rg,[1,pl,praet,konj],'ten').

konjugation(rg,[2,sg,praes,ind], 'st').
konjugation(rg,[2,sg,praes,konj],'est').
konjugation(rg,[2,sg,praet,ind], 'test').
konjugation(rg,[2,sg,praet,konj],'test').

konjugation(rg,[2,pl,praes,ind], 't').
konjugation(rg,[2,pl,praes,konj],'et').
konjugation(rg,[2,pl,praet,ind], 'tet').
konjugation(rg,[2,pl,praet,konj],'tet').

konjugation(rg,[3,sg,praes,ind], 't').
konjugation(rg,[3,sg,praes,konj],'e').
konjugation(rg,[3,sg,praet,ind], 'te').
konjugation(rg,[3,sg,praet,konj],'te').

konjugation(rg,[3,pl,praes,ind], 'en').
konjugation(rg,[3,pl,praes,konj],'en').
konjugation(rg,[3,pl,praet,ind], 'ten').
konjugation(rg,[3,pl,praet,konj],'ten').

% ---- mit e-Erweiterung:

konjugation(rge,[1,sg,praes,ind], 'e').
konjugation(rge,[1,sg,praes,konj],'e').
konjugation(rge,[1,sg,praet,ind], 'ete').
konjugation(rge,[1,sg,praet,konj],'ete').

konjugation(rge,[1,pl,praes,ind], 'en').
konjugation(rge,[1,pl,praes,konj],'en').
konjugation(rge,[1,pl,praet,ind], 'eten').
konjugation(rge,[1,pl,praet,konj],'eten').

konjugation(rge,[2,sg,praes,ind], 'est').
konjugation(rge,[2,sg,praes,konj],'est').
konjugation(rge,[2,sg,praet,ind], 'etest').
konjugation(rge,[2,sg,praet,konj],'etest').

konjugation(rge,[2,pl,praes,ind], 'et').
konjugation(rge,[2,pl,praes,konj],'et').
konjugation(rge,[2,pl,praet,ind], 'etet').
konjugation(rge,[2,pl,praet,konj],'etet').

konjugation(rge,[3,sg,praes,ind], 'et').
konjugation(rge,[3,sg,praes,konj],'e').
konjugation(rge,[3,sg,praet,ind], 'ete').
konjugation(rge,[3,sg,praet,konj],'ete').

konjugation(rge,[3,pl,praes,ind], 'en').
konjugation(rge,[3,pl,praes,konj],'en').
konjugation(rge,[3,pl,praet,ind], 'eten').
konjugation(rge,[3,pl,praet,konj],'eten').

konjugiere(urg(_,(V1,V2,V3,V4),Ablautposition),
           Infinitiv,[Pers,Num,Temp,Mod],Vollform) :-
    concat(Stamm,en,Infinitiv),        % Zerlege z.B.
    LaengeVor is Ablautposition - 1,   % anfangen =
    sub_atom(Stamm,0,LaengeVor,_,Vor), % anf|a | ng |en
    infix(Vor,V1,Nach,Stamm),          % Vor|V1|Nach|en
    verbform((Vor,Nach),(V1,V2,V3,V4),
             [Pers,Num,Temp,Mod],Vollform).

% infix(+Vor,+Mitte,-Nach,+Kette) oder s.u.
% infix(+Vor,+Mitte,+Nach,-Kette) 
infix(Vor,Mitte,Nach,Kette) :-
    concat(Vor,Mitte,Praefix),
    concat(Praefix,Nach,Kette).

verbform((Vor,Nach),(V1,V2,_V3,_V4),
         [Pers,Num,praes,ind],Vollform) :-
    ( not(member([Pers,Num],[[2,sg],[3,sg]])),
      infix(Vor,V1,Nach,Stamm)
    ; member([Pers,Num],[[2,sg],[3,sg]]),
      infix(Vor,V2,Nach,Stamm)
    ),
    konjugation(urg,[Pers,Num,praes,ind],Endung),
    concat(Stamm,Endung,Vollform).

verbform((Vor,Nach),(_V1,_V2,V3,_V4),
         [Pers,Num,praet,ind],Vollform) :-
    infix(Vor,V3,Nach,Stamm),
    konjugation(urg,[Pers,Num,praet,ind],Endung),
    concat(Stamm,Endung,Vollform).
verbform((Vor,Nach),(_V1,_V2,V3,_V4),
         [Pers,Num,praet,konj],Vollform) :-
    (member(V3,[a,o,u]) -> umlaut(V3,U) ; U = V3),
    infix(Vor,U,Nach,Stamm),
    konjugation(urg,[Pers,Num,praet,konj],Endung),
    concat(Stamm,Endung,Vollform).

umlaut(a,ä).  umlaut(o,ö).  umlaut(u,ü).   

% -- unregelmaessige Konjugation --

konjugation(urg,[1,sg,praes,ind], 'e').
konjugation(urg,[1,sg,praes,konj],'e').
konjugation(urg,[1,sg,praet,ind], '').
konjugation(urg,[1,sg,praet,konj],'e').

konjugation(urg,[2,sg,praes,ind], 'st').
konjugation(urg,[2,sg,praes,ind], 'est').
konjugation(urg,[2,sg,praes,konj],'est').
konjugation(urg,[2,sg,praet,ind], 'st').
konjugation(urg,[2,sg,praet,ind], 'est').
konjugation(urg,[2,sg,praet,konj],'st').
konjugation(urg,[2,sg,praet,konj],'est').

konjugation(urg,[3,sg,praes,ind], 't').
konjugation(urg,[3,sg,praes,ind], 'et').
konjugation(urg,[3,sg,praes,konj],'e').
konjugation(urg,[3,sg,praet,ind], '').
konjugation(urg,[3,sg,praet,konj],'e').

konjugation(urg,[1,pl,praes,ind], 'en').
konjugation(urg,[1,pl,praes,konj],'en').
konjugation(urg,[1,pl,praet,ind], 'en').
konjugation(urg,[1,pl,praet,konj],'en').

konjugation(urg,[2,pl,praes,ind], 't').
konjugation(urg,[2,pl,praes,ind], 'et').
konjugation(urg,[2,pl,praes,konj],'et').
konjugation(urg,[2,pl,praet,ind], 't').
konjugation(urg,[2,pl,praet,ind], 'et').
konjugation(urg,[2,pl,praet,konj],'t').
konjugation(urg,[2,pl,praet,konj],'et').

konjugation(urg,[3,pl,praes,ind], 'en').
konjugation(urg,[3,pl,praes,konj],'en').
konjugation(urg,[3,pl,praet,ind], 'en').
konjugation(urg,[3,pl,praet,konj],'en').

erzeuge_vollformenlexikon(Ausgabedatei) :-
   ( tell(Ausgabedatei),
       lex(Stammform,Wortart,Art,Flexionsklasse),
       form(Wortart,Form),
       beuge(Wortart,Flexionsklasse,Stammform,Form,
             Vollform),
       Kategorie =.. [Wortart,Art,Form],
       portray_clause(wort(Stammform,Kategorie,Vollform)),
       fail  % naechste Form oder Stammform 
   ; told,
       format(user,'Vollformen erzeugt und nach 
                   ''~w'' geschrieben.\n', Ausgabedatei)
   ).
% -------------- Nomenflexion ----------------
% dekliniere(+Flex.klasse,+NomSg,?[Num,Kas],-Vollform)
dekliniere(Deklinationsklasse,Stammform,
           Formmerkmale,Vollform) :-
    deklination(Deklinationsklasse,
                Formmerkmale,Endung),
    concat(Stammform,Endung,Vollform).

nomenflexion(Deklinationsklasse,Stammform) :-
    form(n,Formmerkmale),
    dekliniere(Deklinationsklasse,Stammform,
               Formmerkmale,Vollform),
    write(Formmerkmale),write(': '),
    write(Vollform),nl,
    fail.
nomenflexion(_,_).

% deklination(+Dekl.klasse,Formmerkmale,-Endung):

deklination((Sg,Pl),[Num,Kas],Endung) :-
        ( endung(Sg,[Num,Kas],Endung)
        ; endung(Pl,[Num,Kas],Endung) ).

endung(s1, [sg,nom],'').   % bei mehrsilbigem Stamm mit
endung(s1, [sg,gen],'s').  % unbetonter Endsilbe;
endung(s1, [sg,dat],'').   % bei Vokal(+h)-Auslaut;
endung(s1, [sg,akk],'').   % bei Nominalisierungen

endung(s1e,[sg,nom],'').   % bei Auslauten s,ß,x,tsch,z; 
endung(s1e,[sg,gen],'es'). % bei einsilbigen Nomen; 
endung(s1e,[sg,dat],'').   % bevorzugt bei Auslaut sch,st
endung(s1e,[sg,akk],'').

endung(s2e,[sg,nom],'').   % bei Nomina mit 
endung(s2e,[sg,gen],'en'). % konson. Auslaut
endung(s2e,[sg,dat],'en').
endung(s2e,[sg,akk],'en').

endung(s3, [sg,nom],'').   % alle Femina
endung(s3, [sg,gen],'').
endung(s3, [sg,dat],'').
endung(s3, [sg,akk],'').

endung(p1, [pl,nom],'e').
endung(p1, [pl,gen],'e').
endung(p1, [pl,dat],'en').
endung(p1, [pl,akk],'e').

endung(p2, [pl,nom],'').
endung(p2, [pl,gen],'').
endung(p2, [pl,dat],'n').
endung(p2, [pl,akk],'').

endung(p3, [pl,nom],'n').   endung(p3e,[pl,nom],'en').
endung(p3, [pl,gen],'n').   endung(p3e,[pl,gen],'en').
endung(p3, [pl,dat],'n').   endung(p3e,[pl,dat],'en').
endung(p3, [pl,akk],'n').   endung(p3e,[pl,akk],'en').

adjektivflexion(Deklinationsklasse,Stammform) :-
    form(a,Formmerkmale),
    dekliniere(Deklinationsklasse,Stammform,
               Formmerkmale,Vollform),
    write(Formmerkmale),write(': '),
    write(Vollform),nl,
    fail.
adjektivflexion(_,_).

% --------------- Adjektivflexion -----------------
beuge(a,Flexionsklasse,Stammform,Form,Vollform) :-
    dekliniere(Flexionsklasse,Stammform,Form,Vollform).

% undekliniertes Adjektiv (adverbial, prädikativ)
dekliniere(a(StammK,StammS),Stammform,Form,Vollform) :-
    ( Form = [pos]
    -> Vollform = Stammform
    ; Form = [komp]
    -> Vollform = StammK
    ; Form = [sup]
    -> atom_concat(StammS,en,Vollform)
    ; fail ).

% dekliniertes Adjektiv (attributiv beim Nomen): 
dekliniere(a(StammK,StammS),StammP,Form,Vollform) :-
    ( Form = [pos,Adekl,Gen,Num,Kas]
    -> endung(ad,[Adekl,Gen,Num,Kas],E),
        concat(StammP,E,Vollform)
    ; Form = [komp,Adekl,Gen,Num,Kas]
    -> endung(ad,[Adekl,Gen,Num,Kas],E),
        concat(StammK,E,Vollform)
    ; Form = [sup,Adekl,Gen,Num,Kas]
    -> endung(ad,[Adekl,Gen,Num,Kas],E),
        concat(StammS,E,Vollform)
    ; fail ).

% --- Die drei Arten der Adjektivdeklination ---

endung(ad,[Dekl,Gen,Num,Kas],Endung) :-
    formreduktion(Gen,Num,GenPl),
    endung(ad,[Dekl,GenPl,Kas],Endung).
formreduktion(Gen,Num,GenPl) :-
    (Num = pl, GenPl = pl) ; (Num = sg, GenPl = Gen).

% starke oder pronominale Deklination
% (Endungen wie beim Pronomen dies-er):

endung(ad,[st,mask,nom],'er').
endung(ad,[st,mask,gen],'en').
endung(ad,[st,mask,dat],'em').
endung(ad,[st,mask,akk],'en').

endung(ad,[st,fem,nom],'e').
endung(ad,[st,fem,gen],'er').
endung(ad,[st,fem,dat],'er').
endung(ad,[st,fem,akk],'e').

endung(ad,[st,neut,nom],'es').  
endung(ad,[st,neut,gen],'en'). % aber: dies-es alt-en Esels
endung(ad,[st,neut,dat],'em').
endung(ad,[st,neut,akk],'es').

endung(ad,[st,pl,nom],'e').
endung(ad,[st,pl,gen],'er').
endung(ad,[st,pl,dat],'en').
endung(ad,[st,pl,akk],'e').

% nominale oder schwache Deklination
% (Endungen wie nach dem bestimmten Artikel):

endung(ad,[sw,mask,nom],'e').
endung(ad,[sw,mask,gen],'en').
endung(ad,[sw,mask,dat],'en').
endung(ad,[sw,mask,akk],'en').

endung(ad,[sw,fem,nom],'e').
endung(ad,[sw,fem,gen],'en').
endung(ad,[sw,fem,dat],'en').
endung(ad,[sw,fem,akk],'e').

endung(ad,[sw,neut,nom],'e').  
endung(ad,[sw,neut,gen],'en').
endung(ad,[sw,neut,dat],'en').
endung(ad,[sw,neut,akk],'e').

endung(ad,[sw,pl,nom],'en').
endung(ad,[sw,pl,gen],'en').
endung(ad,[sw,pl,dat],'en').
endung(ad,[sw,pl,akk],'en').

% gemischte Deklination
% (wie nach 'ein', 'mein', 'kein'):

endung(ad,[ge,mask,nom],'er').
endung(ad,[ge,mask,gen],'en').
endung(ad,[ge,mask,dat],'en').
endung(ad,[ge,mask,akk],'en').

endung(ad,[ge,fem,nom],'e').
endung(ad,[ge,fem,gen],'en').
endung(ad,[ge,fem,dat],'en').
endung(ad,[ge,fem,akk],'e').

endung(ad,[ge,neut,nom],'es').  
endung(ad,[ge,neut,gen],'en').
endung(ad,[ge,neut,dat],'en').
endung(ad,[ge,neut,akk],'es').

endung(ad,[ge,pl,nom],'en').
endung(ad,[ge,pl,gen],'en').
endung(ad,[ge,pl,dat],'en').
endung(ad,[ge,pl,akk],'en').

