% A program which compiles a DCG in BH-GRN into a top-down parser
% bhgrncompiler.pl

:- op(1200, xfx, --->).                            
:- op(1200, xfx, ===>).

term_expansion((LHS ---> RHS), (Head :- Body)) :-
   grn_translate1(LHS, Head, Xs, Ys), grn_translate1(RHS, TempBody, Xs, Ys),
   strip_trues(TempBody, Body).
   
grn_translate1((A, B), (A1, B1), Xs, Ys) :- !,
   grn_translate1(A, A1, Xs, Xs1), grn_translate1(B, B1, Xs1, Ys).
      
grn_translate1({A}, A, Xs, Xs) :- !.
      
grn_translate1([A|B], (A1, B1), Xs, Ys) :- !,
   grn_translate1(A, A1, Xs, Xs1), grn_translate1(B, B1, Xs1, Ys).

grn_translate1([], true, Xs, Xs) :- !.

grn_translate1(A, A1, Xs, Ys) :- !,
   A  =.. [F|Args],
   append(Args, [Xs, Ys], NewArgs),
   A1 =.. [F|NewArgs].

term_expansion((Cat ===> Words), (Head :- Body)) :-
    grn_translate1(Cat, Head, Xs, Ys), grn_translate2(Words, Body, Xs, Ys).

grn_translate2(([X|Xs],{A}), A, [X | Ys], Zs) :- !, append(Xs, Zs, Ys).

grn_translate2([X|Xs], true, [X | Ys], Zs) :- !, append(Xs, Zs, Ys).

strip_trues((A, B), C) :- !,
   strip_trues(A, A1), strip_trues(B, B1),
   combine(A1, B1, C).

strip_trues(A, A).

combine(true, B, B) :- !.
combine(A, true, A) :- !.
combine(A, B, (A, B)).

% append/3: see appendix A