:- op(500,yfx,&), op(600,yfx,'\/'),
    op(600,xfx,'=>'), op(600,xfx,'<=>').

kleinschreibung(Wort,Klein) :-
    atom(Wort),
    name(Wort,[C|Chars]),
    (member(C,"ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ")
    ->  K is C+32,           
        name(Klein,[K|Chars])
    ; Klein = Wort).

sem([en(Art,Form), [Vollform]],LamTerm) :-
    wort(Stammform, en(Art,Form), Vollform),
    kleinschreibung(Stammform,EN),
    LamTerm = EN.

sem([rn(Art,Form), [Vollform]],LamTerm) :-
    wort(Stammform, rn(Art,Form), Vollform),
    kleinschreibung(Stammform,Stamm),
    Formel =.. [Stamm,X,Y],
    LamTerm = lam(X,lam(Y,Formel)).

sem([v([nom,akk],Form),[Vollform]],LamTerm) :-
    kleinschreibung(Vollform,VollformKl),
    wort(Stammform,v([nom,akk],Form),VollformKl),
    Formel =.. [Stammform,X,Y],
    LamTerm = lam(X,lam(Y,Formel)).
   
sem([n(Art,Form),[Vollform]],LamTerm) :-
    wort(Stammform, n(Art,Form), Vollform),
    kleinschreibung(Stammform,Stamm),
    Formel =.. [Stamm,X],
    LamTerm = lam(X,Formel).
   
sem([n(Art,Form),[rn(Art,Form),[Vollform]]],LamTerm) :-
    wort(Stammform, rn(Art,Form), Vollform),
    kleinschreibung(Stammform,Stamm),
    Formel =.. [Stamm,X],
    LamTerm = lam(X,Formel).
   
sem([det([quant],_Form),_Vollform],
    lam(N,lam(P,all(X,N*X => P*X)))).

sem([det([indef],_Form),_Vollform],
    lam(N,lam(P,ex(X,N*X & P*X)))).

sem([det([def],[_,pl,_]),[Vollform]],
    lam(N,lam(P, anzahl(X,N*X & P*X,Zahl)))) :-
    anzahl(Vollform,Zahl), !.
sem([det([def], [_,sg,_]),_Vollform],
    lam(N,lam(P,
    ex(Y,all(X,eq(X,Y) <=> N*X) & P*Y)))).

sem([det([qu], _Form),_Vollform],
    lam(N,lam(P,qu(X,N*X & P*X)))).  

sem([a([als(nom)],[komp]),[kleiner]],
    lam(X,lam(Y,(X < Y)))). % Fehlermeldung?
sem([a([als(nom)],[komp]),[größer]],
    lam(X,lam(Y,(Y < X)))). % > kein Grundprädikat

sem([pron([rel],_Form),_Rel], lam(P,lam(X,P*X))).
sem([pron([qu],_Form),_Pron], lam(P,qu(X,P*X))).

sem([poss([rel],[_Gen,_Num,gen]),_Poss],
    lam(RN,lam(P,lam(Y,ex(X,RN*X*Y & P*X))))).
    % nur bei RNsg 
sem([np([_,3,_],[_,_]),
       Det, [n(Art,Form),Vf]], SemNP) :-
    sem(Det,SemDet),
    Vf \= km, sem([n(Art,Form),Vf],SemN),
    normalize(SemDet * SemN,SemNP).

sem([np([def,3,Gen],[Num,Kas]),
       [en([Gen],[Num,Kas]),EN]], SemNP) :-
    sem([en([Gen],[Num,Kas]),EN],SemEN),
    SemNP = lam(P,P*SemEN).
sem([np([def,3,Gen],[Num,_Kas]),
       [det([def],_),_],
       [en([Gen],[Num,nom]),EN]],
    SemNP) :-
    !, sem([en([Gen],[Num,nom]),EN],SemEN),
    SemNP = lam(P,P*SemEN).
sem([np([def,3,Gen],[Num,Kas]), 
       [det([def],_),_],
       [n([Gen],[Num,Kas]),N],
       [en([Gen2],[Num,nom]),EN]], SemNP) :-
    !, sem([n([Gen],[Num,Kas]),N],SemN),
    sem([en([Gen2],[Num,nom]),EN],SemEN),
    normalize(lam(P,SemN*SemEN & P*SemEN),SemNP).

sem([np([Def,3,Gen],[Num,Kas]),
      [pron([DefP],[Gen,Num,Kas]),Pron]],
    SemNP) :-
    ( DefP = rel, Def = rel(Gen,Num)
    ; DefP = qu, Def = qu ),
    sem([pron([DefP],[Gen,Num,Kas]),Pron],
        SemNP).

