GREIBACH.PRO



%%-------------------------------------------------------------------------
%% Programa: 	Forma normal de Greibach
%%
%%
%% Manera de ejecutarse:
%%
%%	lee_datos:-
%%		assertz(gram("A1",[ ["A2","A3"] ]), gram),
%%		assertz(gram("A2",[ ["A3","A1"], ["b"] ]), gram),
%%		assertz(gram("A3",[ ["A1","A2"], ["a"] ]), gram).
%%
%%
%% gram("NOMBRE_DE_VARIABLE", [[PRODUCCION_1], [PRODUCCION_2], ..., [PRODUCCION_N]])
%%
%% PRODUCCION_N =
%% "PARTE_DE_PRODUCCION", ""PARTE_DE_PRODUCCION", ... "PARTE_DE_PRODUCCION"
%%
%%
cciones)
%%	A1 ---------> A2 A3
%%	A2 ---------> A3 A1 | b
%%	A3 ---------> A1 A2 | a
%%-------------------------------------------------------------------------


domains
	st = string
	lst = st*
	producciones = lst*
database - gram
	gram(st, producciones)
database - temp
	temp(producciones)
database - g_s
	g_s(st, producciones)
predicates
	entorno
	lee_datos
	paso1
	paso2
	paso3
	ok(st, lst)
	inserta(st, lst, producciones)
	unir(lst, lst, lst)
	al_final(producciones, producciones, producciones)
	resultado
	new(lst, lst)
	new_prod(st)
	inserta_B(st, lst)
	change(st, st)
	agrega(producciones, lst)
	modifica(st)
clauses
	entorno:-
		makewindow(1,7,7,"Forma Normal de Greibach GNF",0,0,25,80).
	lee_datos:-
		assertz(gram("A1",[ ["A2","A3"] ]), gram),
		assertz(gram("A2",[ ["A3","A1"], ["b"] ]), gram),
		assertz(gram("A3",[ ["A1","A2"], ["a"] ]), gram).
	paso1:-
		gram(Nom, [Prod|_]), ok(Nom, Prod), fail.
	paso1:-!.

	paso2:-
		gram(Nom, [[H|_]|_]),
		Nom = H, frontstr(1,Nom,_,Num), concat("B",Num,Name),
		gram(Name,_), change(Nom, Name), fail.
	paso2:-!.

	paso3:-
		g_s(Nom,_),
		modifica(Nom), fail.
	paso3:-!.

	modifica(N):-
		gram(Nom, [[N|H]|T]),
		g_s(N, Producs),
		agrega(Producs, H),
		temp(Prod), al_final(Prod, T, New_prods), !,
		retractall(gram(Nom,[[N|H]|T]), gram),	%% elimina Ak --> Ak alfa
		assertz(g_s(Nom, New_prods), g_s),
		retractall(_,temp), assertz(temp([]), temp),
		paso3.

	change(A, B):-
		gram(A, [_|Ta]),
		agrega(Ta,[B]), temp(Prod), al_final(Prod, Ta, New_prods), !,
		retractall(gram(A,_), gram),	%% elimina Ak --> Ak alfa
		assertz(g_s(A, New_prods), g_s),
		retractall(_,temp), assertz(temp([]), temp).

	agrega([],_):-!.
	agrega([H|T], B):-
		unir(H,B,H1),	temp(Prod),
		al_final(Prod,[H1],New_prods), !,
		retractall(_,temp), assertz(temp(New_prods), temp),
		agrega(T, B).

	agrega(T,B):- 
		agrega(T,B),
		write("Fin\n", T, "\n", B), readchar(_), !.

	ok(_,[]):-!.
	ok(N, [H|_]):-
		N = N, frontchar(H, Frente, Rest), char_int(Frente, Asc),
		
		frontstr(1,H,_,Rest1), str_int(Rest1, N1),
		frontstr(1,N,_,Rest2), str_int(Rest2, N2),
	ok(N, [H|Resto]):-				%% N2 < N1
		gram(H, Nuevo),
		inserta(N, Resto, Nuevo), !,
		gram(N, [Prod|_]), ok(N, Prod), !,
		new_prod(N).

	inserta(_, _, []):-!.
	inserta(N, Resto, [New_H|New_T]):-
		unir(New_H, Resto, Unido),		%% en ese orden.
		temp(Temp),
		al_final(Temp, [Unido], New_temp),	%% lista temporal.
		retractall(_, temp), assertz(temp(New_temp), temp), !,
		inserta(N, Resto, New_T), !,
		gram(N, [_|Tail]),
		al_final(New_temp, Tail, New_tail),	%% corrige original.
		!, retractall(gram(N,_), gram), retractall(_, temp),
		assertz(gram(N, New_tail), gram), !,
		assertz(temp([]), temp).

	unir([], Lista, Lista).
	unir([X|L1], Lista2, [X|L3]):-
		unir(L1, Lista2, L3).

	al_final([], Lista, Lista).
	al_final([X|L1], Lista2, [X|L3]):-
		al_final(L1, Lista2, L3).

	new_prod(N):-
		gram(N,[H|_]), new(H, New_prod),
		frontstr(1,N,_,Num), concat("B", Num, New_name),
		not(gram(New_name,_)), !,
		inserta_B(New_name, New_prod),
		unir(New_prod, [New_name], New_produc),
		inserta_B(New_name, New_produc).
	new([_|T], T):-!.

	inserta_B(Name, Prod):-			%% es el primero
		assertz(gram(Name, [Prod]), gram), !.

	resultado:-
		gram(N, Produccs),
		write("\n", N, " ===> ", Produccs),
		fail.
	resultado:-
		g_s(N, Produccs),
		write("\n", N, " ===> ", Produccs),
		fail.
goal
	entorno,
	retractall(_,gram), retractall(_,g_s),
	retractall(_,temp), assertz(temp([]), temp),
	lee_datos,
	paso1,
	paso2,
	paso3,
	resultado,
	readchar(_).