% er.pl
% expresiones regulares en Prolog
% Jacinto Dávila
%

profundidad(3). 

er(A, A) :- A\=[], atomico(A), !. 
er((A,R), AR) :- er(A,AA), er(R,RR), er(AA,RR,AR). 

er(A+B,[AUB1,AUB2]) :- er(A,AUB1), er(B,AUB2).
er(A^e, E) :- 
  profundidad(N), er(A, AA), ere(AA^N, E). 

er(A, B, AIB) :- y(A,B,AIB). 

ere(_^0, [lambda]). % cualquier expresion cero veces
ere(A^N, [AA|R]) :- % una expresion n veces
  N>0, NN is N-1, ern(N,A,AA), ere(A^NN,R).

ern(1,A,A). 
ern(N,A,(A,R)) :- 
  N>0, NN is N-1, ern(NN,A,R).

veru(A) :- A\=[], atomico(A), write(A). 
ver([]) :- write(lambda). 
ver((A,R)) :- veru(A), veru(R). 
ver((A,R)) :- veru(A), ver(R). 
ver([A|_]) :- ver(A).
ver([_|R]) :- write(' ó '), ver(R).  

y(A,B,(A,B)) :- A\=[], atomico(A), !. 
y((A,R), B, (A, RR)) :- y(R,B,RR). 

% aplana normaliza la expresión de entrada ()
% para obtener una disjuncion [ ] de conjunciones ( )
% aplana([],[]). 
% aplana(lambda, [(lambda)]).
aplana(A,A) :- A\=[], atomico(A). 
aplana((A,B), RR) :- !, 
  aplana(A, AA), aplana(B, BB),
  y(AA,BB,RR).  
aplana(L, ALi) :- 
  member(Li, L), aplana(Li, ALi). 

atomico(A) :- atom(A).
atomico(A) :- number(A). 

ereg(E, C) :- er(E,L), aplana(L, C). 
ereg(E, C) :- er(E,L), member(L1, L), aplana(L1, C). 