sem([np([rel(Gen2,Num2),3,Gen],[sg,Kas]),
       [poss([rel],[Gen2,Num2,gen]),Poss],
       [rn([Gen],[sg,Kas]),RN]],
    SemNP) :-
    sem([poss([rel],[Gen2,Num2,gen]),Poss],
        SemPoss),
    sem([rn([Gen],[sg,Kas]),RN],SemRN),
    normalize(SemPoss*SemRN,SemNP).

sem([np([_,3,_],[_,_]),
       [det([def],_),[Zahlatom]],[n(_,_),[km]]],
    lam(P,P*Zahl)) :-
    anzahl(Zahlatom,Zahl). % Ausnahme: Maß

sem([np([_,3,_],[_,_]),
       Det,[rn(Art,Form),RN],NPgen], Sem) :-
    sem(Det,SemDet),   
    sem([rn(Art,Form),RN],SemRN),
    sem(NPgen,SemNPgen),
    SemN = lam(X,SemNPgen*lam(Y,(SemRN*X)*Y)),
    normalize(SemDet*SemN,Sem).

sem([s([_Def],[_,_,vz]),
      NP1, [v([nom,akk],[3,Num,_,ind]),V], NP2],
    SemS)
:-  sem(NP1,SemNP1), sem(NP2,SemNP2),
    sem([v([nom,akk],[3,Num,_,ind]),V], SemV),
    not(debugging(typisieren)), % ohne Typen!
    NP1 = [np([_,3,_],[Num1,Kas1])|_Konst], 
    (Kas1 = nom, Num1 = Num,
        Sem = SemNP1 * lam(X,SemNP2 *
                          lam(Y,SemV * X * Y))
    ; Kas1 = akk,
        Sem = SemNP1 * lam(Y,SemNP2 *
                          lam(X,SemV * X * Y))
    ), normalize(Sem,SemS).
       
sem([s([qu],[_,ind,ve]),
      [v([nom,akk],[3,Num,_,ind]),V], NP1, NP2],
    SemS)
:-
    sem([v([nom,akk],[3,Num,_,ind]),V], SemV),
    sem(NP1,SemNP1), sem(NP2,SemNP2),
    NP1 = [np(_,[Num1,Kas1])|_Konstituenten], 
    (Kas1 = nom, Num1 = Num,
        Sem = SemNP1 * lam(X,SemNP2 *
                          lam(Y,SemV * X * Y))
    ; Kas1 = akk,
        Sem = SemNP1 * lam(Y,SemNP2 *
                          lam(X,SemV * X * Y))
    ), normalize(Sem,SemS).
       
sem([s([qu],[_,ind,ve]),
      [v([sein],[3,Num,_,ind]),_V], NP1, NP2],
    SemS)
:-
    NP1 = [np(_,[Num,nom])|_Konst1],
    NP2 = [np([Def2,3,_],[Num,nom])|_Konst2], 
    sem(NP1,SemNP1),
    sem(NP2,SemNP2), (Def2 = indef ; Def2 = def), 
    Sem = SemNP1*lam(X,SemNP2*lam(Y,eq(X,Y))),
    normalize(Sem,SemS).

sem([s([qu],[_,ind,ve]),
      [v([sein],[3,Num,_,ind]),_], NP1, AP],
    SemS)
:-
    NP1 = [np(_,[Num,nom])|_Konst1],
    AP  = [ap([def],[komp])|_Konst2], 
    sem(NP1,SemNP1), sem(AP,SemAP),
    normalize(SemNP1*SemAP, SemS).

sem([s([rel(GenR,NumR)],[Tmp,Mod,vl]),
      NP1,
      NP2, 
      [v([nom,akk],[3,Num,Tmp,Mod]),V]],
    SemS)
:-
    NP1 = [np([rel(GenR,NumR),3,GenR],[_,Kas1])|_], 
    sem(NP1,SemNP1),
    sem([v([nom,akk],[3,Num,Tmp,Mod]),V], SemV),
    sem(NP2,SemNP2),
    ( Kas1 = nom, Sem =
      SemNP1 * lam(X,SemNP2 * lam(Y,SemV * X * Y))
    ; Kas1 = akk, Sem =
      SemNP1 * lam(Y,SemNP2 * lam(X,SemV * X * Y))
    ),
    normalize(Sem,SemS).
       
sem([s([rel(GenR,NumR)],[Temp,ind,vl]),
      NP1, AP, [v([sein],[3,Num,Temp,ind]),_]],
    SemS)
