/* Grammaires pour les exressions arithmétiques 
   avec génération du terme standard correspondant à l'expression lue
*/

% Notation polonaise préfixée ==================================================

rTop(E) --> rS(A), {pref2exp(A, E)}.
rS(pref1(Op, Ag, Ad)) --> rOp(Op), rS(Ag), rS(Ad).
rS(pref2(Cte)) --> rCte(Cte).
rS(pref3(Vbl)) --> rVbl(Vbl).
rOp(+) --> [+].
rOp(*) --> [*].
rCte(1) --> [1].
rCte(2) --> [2].
rVbl(x) --> [x].
rVbl(y) --> [y].


pref2exp(pref1(Op, G, D), E) :- pref2exp(G, Eg), pref2exp(D, Ed), E =.. [Op, Eg, Ed].
pref2exp(pref2(V), V).
pref2exp(pref3(V), V).

top :- rS(A, [*,+,2,x, 1], []), pref2exp(A, X), write(X).

tt :- rTop(A, [*,+,2,x, 1], []), write(A).

% Notation complètement parenthésée ==============================================

topCP(A) --> expCP(E), {cp2arb(E, A)}.
expCP(cp1(G, Op, D)) --> parouv, expCP(G), oper(Op), expCP(D), parfer.
expCP(cp2(V)) --> variable(V).
expCP(cp3(C)) --> constante(C).
parouv --> ['('].
parfer --> [')'].
oper(+) --> [+].
oper(*) --> [*].
variable(x) --> [x].
variable(y) --> [y].
variable(z) --> [z].
constante(1) --> [1].
constante(2) --> [2].

cp2arb(cp1(G, Op, D), E) :- cp2arb(G, Eg), cp2arb(D, Ed), E =.. [Op, Eg, Ed].
cp2arb(cp2(V), V).
cp2arb(cp3(V), V).

cp :- topCP(A, ['(', '(',x, +, y,')', *, z, ')'], []), write(A).


% Notation polonaise postfixée ===================================================
/* E --> E E Op, E --> Var, E --> Cte   se transforme en
 E --> Var, E --> Cte, E --> Var S, E --> Cte S,  S --> E Op S, S --> E Op.
*/

post2arb(post1(V), V).
post2arb(post2(C), C).
post2arb(post3(V, S), E) :- postAux(V, S, E).
post2arb(post4(C, S), E) :- postAux(C, S, E).

postAux(EG, post5(CD, Op, S), E) :- post2arb(CD, ED), EG1 =.. [Op, EG, ED], postAux(EG1, S, E).
postAux(EG, post6(CD, Op), E) :- post2arb(CD, ED), E =.. [Op, EG, ED].

pTop(E) --> pE(A), {post2arb(A, E)}.
pE(post1(V)) --> vbl(V), {write(1)}.
pE(post2(C)) --> cte(C), {write(2)}.
pE(post3(V, S)) --> vbl(V), pS(S), {write(3)}.
pE(post4(C, S)) --> cte(C), pS(S), {write(4)}.
pS(post5(CD, Op, S)) --> pE(CD), pOp(Op), pS(S), {write(5)}.
pS(post6(CD, Op)) --> pE(CD), pOp(Op), {write(6)}.
pOp(+) --> [+].
pOp(*) --> [*].
cte(1) --> [1].
cte(2) --> [2].
vbl(x) --> [x].
vbl(y) --> [y].

po :- pTop(A, [x,y,+,2, *], []), write(A).

% Notation à précédences associant à gauche, avec un seul niveau de priorité ==================

/* E -> E Op T, E -> T,  T -> ( E ), T -> Var  
   recursive a gauche se transforme en
   E -> T S, E -> T, S -> Op T S, S -> Op T, T -> ( E ), T -> Var */
   

prec12arb(prec11(G, D), E) :- term12arb(G, TG), prec1Aux(TG, D, E).
prec12arb(prec12(T), E) :- term12arb(T, E).

term12arb(prec15(F), E) :-prec12arb(F, E).
term12arb(prec16(V),V).
term12arb(prec17(C),C).

