Kombinátor je predikát provádějící kompozici několika parserů, jejímž výsledkem je parser nový. Snad v každé gramatice se objevuje zřetězení, proto asi nejběžnější operací nad parsery je jejich sekvenční kompozice. Definujme tedy kombinátor pro tento účel:
% <&>>(+Parser1, +Parser2, ?Wrapper)
<&>>(P1,P2,I+L):-
I+L1 :-> P1,
<&>>^(P2,L1,L-[]).
% <&>>^(+Parser2, +LosOfP1, -ComposedLosOfP1P2)
<&>>^(_,[],D-D).
<&>>^(P2,[N>R|L1s],L12-D):-
N+L2 :-> P2,
mapListDL(fstTuple *>* (const(R) *>* sndTuple),L2,L12-D_),
<&>>^(P2,L1s,D_-D).
Kombinátor <&>> postupně aplikuje na vstup parsery
Na vstup
je tedy nejdříve aplikován parser
. Jeho výstupem je
seznam úspěšných rozkladů
délky
. Ten může obsahovat několik,
jednu nebo dokonce žádnou derivaci. Jak bylo uvedeno, každá položka
tohoto seznamu se skládá z nezpracovaného zbytku vstupu a výsledku:
<&>>^ aplikuje na
každý zbytek vstupu
mapListDL a tím vytvoří seznam
Predikát mapListDL se od mapList liší pouze tím, že jeho
výstupem je seznam v rozdílové reprezentaci. Rozdílové seznamy
,...,
musí být ve výsledném seznamu
zřetězeny
a právě rozdílová reprezentace nám umožní efektivní provedení této
operace.