:-
    NP1 = [np([rel(GenR,NumR),3,_],[Num,nom])|_],
    AP  = [ap([def],[komp])|_Konst2], 
    sem(NP1,SemNP1),
    sem(AP,SemAP),
    normalize(SemNP1*SemAP, SemS).

sem([s([rel(GenR,NumR)],[Temp,ind,vl]),
      NP1, NP2, [v([sein],[3,Num,Temp,ind]),_V]],
    SemS)
:-
    NP1 = [np([rel(GenR,NumR),3,_],[Num,nom])|_],
    NP2 = [np([Def2,3,_],[Num,nom])|_Konst2], 
    sem(NP1,SemNP1),
    sem(NP2,SemNP2), (Def2 = indef ; Def2 =def),
    Sem = SemNP1*lam(X,SemNP2*lam(Y,eq(X,Y))),
    normalize(Sem,SemS).

sem([np([_Def,3,Gen],[Num,Kas]),
       DET,
       [n([Gen],[Num,Kas]), N],
       [s([rel(Gen,Num)],[_,_,vl])|Konst]], 
    LamTerm)
:-
    sem(DET,SemDET),
    sem([n([Gen],[Num,Kas]),N],SemN),
    sem([s([rel(Gen,Num)],[_,_,vl])|Konst],SemSREL),
    SemNREL = lam(X,(SemN * X) & (SemSREL * X)),
    normalize(SemDET * SemNREL, LamTerm).
        
sem([ap([def],[komp]),
       [a([als(nom)],[komp]),Adj], [als], NP], 
    SemAP)
:-  sem([a([als(nom)],[komp]),Adj], SemAdj),
    NP = [np([_,3,_],[_,nom])|_],
    sem(NP,SemNP),
    normalize(lam(X,SemNP*lam(Y,SemAdj*X*Y)), SemAP).    
       
sem([np([rel(Gen2,Num2),3,Gen],[pl,Kas]),
       [poss([rel],[Gen2,Num2,gen]),_Poss],
       [rn([Gen],[pl,Kas]),RN]],
    SemNP) :-
    SemPoss = lam(R,lam(P,lam(Y,
                 all(X,R*X*Y => P*X)))),
    sem([rn([Gen],[pl,Kas]),RN],SemRN),
    normalize(SemPoss*SemRN,SemNP).

sem([v([werden],_Form),_Vollform],LamTerm) :-
   LamTerm = lam(TV,lam(Y,ex(X,(TV * X) * Y))).

sem([s([qu],[_,_,ve]),
         [v([werden],Form),PassAux], NP, 
         [v([nom,akk],[part2]),TV]],
    SemS) :-
    sem(NP,SemNP),
    sem([v([werden],Form),PassAux], SemPassAux),
    sem([v([nom,akk],[part2]),TV], SemTV),
    normalize(SemNP * (SemPassAux * SemTV), SemS).

sem([s([_Def],[_,_,vz]),
         NP, [v([werden],Form),PassAux],
         [v([nom,akk],[part2]),V]],
    SemS) :-
    sem(NP,SemNP),
    sem([v([werden],Form),PassAux], SemPassAux),
    sem([v([nom,akk],[part2]),V], SemTV),
    normalize(SemNP * (SemPassAux * SemTV), SemS).

sem([s([_Def],[_,_,vl]),
         NP, [v([nom,akk],[part2]),V],  
         [v([werden],Form),PassAux]],
    SemS) :-
    sem(NP,SemNP),
    sem([v([werden],Form),PassAux], SemPassAux),
    sem([v([nom,akk],[part2]),V], SemTV),
    normalize(SemNP * (SemPassAux * SemTV), SemS).

sem([s([qu],[_,_,ve]),
         [v([werden],_Form),_PassAux],
         NP, [von], NPsbj,
         [v([nom,akk],[part2]),TV]],
    SemS) :-
    sem(NP,SemNP),
    NPsbj = [np([_Def2,_Pers2,_Gen2],[_Num2,dat]) | _],
    sem(NPsbj,SemNPsbj),
    sem([v([nom,akk],[part2]),TV], SemTV),
    normalize(SemNP * lam(Y,SemNPsbj
                      * lam(X,(SemTV*X)*Y)), SemS).

