WikiDer > Синтаксис и семантика пролога - Википедия
В синтаксис и семантика Язык программирования пролог представляют собой набор правил, определяющих, как пишется программа на Прологе и как она интерпретируется. Правила изложены в Стандарт ISO ISO / IEC 13211[1] хотя есть различия в Реализации Пролога.
Типы данных
Пролог - это динамически типизированный. Имеет сингл тип данных, то срок, который имеет несколько подтипов: атомы, числа, переменные и сложные термины.
An атом имя общего назначения без внутреннего значения. Он состоит из последовательности символов, которая анализируется средством чтения Prolog как единое целое. В коде Пролога атомы обычно представляют собой голые слова, написанные без специального синтаксиса. Однако атомы, содержащие пробелы или некоторые другие специальные символы, должны быть заключены в одинарные кавычки. Атомы, начинающиеся с заглавной буквы, также должны быть заключены в кавычки, чтобы отличать их от переменных. Пустой список, написанный []
, также является атомом. Другие примеры атомов включают Икс
, синий
, 'Тако'
, и 'какой-то атом'
.
Числа возможно поплавки или же целые числа. Многие реализации Prolog также предоставляют неограниченные целые числа и рациональное число.
Переменные обозначаются строкой, состоящей из букв, цифр и символов подчеркивания и начинающейся с заглавной буквы или символа подчеркивания. Переменные очень похожи на переменные по логике в том смысле, что они заменяют произвольные термины. Переменная может быть создана (привязана к определенному члену) через объединение. Одиночное подчеркивание (_
) обозначает анонимную переменную и означает «любой термин». В отличие от других переменных, подчеркивание не означает одно и то же значение везде, где оно встречается в определении предиката.
А составной термин состоит из атома, называемого «функтором», и ряда «аргументов», которые снова являются терминами. Составные термины обычно записываются как функтор, за которым следует список терминов аргументов, разделенных запятыми, который содержится в круглых скобках. Количество аргументов называется термином арность. Атом можно рассматривать как составной термин с арность нуль.
Примеры составных терминов: truck_year ('Мазда', 1986)
и 'Person_Friends' (зельда, [том, джим])
. Сложные термины с функторами, объявленными как операторы, могут быть записаны в префиксной или инфиксной нотации. Например, условия - (z)
, + (а, б)
и = (X, Y)
также можно записать как -z
, а + б
и X = Y
, соответственно. Пользователи могут объявлять произвольные функторы как операторы с разным приоритетом, что позволяет использовать нотации, специфичные для предметной области. Обозначение ж / п обычно используется для обозначения термина с функтором ж и арность п.
Частные случаи сложных терминов:
- Списки определены индуктивно: атом
[]
это список. Составной термин с функтором.
(точка) и арность 2, второй аргумент которой является списком, сам является списком. Для обозначения списков существует специальный синтаксис:. (А, В)
эквивалентно[A | B]
. Например, список.(1, .(2, .(3, [])))
также можно записать как[1 | [2 | [3 | []]]]
, или даже более компактно, как[1,2,3]
. - Струны: Последовательность символов, окруженная кавычками, эквивалентна списку (числовых) кодов символов, обычно в локальном кодировка символов или же Unicode если система поддерживает Unicode.
Пролог программы
Программы на языке Prolog описывают отношения, определяемые с помощью предложений. Чистый Пролог ограничен Роговые оговорки, а Полный по Тьюрингу подмножество первого порядка логика предикатов. Есть два типа статей: факты и правила. Правило имеет форму
Голова :- Тело.
и читается как «Голова истинна, если тело истинно». Тело правила состоит из вызовов предикатов, которые называются цели. Встроенный предикат ,/2
(имеется в виду оператор 2-арности с именем ,
) обозначает соединение целей и ;/2
обозначает дизъюнкция. Соединения и разъединения могут появляться только в теле, а не в голове правила.
Предложения с пустыми телами называются факты. Пример факта:
Кот(Том).
что эквивалентно правилу:
Кот(Том) :- истинный.
другой пример:
Икс является 3+2.
и когда вы запустите его, результат будет
Икс=5 да.
Встроенный предикат правда / 0
всегда правда.
Оценка
Выполнение программы на Прологе инициируется публикацией пользователем единственной цели, называемой запросом. Логично, что движок Prolog пытается найти разрешающая способность опровержение опровергнутого запроса. Метод разрешения, используемый Prolog, называется Разрешение SLD. Если отрицательный запрос может быть опровергнут, из этого следует, что запрос с соответствующими привязками переменных является логическое следствие программы. В этом случае пользователю сообщается обо всех сгенерированных привязках переменных, и считается, что запрос выполнен успешно. С функциональной точки зрения стратегию выполнения Пролога можно рассматривать как обобщение вызовов функций на других языках, с одним отличием в том, что несколько заголовков предложений могут соответствовать данному вызову. В этом случае система создает точку выбора, объединяет цель с заголовком предложения первой альтернативы и продолжает цели этой первой альтернативы. Если какая-либо цель терпит неудачу в ходе выполнения программы, все привязки переменных, которые были выполнены с момента создания самой последней точки выбора, отменяются, и выполнение продолжается со следующей альтернативой этой точки выбора. Эта стратегия исполнения называется хронологической. возврат. Например:
мать_дитя(трудиться, Салли). отец_ ребенок(Том, Салли).отец_ ребенок(Том, Эрика).отец_ ребенок(Майк, Том). брат или сестра(Икс, Y) :- parent_child(Z, Икс), parent_child(Z, Y). parent_child(Икс, Y) :- отец_ ребенок(Икс, Y).parent_child(Икс, Y) :- мать_дитя(Икс, Y).
Это приводит к тому, что следующий запрос оценивается как истинный:
?- брат или сестра(Салли, Эрика).да
Это получается следующим образом: Изначально единственный совпадающий заголовок предложения для запроса брат (Салли, Эрика)
является первым, поэтому доказательство запроса эквивалентно доказательству тела этого предложения с соответствующими привязками переменных на месте, то есть конъюнкцией (родитель_деток (Z, салли), родитель_деток (Z, Эрика))
. Следующая цель, которую нужно доказать, - это самая левая цель этого конъюнкции, т. Е. parent_child (Z, салли)
. Этой цели соответствуют две главы статьи. Система создает точку выбора и пробует первую альтернативу, тело которой Father_child (Z, салли)
. Эта цель может быть доказана, используя факт Father_child (Том, Салли)
, поэтому привязка Z = том
генерируется, и следующая цель, которую необходимо доказать, - это вторая часть вышеуказанного соединения: parent_child (Том, Эрика)
. Опять же, это подтверждается соответствующим фактом. Поскольку все цели могут быть доказаны, запрос выполняется. Поскольку запрос не содержит переменных, пользователю не сообщается о привязках. Запрос с переменными, например:
?- отец_ ребенок(Отец, Ребенок).
перечисляет все действительные ответы при возврате.
Обратите внимание, что с указанным выше кодом запрос ? - брат (салли, вылазка).
тоже удается. При желании можно было бы вставить дополнительные цели для описания соответствующих ограничений.
Циклы и рекурсия
Итерационные алгоритмы могут быть реализованы с помощью рекурсивных предикатов. Системы Prolog обычно реализуют хорошо известный метод оптимизации, называемый хвостовой зов оптимизация (TCO) для детерминированных предикатов, показывающих хвостовая рекурсия или, в более общем смысле, хвостовые вызовы: кадр стека предложения отбрасывается перед выполнением вызова в хвостовой позиции. Следовательно, детерминированные хвостовые рекурсивные предикаты выполняются с постоянным пространством стека, как циклы в других языках.
Порезы
А резать (!
) внутри правила не позволит Прологу возвращать любые предикаты за вырезом:
предикат(Икс) :- один(Икс), !, два(Икс).
завершится ошибкой, если первое найденное значение Икс
для которого один (X)
правда приводит к два (X)
ложь.
Анонимные переменные
Анонимные переменные _
никогда не привязаны к значению и могут использоваться в предикате несколько раз.
Например, поиск в списке по заданному значению:
содержит(V, []) :- ложный.содержит(V, [V|_]) :- истинный.содержит(V, [_|Т]) :- содержит(V, Т).
Отрицание
Встроенный предикат Prolog \+/1
обеспечивает отрицание как неудача, что позволяет немонотонный рассуждения. Цель + незаконно (X)
в правиле
законный(Икс) :- \+ незаконный(Икс).
оценивается следующим образом: Пролог пытается доказать незаконно (X)
. Если может быть найдено доказательство этой цели, исходная цель (т. Е. + незаконно (X)
) не работает. Если не найти доказательств, первоначальная цель достигнута. Следовательно \+/1
префиксный оператор называется "недоказуемым" оператором, поскольку запрос ? - + Цель.
считается успешным, если цель недоказуема. Такое отрицание звук если его аргумент "земля" (т.е. не содержит переменных). Разумность теряется, если аргумент содержит переменные. В частности, запрос ? - юридический (X).
теперь нельзя использовать для перечисления всего, что является законным.
Семантика
При декларативном чтении порядок правил и целей внутри правил не имеет значения, поскольку логическая дизъюнкция и конъюнкция коммутативны. Однако с процедурной точки зрения часто важно учитывать стратегию выполнения Пролога либо из соображений эффективности, либо из-за семантики нечистых встроенных предикатов, для которых важен порядок оценки. Кроме того, поскольку интерпретаторы Пролога пытаются объединить предложения в порядок, в котором они указаны, отсутствие правильного порядка может привести к бесконечной рекурсии, как в:
предикат1(Икс) :- предикат2(Икс,Икс).предикат2(Икс,Y) :- предикат1(Икс), Икс \= Y.
При таком порядке любой запрос формы
?- предикат1(атом).
будет повторяться, пока стек не будет исчерпан. Если, однако, последние 3 строки были изменены на:
предикат2(Икс,Y) :- Икс \= Y, предикат1(Икс).
тот же запрос за очень короткое время приведет к результату Нет.
Грамматики с определенными предложениями
Существует специальная нотация, называемая грамматиками с определенными предложениями (DCG). Правило, определенное через -->/2
вместо :-/2
расширяется препроцессором (expand_term / 2
, средство, аналогичное макросам на других языках) в соответствии с несколькими простыми правилами переписывания, что приводит к обычным предложениям Пролога. В частности, переписывание снабжает предикат двумя дополнительными аргументами, которые могут использоваться для неявной передачи состояния вокруг, аналогично монады на других языках. DCG часто используются для написания парсеров или генераторов списков, так как они также предоставляют удобный интерфейс для перечисления различий.
Пример парсера
Более крупный пример покажет потенциал использования Prolog в разбор.
Учитывая предложение, выраженное в Форма Бэкуса – Наура:
<приговор> ::= <stat_part><stat_part> ::= <утверждение> | <stat_part> <утверждение><утверждение> ::= <я бы> = <выражение> ;<выражение> ::= <операнд> | <выражение> <оператор> <операнд><операнд> ::= <я бы> | <цифра><я бы> ::= а | б<цифра> ::= 0..9<оператор> ::= + | - | *
Это может быть написано на Прологе с использованием DCG, что соответствует прогнозирующему синтаксическому анализатору с упреждающим просмотром одного токена:
приговор(S) --> утверждение(S0), предложение_r(S0, S).предложение_r(S, S) --> [].предложение_r(S0, seq(S0, S)) --> утверждение(S1), предложение_r(S1, S). утверждение(назначать(Идентификатор,E)) --> я бы(Идентификатор), [=], выражение(E), [;]. выражение(E) --> срок(Т), выражение_r(Т, E).выражение_r(E, E) --> [].выражение_r(E0, E) --> [+], срок(Т), выражение_r(плюс(E0,Т), E).выражение_r(E0, E) --> [-], срок(Т), выражение_r(минус(E0, Т), E). срок(Т) --> фактор(F), term_r(F, Т).term_r(Т, Т) --> [].term_r(T0, Т) --> [*], фактор(F), term_r(раз(T0, F), Т). фактор(я бы(Я БЫ)) --> я бы(Я БЫ).фактор(цифра(D)) --> [D], { (номер(D) ; вар(D)), между(0, 9, D)}. я бы(а) --> [а].я бы(б) --> [б].
Этот код определяет отношение между предложением (заданным как список токенов) и его абстрактное синтаксическое дерево (АСТ). Пример запроса:
?- фраза(приговор(AST), [а,=,1,+,3,*,б,;,б,=,0,;]).AST = seq(назначать(а, плюс(цифра(1), раз(цифра(3), я бы(б)))), назначать(б, цифра(0))) ;
AST представлен с использованием терминов Пролога и может использоваться для применения оптимизаций, для компиляции таких выражений в машинный код или для прямой интерпретации таких операторов. Как типично для реляционной природы предикатов, эти определения могут использоваться как для синтаксического анализа и генерации предложений, так и для проверки того, соответствует ли данное дерево заданному списку токенов. С помощью итеративное углубление для честного перечисления в конечном итоге будет сгенерировано каждое произвольное, но фиксированное предложение и соответствующее ему AST:
?- длина(Токены, _), фраза(приговор(AST), Токены). Токены = [а, =, а, (;)], AST = назначать(а, я бы(а)) ; Токены = [а, =, б, (;)], AST = назначать(а, я бы(б)) так далее.
Смотрите также
Рекомендации
- ^ ISO / IEC 13211: Информационные технологии - Языки программирования - Пролог. Международная организация по стандартизации, Женева.