
Искусство программирования на языке Пролог / prolog14_end / prol16
.docГлава 16
Синтаксический
анализ для грамматик, задаваемых
определительными предложениями
Синтаксический анализ является очень важным приложением Пролога и логического программирования. В действительности, происхождение Пролога связано с попыткой использовать логику для выражения грамматических правил и формализации процесса синтаксического разбора.
Наиболее распространенным подходом к реализации синтаксического разбора средствами Пролога является использование грамматик, задаваемых определительными предложениями (definite clause grammar, DCG). DC-грамматики являются некоторым обобщением контекстно-свободных грамматик. Они представляют собой нотационный вариант определенного класса программ на Прологе и потому являются исполняемыми.
Разбор с использованием DC-грамматик обсуждается здесь, поскольку эта тема связана с темами двух предыдущих глав. Разработка программ синтаксического разбора на Прологе является идеальной иллюстрацией программирования на Прологе с использованием недетерминированных программ и разностных списков.
Начнем с обсуждения контекстно-свободных грамматик. Контекстно-свободные грамматики определяются множеством правил вида
< нетерминал> (тело).
где нетерминал является нетерминальным символом, а тело - последовательностью из одного или нескольких элементов, разделяемых запятыми. Каждый элемент-это либо нетерминальный символ, либо последовательность терминальных символов. Смысл правила в том, что тело есть возможная форма грамматической группы нетерминального типа.Нетерминальные символы записываются как атомы Пролога, а последовательности терминальных символов-в виде списков атомов. Это облегчает трансляцию грамматик в Пролог - программы.
Для каждого нетерминального символа S грамматика определяет язык, который представляет собой множество последовательностей терминальных символов, получаемых путем повторного недетерминированного применения правил грамматики, начиная с символа S.
Рассмотрим простую контекстно-свободную грамматику для небольшого подмножества английского языка. Грамматика, показанная на рис. 16.1, не требует специальных пояснений. Первое правило грамматики читается так: «Предложение состоит из группы существительного, за которым следует группа глагола». Примером предложения, распознаваемого этой грамматикой, является предложение «The decorated pieplate contains a surprise».
Грамматика может быть непосредственно записана в виде программы на языке Пролог, В этой программе каждому нетерминальному символу соответствует унарный предикат, идентифицируемый аргумент которого есть предложение или группа. Для представления предложения можно выбрать просто список слов. Части предложения также легко представить списками слов. Первое правило грамматики
1) В литературе на русском языке наряду с этим существуют термины грамматика определенных дизъюнктов, дизъюнктивно-определяемая грамматика
Грамматические правила
предложение группа_существительного, группа_глагола.
группа существительного артикль, группа_сушествительного2.
группа существительного группа-существитсльного2.
группа_существительного2 прилагательное, группа_существительного2.
группа _сущсствнтельного2 существительное.
группа_глагола глагол.
группа_глагола глагол, группа_существительного
Словарь
артикль [the]. прилагательное[decorated].
артикль [а].
существительное[pieplate] глагол[contains]
существительное[surprise]
Рис. 16.3. Простая контекстно-свободная грамматика
на языке Пролог запишется следующим образом:
предложение(S) append(NP,VP.S),
группа_сущсствительного(NP),
группа_глагола(VP).
Словарные правила, связанные с терминальными символами, могут, быть выражены как факты, например, так:
артикль ([the]). существительное([рieplate]).
Таким образом, представленную на рис. 16.1 полную грамматику можно записать на языке Пролог в виде программы синтаксического разбора, однако такая программа будет неэффективной. Использование в программе предиката append наводит на мысль, что более подходящей структурой данных для синтаксического анализа является разностный список. Программа 16.1 является результатом преобразования грамматики, представленной на рис. 16.1, в Пролог-программу, в которой грамматические группы представлены разностными списками.
Базовая реляционная схема-это предикат предложение (S), где S -разностный список слов. образующих некоторое предложение согласно правилам грамматики. Подобным же образом предикаты группа_существительного(S), группа_существительного2(S), артикль(S), гpynna_глагола(S), существительное(S) и глагол (S) истинны, если их аргумент, некоторый разностный список слов S, является частью речи, соответствующей их именам.
Программа 16.1-это синтаксический анализатор, реализующий нисходящий рекурсивный разбор слева направо, в процессе которого производится возврат, когда требуется выбрать некоторое альтернативное решение. Хотя анализаторы с возвратами легко конструируются, в общем случае они неэффективны. Однако эффективность механизма возврата, присущего Прологу, позволяет создавать на основе DC-грамматик практически эффективные анализаторы.
Преобразование контекстно-свободной грамматики в эквивалентную Пролог-программу осуществляется просто. Программа 16.2 преобразует отдельное правило грамматики в его эквивалент на Прологе-. Преобразование всей грамматики заключается в последовательном преобразовании отдельных правил. Предполагается, что правила грамматики представлены термами вида А В, где А - нетерми-
предложсиие(S\S0)
группа_существительного(S\S1), группа_глагола(S1 \S0).
группа существительного (S\ S0)
артикль (S\S1), группа_сутествительного2 (S1 \S0)
группа_существительного(S)
группа_существительного2(S).
группа_существительного2(S\S0)
прилагательное(S\S1), группа_.существительного2(S\S0).
группа_сущсствительного2(S)
существительное(S).
группа_глагола(S)
глагол(S).
группа._глагола (S\S0)
глагол(S\S1), группа_существительного(S1\S0).
артикль ([the | S] \S).прилагательное ([decorated | S]\S).
артикль ([а | S]\S).
существительное ([pieplate | S]\S). глагол([соntains | S]\S).
cуществительное([surprise | S]\.S).
Программа 16.1. Программа на Прологе для разбора предложений языка, определенного грамматикой, представленной на рис. 16.1.
нальный символ, а В - конъюнкция нетерминальных символов и списков терминальных символов. Нетерминальные символы являются атомами Пролога. Предполагается также, что для знака существует подходящее объявление оператора.
Основная реляционная схема программы 16.2-это предикат преобразовать(ПравилоГрамматики, ПредложениеПролога).
преобразовать (Правило Грамматики,, Предложение Пролога)
Предложение Пролога- эквивалент на Прологе правила контекстно-свободной грамматики ПравилоГрамматики.
преобразовать((Lhs Rhs),(Head Body))
преобразовать (Lhs, Head, Xs\ Ys),
преобразовать (Rhs, Body,Xs\Ys).
преобразовать ((A,B),(A1, Вl),Xs\Ys)
преобразовать (A, A1, Xs \ Xs1),
преобразовать (B,Bl,Xsl\Ys).
преобразовать (А, А1, S)
не_терминал(A),functor(A1,A,1),arg(1,A1,S).
преобразовать (Xs, true, S)
терминалы (Xs),
последовательность (Xs, S).
не_терминал (A) atom(A). терминалы([Х | Xs]).
последовательность ([X | Xs],[X | S] \S0)
последовательность(Xs, S\S0).
последовательность ([ ],Xs\Xs).
Программа 16.2. Программа преобразования грамматических правил в предложения Пролога
Процедура преобразовать.2 преобразует левую и правую части данного правила грамматики в заголовок и тело эквивалентного предложения на Прологе. Основная идея состоит в добавлении некоторого разностного списка к каждому нетерминальному символу. Необходим новый вариант предиката преобразовать, а именно предикат npeo6paзoвamь(Символ,Цель.Xs). Это отношение истинно, если Символ преобразуется в Цель при добавлении разностного списка Xs в качестве аргумента. Три предложения преобразовать/3 покрывают возможные термы в грамматическом правиле. Если терм является конъюнкцией, то каждый ее элемент рекурсивно преобразуется с выполнением подходящих соединений разностных списков. Нетерминальный символ преобразуется в унарную структуру, функтором которой является символ, а аргументом - разностный список. Последовательность терминальных символов с помощью предиката последовательность(Символ,Xs) унифицируется с разностным списком соответствующего правила. Некоторый постпроцессор может удалить избыточные «истинные» цели true. Однако можно предотвратить их появление, используя разностную структуру.
Следующие две программы дополняют программу 16.1. Эти программы представляют собой хотя и простые, но типичные примеры использования DC-грамма-тик для построения синтаксических анализаторов. Значительную роль в них играют логические переменные.
Первая программа предназначена для конструирования дерева разбора анализируемого предложения. К предикатам программы 16,1 должны быть добавлены аргументы, представляющие определенные части дерева разбора. Это расширение подобно рассмотренному в разд. 2.2 добавлению структурных аргументов к логическим программам. Так, предикат предложение/1 заменяется бинарным отношением предложение (Дерево, Слова), где Дерево- дерево разбора слов, представленных переменной Слова и анализируемых согласно правилам грамматики. Другие унарные предикаты, представляющие грамматические группы и части речи, должны быть подобным же образом заменены бинарными предикатами. Здесь предполагается, что дерево разбора является первым аргументом предикатов.
Первое предложение программы 16.1 после изменения принимает следующий вид:
предложение (предложение (NP,VP),S\S1 )
группа_существительного(NP,S\SO),
группа_глагола(VР, S0\S1).
Составной терм предложение (NP, VP) представляет дерево разбора, в котором NP и VP в свою очередь представляют подлежащие разбору группу существительного и группу глагола соответственно.
Программа, кроме того, может быть расширена за счет дополнения правил грамматики, К нетерминальным символам может быть добавлен дополнительный аргумент, что превращает их в структуры. Приведенное выше правило представляется теперь следующим образом:
предложение(предложение(КР, VP))
группа_существительного(NP), группа_глагола(VТ).
Добавление аргументов к нетерминальным символам контекстно-свободных грамматик делает их более полезными.
Программа 16.2, преобразующая правила контекстно-свободных грамматик в программы на языке Пролог, может быть расширена для преобразования DC-грамматик в Пролог-программы. Такое расширение предлагается выполнить в качестве Упражнения [см. упражнение 16(3)]. Поэтому, используя DC-грамматики в нотации грамматических правил, мы понимаем, что по существу пишем Пролог-программы.
DC-грамматики в программе 16.3 являются расширением программы 16.1. В программе 16.3 выполняются синтаксический анализ предложения и построение
предложение(предложение(N,V))
группа_существительногo(N), группа_глагола(V).
группа_существительного(группа_существительного(D,N))
артикль (D), группа_существительного2(N). группа_существительного(группа_существительного(N))
группа_сушествительного2 (N).
группа_существительного2(группа_существительного2(A,N))
прилагательное(A), группа_существительного2(N).
группа_существительного2(группа_существительного2(N))
существительное (N).
группа_глагола(группа_глагола(V)) глагол (V). группа_глагола(группа._глагола(V,N))
глагол (V),группа_сушествительного(N).
Словарь
артикль(артикль(the)) [the].
артикль(артикль((а)) [а].
существительное (существительное(рiер1а1е)) [pieplate].
существительное (существительное(surprise)) [surprise].
прилагательное(прилагательное((dесогаtеd)) [decorated].
глагол(глагол(contains)) [contains].
Программа 16.3 DC-грамматика построения дерева разбора.
дерева разбора. Как логическая программа, она подобна программе 2.3, которая в дополнение к- идентификации компонентов схемы строила некоторую структуру, Программа выполняет нисходящее построение дерева разбора, используя при этом возможности логической переменной.
Следующее расширение связано с согласованием подлежащего и дополнения по числу. Предположим, что по нашей грамматике необходимо разобрать такое предложение: "The decorated pieplates contain a surprise". Простейшим способом управления множественно-числовыми формами существительных и глаголов, достаточным для целей нашего изложения, является обработка разных числовых форм как различных слов. Расширим словарь путем добавления следующих фактов:
существительное(существительное(рiер1а1еs)) [pieplates].
глагол(глагол(соп1а1п)) [contain].
Новая программа должна быть способна разбирать предложение "The decorated pieplates contain a surprise", но, кроме того, она, к сожалению, должна выполнять и разбор предложения "The decorated pieplates contains a surprise". Необязательно, чтобы существительное и глагол были либо оба в единственном, либо оба во
множественном числе,
Согласование в числе может быть осуществлено с помощью добавления аргумента к частям речи, которые должны иметь одинаковое число. Этот аргумент указывает, в каком числе (единственном или множественном) представлены соответствующие части речи. Рассмотрим правило грамматики:
предложение (предложение(МР,\Т))
группа_существительного (NP,Num),
группа_глагола (VP,Num).
Согласно этому правилу, требуется, чтобы и группа существительного (подлежащее), и группа глагола (дополнение) имели одно и то же число - единственное или множественное. Согласование в числе указывается с помощью общей переменной Num. Информация, определяющая согласование в числе субъекта и объекта предложения. является контекстно-зависимой. Такие контекстно-зависимые требования. очевидно, не могут быть определены средствами контекстно-свободной грамматики.
Программа 16.4, в которой осуществляется корректное согласование в числе, является расширением программы 16.3. Группы существительного и группы глагола должны иметь одно и то же число единственное или множественное. Аналогично в группе существительного должны согласовываться в числе артикли и существительные. Чтобы определить, какие слова имеют единственное, а какие множественное число, производится расширение словаря. Следует отметить, что число не является грамматической категорией некоторых частей речи, например наречия, в таких случаях вводить дополнительные аргументы не требуется. Артикль может использоваться как в случае единственного, так и в случае множественного числа. При этом аргумент, указывающий число, остается неконкретизированным.
предложение(предложение(N,V))
группа_существительного(N,Num), группа_глагола(V,Num).
группа_существительного(группа_существительного(D,N),Num)
apтикль(D,Num), группа._существительного2(N,Num).
группа_существительного (группа_существительного(N),Num)
группа_существитсльного2(N,Num).
группа_существительного2(группа_существительного2(А,N),Num)
прилагательное(A), группа_существительного2(N,Num).
группа_существительного2(группа_существительного2(N), Num)
существительное(N,Num).
группа_глагола(группа_глагола(V),Num) глагол (V,Num).
группа_глагола (группа _глагола(V,N),Num)
глагол (V,Num), группа_существительного(N,Num1).
Словарь
артикль(apтикль(the),Num) [the].
артикль(артикль(а).единственное) [а].
существительное(сушествительное(рieplatе), единственное) [pieplate].
существительное(сушествительное(pieplates), множественное) [pieplates].
существительное (существительное(surprise), единственное) [surprise]. существительное(существительное(surprises), множественное) [surprises].
прилагательное(при.лагательное(dесогatеd)) [decorated].
глагол (глагол (contains), единственное) [contains].
глагол (глагол (contain,) множественное) [contain].
Программа 16.4. DC-грамматика с согласованием в числе субъекта и объекта.
В следующем примере DC-грамматики используется еще одно свойство Пролога - возможность ссылаться в теле правила Пролога на произвольную цель. Программа 16.5 представляет собой грамматику для распознавания чисел, не превышающих одну тысячу. Числа записываются по-русски. При этом значение распознанного числа вычисляется с использованием арифметических средств Пролога.
Основным отношением в данной грамматике является отношение number(N), где N- численное значение числа, подлежащего распознаванию. Согласно грамматике, специфицированной программой 16.5, некоторое число-это либо нуль, либо число /V. состоящее не более чем из трех цифр. Такое число представляется предикатом xxx(N). Аналогично предикат xx(N} прсдставлясг числа, состоящие не
number(0) [нуль].
number(N) xxx(N).
xxx(N) цифра(0), [сто], остаток_xxx(N1),{N := D*100+N1}.
остаток_ххх(0) [ ].
остаток_xхх(N) [и], xx(N).
xx(N) цифра(N)
xx(N) дцать(N).
xx(N) десятки(Т), остаток. xx(Nl), {N := T+N1}.
остаток_хх(0) [ ].
остаток_хх(N) цифpa(N).
цифра (1) [один]. дцать(10) [десять].
цифра (2) [два]. дцать(11) [одиннадцать].
цифра(З) [три]. дцать(12) [двенадцать].
цифра(4) [четыре]. дцать(13) [тринадцать].
цифра(5) [пять]. дцать(14) [четырнадцать].
цифра (6) [шесть]. дцать(15) [пятнадцать].
цифра(7) [семь]. дцать(16) [шестнадцать].
цифра (8) [восемь]. дцать(17) [семнадцать]
цифра (9) [девять]. дцать(18) [восемнадцать].
дцать(19) [девятнадцать].
десятки (20) [двадцать].
десятки (30) [тридцать].
десятки (40) [сорок].
десятки (50) [пятьдесят].
десятки (60) [шестьдесят].
десятки (70) [семьдесят].
десятки (80) [восемьдесят].
десятки (90) [девяносто].
Программа 16.5. DC-грамматика для распознавания чисел,
более чем из двух цифр. Предикаты остаток_ххх и остаток_хх обозначают остатки чисел из трех и двух цифр соответственно после удаления ведущей цифры. Предикаты цифра, дцать и десятки используются соответственно для распознавания цифр, чисел от десяти до девятнадцати включительно и чисел, кратных десяти, от 20 до 90 включительно.
В грамматику необходимо ввести новую синтаксическую конструкцию, которая позволяла бы использовать произвольные цели Пролога. Такая возможность осуществляется путем помещения цели Пролога в фигурные скобки. Для иллюстрации рассмотрим следующее правило для определения чисел из трех цифр:
xxx(N)цифра(D),[сто],остаток_xxx(Nl),{N:= D*100+N1}.
Согласно этому правилу, в числе N из трех цифр первая цифра имеет значение D, за ней следует слово «сто», за которым в свою очередь следует остаток числа, имеющий значение N1. Значение числа N получается посредством умножения D на 100 и прибавления значения Nl.
DC-грамматики наследуют еще одно свойство логического программирования - использование возвратов при выполнении программы. Программа 16.5 может использоваться для порождения записи заданного числа, не превышающего тысячи. Эта грамматика, говоря техническим языком, порождает и допускает. При этом реализуется классический принцип-«порождать и проверять». Все допустимые грамматикой числа порождаются одно за другим и проверяются на правильность значения до тех пор, пока не будет получено фактически заданное число. Конечно, это скорее необычный, нежели эффективный способ записи чисел.
В общем случае порождающее свойство DC-грамматик не является полезным, Во многих грамматиках используются рекурсивные правила. Например, правило на рис. 16.1, которым группа_существителъного2 определяется как прилагательное, за которым следует группа_существителъного2, является рекурсивным. Рекурсивно определенные грамматики применяются для порождения результатов в недетерминированных вычислениях. В грамматике, представленной программой 16.3, сначала обрабатываются группы существительных с произвольно большим количеством прилагательных, а затем рассматривается группа глагола.
Упражнения к гл. 16
1. Напишите простую грамматику для французского языка, в которой предусматривается согласование по ролям.
2. Расширьте и измените программу 16.5 с целью разбора чисел, так чтобы она допускала разбор всех чисел, не превышающих одного миллиона. Не забудьте включить объекты типа «тридцать пять сотен» и не включайте «тридцать сотен».
3. Расширьте программу 16.2 для преобразования правила DC-грамматики в предложение Пролога.
16.1 Дополнительные сведения
Язык Пролог с самого начала был связан с синтаксическим разбором. Как упоминалось выше, появление языка Пролог было подготовлено работами Колмероэ по синтаксическому анализу и Q-системам (Colmerauer, 1973). Разработчики языка Пролог-10 также были нацелены на обработку текстов на естественном языке; ими написан один из наиболее подробных отчетов по DC-грамматикам (Pereira и Warren, 1980). В этой публикации содержится хорошее обсуждение преимущества DC-грамматик как формализма для синтаксического разбора по сравнению с грамматиками ATN.
Во многих версиях языка Пролог, например в языке Wistiom-Пролог, предусмотрены специальные средства, позволяющие автоматически преобразовывать правила грамматики по мере просмотра соответствующего файла.
Несмотря на то что управляющие структуры Пролога непосредственно пригодны для построения синтаксических анализаторов, работающих по методу рекурсивного спуска и нисходящего разбора, средствами Пролога могут быть довольно легко реализованы и другие алгоритмы разбора. Например, Matsumoto и др, (1986) описывают реализованную на Прологе программу синтаксического анализа для восходящего разбора.
Грамматика, представленная в программе 16.1, заимствована из книги Винограда по вычислительной лингвистике (Winograd, 1983).
ыыы