prec1Aux(TG, prec13(Op, CD, S), E) :- term12arb(CD, TD), TG1 =.. [Op, TG, TD], prec1Aux(TG1, S, E).
prec1Aux(TG, prec14(Op, T), E) :- term12arb(T, TD), E =.. [Op, TG, TD].

prec1Top(A) --> prec1E(D), {prec12arb(D, A)}.
prec1E(prec11(G, D)) --> prec1T(G), prec1S(D).
prec1E(prec12(T)) --> prec1T(T).
prec1S(prec13(Op, CD, S)) --> prec1Op(Op), prec1T(CD), prec1S(S).
prec1S(prec14(Op, CD)) --> prec1Op(Op), prec1T(CD).
prec1T(prec15(F))  --> prec1parouv, prec1E(F), prec1parfer.
prec1T(prec16(V))  --> prec1var(V).
prec1T(prec17(C))  --> prec1cte(C).
prec1parouv --> ['('].
prec1parfer --> [')'].
prec1var(x) --> [x].
prec1var(y) --> [y].
prec1cte(1) --> [1].
prec1cte(2) --> [2].
prec1Op(+) --> [+].
prec1Op(*) --> [*].

pp1 :- prec1Top(A, ['(', x, +, y, *, 2, ')', +, 1, *, 2 ], []), write(A).

% Notation à précédences associant à gauche, avec deux niveaux de priorité ==================


prec22arb(prec21(T, S1), A) :- term22arb(T, TG), prec2Aux1(TG, S1, A).
prec2arb(prec22(T), A) :- term22arb(T, A).

term22arb(prec25(F, S2), A) :- fac22arb(F, FG), prec2Aux2(FG, S2, A).
term22arb(prec26(F), A) :- fac22arb(F, A).

fac22arb(prec29(E), A) :- prec22arb(E, A).
fac22arb(prec210(V), V).
fac22arb(prec211(C), C).

prec2Aux1(TG, prec23(Oa, T, S1), A) :- term22arb(T, TD), TG1 =.. [Oa, TG, TD], prec2Aux1(TG1, S1, A).
prec2Aux1(TG, prec24(Oa, T), A) :- term22arb(T, TD), A =.. [Oa, TG, TD].

prec2Aux2(FG, prec27(Om, F, S2), A) :- fac22arb(F, FD), FG1 =.. [Om, FG, FD], prec2Aux2(FG1, S2, A).
prec2Aux2(FG, prec28(Om, F), A) :- fac22arb(F, FD), A =.. [Om, FG, FD].

    prec2Top(A) --> prec2E(D), {prec22arb(D, A)}.
    prec2E(prec21(G, D)) --> prec2T(G), prec2S1(D).
    prec2E(prec22(T)) --> prec2T(T).
    prec2S1(prec23(Opadd, CD, S)) --> prec2Oa(Opadd), prec2T(CD), prec2S1(S).
    prec2S1(prec24(Opadd, CD)) --> prec2Oa(Opadd), prec2T(CD).
    prec2T(prec25(F, S))  --> prec2F(F), prec2S2(S).
    prec2T(prec26(F))  --> prec2F(F).
    prec2S2(prec27(Opmul, CD, S)) --> prec2Om(Opmul), prec2F(CD), prec2S2(S).
    prec2S2(prec28(Opmul, CD)) --> prec2Om(Opmul), prec2F(CD).
    prec2F(prec29(E))  --> prec2parouv, prec2E(E), prec2parfer.
    prec2F(prec210(V))  --> prec2var(V).
    prec2F(prec211(C))  --> prec2cte(C).
    prec2parouv --> ['('].
    prec2parfer --> [')'].
    prec2var(x) --> [x].
    prec2var(y) --> [y].
    prec2cte(1) --> [1].
    prec2cte(2) --> [2].
    prec2Oa(+) --> [+].
    prec2Om(*) --> [*].

pp2 :- prec2Top(A, ['(', x, +, y, *, 2, ')', +, 1, *, 2 ], []), write(A).
