В дополнение к ответу @Mog рассмотрим более общий случай:
Что, если грамматика настолько сложна, что переупорядочивание DCG-правил не поможет? Как мы можем по-прежнему перечислять все предложения? Если грамматика сформулирована таким образом, что она обрывается на фиксированную длину, мы получим все предложения с
?- length(Xs, N), phrase(s, Xs).
Одна только цель length
перечислит все списки справедливым образом. То есть начиная с самого короткого []
перечисляются все списки:
?- length(Xs, N).
Xs = [],
N = 0 ;
Xs = [_G307],
N = 1 ;
Xs = [_G307, _G310],
N = 2 ;
Xs = [_G307, _G310, _G313],
N = 3 ;
Xs = [_G307, _G310, _G313, _G316],
N = 4 ; ...
И теперь, когда длина фиксирована, цель phrase(s, Xs)
найдет все ответы для этой фиксированной длины. В качестве примера посмотрите на ответ Мэта на эту грамматику.
Итак, это общий метод проверки предложений грамматики. Однако за эту общность приходится платить! Для грамматик с конечным числом предложений метод out не завершится:
:- use_module(
library(double_quotes)
).
s --> "a"|"b".
?- phrase(s, Xs).
Xs = "a" ;
Xs = "b".
Эта грамматика работает из коробки, но вместе с length/2
мы получаем сейчас:
?- length(Xs, N),phrase(s, Xs).
Xs = "a",
N = 1 ;
Xs = "b",
N = 1 ;
**loops**
Этот метод часто называют итеративным углублением, хотя этот термин точнее накладывает ограничение на глубина происхождения. Но мы накладываем ограничение на фактический «выход». Таким образом, итеративное углубление также может обрабатывать левую рекурсию, тогда как length/2
работает только для грамматик, которые завершаются при фиксированной длине ввода.
Что делает эту технику особенно интересной в Прологе, так это то, что она идеально сочетается с механизмом хронологического возврата Пролога.
person
false
schedule
26.03.2012