sem([s([_Def],[_,_,vz]),
         NPobj,
         [v([werden],_Form),_PassAux],
         [von], NPsbj,
         [v([nom,akk],[part2]),TV]],
    SemS) :-
    sem(NPobj,SemNPobj),
    NPsbj = [np([_Def2,_Pers2,_Gen2],[_Num2,dat]) | _],
    sem(NPsbj,SemNPsbj),
    sem([v([nom,akk],[part2]),TV], SemTV),
    normalize(SemNPobj * lam(Y,SemNPsbj
                         * lam(X,(SemTV*X)*Y)), SemS).

sem([s([_Def],[_,_,vl]),
         NP, [von], NPsbj,
         [v([nom,akk],[part2]),TV],
         [v([werden],_Form),_PassAux]],
    SemS) :-
    sem(NP,SemNP),
    NPsbj = [np([_Def2,_Pers2,_Gen2],[_Num2,dat]) | _],
    sem(NPsbj,SemNPsbj),
    sem([v([nom,akk],[part2]),TV], SemTV),
    normalize(SemNP * lam(Y,SemNPsbj
                      * lam(X,(SemTV*X)*Y)), SemS).

sem([pron([rezi],[mask,pl,akk]),[einander]],
    lam(P, lam(X,lam(Y, (P*X)*Y & (P*Y)*X)))).
sem([det([quant],[_Gen,pl,_Kas]),_Vollform],
    lam(N,lam(P,all(X,all(Y,N*X& N*Y& neg(eq(X,Y))=> P*X*Y))))).
sem([det([indef],[_Gen,pl,_Kas]),_Vollform],
    lam(N,lam(P,ex(X,ex(Y,N*X & N*Y & neg(eq(X,Y)) & P*X*Y))))).
sem([det([def],[_Gen,pl,_Kas]),_Vollform],
    lam(N,lam(P,all(X,all(Y,N*X& N*Y& neg(eq(X,Y))=> P*X*Y))))).
sem([np([Def,3,Gen],[Num,Kas]),
      [pron([DefP],[Gen,Num,Kas]),Pron]], SemNP) :-
    (DefP = rezi, Def = indef), 
    sem([pron([DefP],[Gen,Num,Kas]),Pron], SemNP).

sem([s([_Def],[_,_,vz]),
      NP1, [v([nom,akk],[3,Num,_,ind]),V], NP2], SemS)
:-  sem(NP1,SemNP1), sem(NP2,SemNP2),
    sem([v([nom,akk],[3,Num,_,ind]),V], SemV),
    debugging(typisieren), % nur für die getypte Version
    NP1 = [np([_,3,_],[Num1,Kas1])|_Konst], 
    (Kas1 = nom,
        (NP2 = [np(_,_),[pron([rezi],_),_]], Num1=pl
        -> Sem = SemNP1 * (SemNP2 * SemV)
        ; Sem = SemNP1 * lam(X,SemNP2 *
                          lam(Y,SemV * X * Y))
        )
    ; Kas1 = akk,
        Sem = SemNP1 * lam(Y,SemNP2 *
                          lam(X,SemV * X * Y))
    ), normalize(Sem,SemS).

sem([s([_Def],[_,_,ve]),
      [v([nom,akk],[3,Num,_,ind]),V], NP1, NP2], SemS)
:-  sem(NP1,SemNP1), sem(NP2,SemNP2),
    sem([v([nom,akk],[3,Num,_,ind]),V], SemV),
    debugging(typisieren), % nur für die getypte Version
    NP1 = [np([_,3,_],[Num1,Kas1])|_Konst], 
    (Kas1 = nom,
        (NP2 = [np(_,_),[pron([rezi],_),_]], Num1=pl
        -> Sem = SemNP1 * (SemNP2 * SemV)
        ; Sem = SemNP1 * lam(X,SemNP2 *
                          lam(Y,SemV * X * Y))
        )
    ; Kas1 = akk,
        Sem = SemNP1 * lam(Y,SemNP2 *
                          lam(X,SemV * X * Y))
    ), normalize(Sem,SemS).
parset :-
    write('Beende die Eingabe mit <Punkt><Return>'),
    nl,read_sentence(user,Sentence,[]),
    tokenize(Sentence,Atomlist),
    startsymbol(S), addTree:translate1(S,Term,Baum),
    addDifflists:translate(Term,ExpTerm,Atomlist,[]),
    nl,write('Aufruf: '), portray_clause(ExpTerm),
    call(ExpTerm), 
    write('Baum:   '),nl,showTree(Baum,4),nl, 
    sem(Baum,Lam),
    (debugging(typisieren) 
    -> type([],Lam,LamTy,Ty),
        writen('    + '),writen(LamTy:Ty),nl
    ; writen('    + '),writen(Lam),nl),
    fail.
parset.
