Я столкнулся с проблемой бесконечной рекурсии, пытаясь реализовать очень простую грамматику без ограничений в прологе.
Вот мои правила: (вп -> глагольная фраза, нп -> именная фраза, ап -> прилагательная фраза, пп -> подготовительная фраза)
verb(S) :- member(S, [put, pickup, stack, unstack]).
det(S) :- member(S, [the]).
adj(S) :- member(S, [big, small, green, red, yellow, blue]).
noun(S) :- member(S, [block, table]).
prep(S) :- member(S, [on, from]).
vp([V|R]) :- verb(V), pp(PP), np(NP), append(NP, PP, R).
np([D, N]) :- det(D), noun(N).
np([D|R]) :- det(D), ap(AP), noun(N), append(AP, [N], R).
ap([A]) :- adj(A).
ap([A|R]) :- adj(A), ap(R).
pp([P|R]) :- prep(P), np(R).
Проблема, с которой я столкнулся, заключается в том, что правило для ap может создавать произвольно длинные строки прилагательных, поэтому в какой-то момент я застреваю, пытаясь удовлетворить запрос, пробуя все эти бесконечные возможности.
Например, следующий запрос никогда не даст S = [положить, красный, блок, на, зеленый, блок], потому что он сначала расширит прилагательную фразу слева «красный» до бесконечных возможностей, прежде чем пытаться выполнить правильно.
?- vp(S)
S = [put, the, red, green, block, on, the, block] ;