an_number(Z) -->
an_number(0, X), "-", {Z is -X}. an_number(Z) -->
an_number(0, Z).
an_number(N, Z) --> [C],
{48 =< C, C =< 57, Z is 10^N * (C - 48)}. an_number(N, Z) -->
[C],
{48 =< C, C =< 57, X is 10^N * (C - 48), N1 is N+1}, an_number(N1, Y), {Z is X+Y}.
test1("1+2*2+3*3*3"). test2("0-123*1001-1001*321"). test3("6-3-2").
test4("6/3/2"). test5("123*2+123/3-287").
После отработки целевых утверждений для представленных в программе кода 6.4 тестов будут получены результаты:
? – test1(List), pars(List, Value).
… Value = 32
?– test2(List), pars(List, Value).
… Value = -444444
?– test3 (List), pars(List, Value).
… Value = 1
? – test4(List), pars(List, Value).
… Value = 1
? – test5(List), pars(List, Value).
…Value = 0
3.Трансляция с ограниченного естественного языка в
ЯИП-1П
Следующий пример – преобразование фраз ограниченного естественного языка (ОЕЯ) в язык исчисления предикатов первого порядка (ЯИП-1П).
91
Данный пример позаимствован автором из книги У.Клоксина и К.Меллиша [4, с. 257 – 259].
Вкачестве ОЕЯ взято подмножество английского языка, так как
внём, в отличие от русского языка, «логические конструкции» выражаются более простыми средствами. Например, кванторы всеобщности и существования в английской и в русской фразах с одинаковым смыслом представляются так:
«Every man loves a woman»
«Для каждого мужчины существует некая женщина, которую он любит»
Следующий код демонстрирует решение данной задачи:
Код 6.5
:-op(100, xfy, &). :-op(150, xfy, '=>').
an_phrase(P) --> an_ng(X, P1, P), an_vg(X, P1).
an_ng(X, P1, P) -->
an_kv(X, P2, P1, P), an_noun(X, P3), an_aux(X, P3, P2).
an_ng(X, P, P) -->
an_name(X).
an_vg(X, P) -->
an_verb1(X, Y, Q), an_ng(Y, Q, P).
an_vg(X, P) -->
an_verb2(X, P).
an_aux(X, R1, (R1 & R2)) --> [that], an_vg(X, R2).
an_aux(_, R, R) --> [].
an_kv(X, Q, R, all(X, (Q => R))) --> [every]. an_kv(X, Q, R, exists(X, (Q & R))) --> [a].
92
an_name(X) -->
[X], {name_list(L), member(X, L)}.
an_noun(V, Z) -->
[X], {noun_list(L), member(X, L), Z=..[X, V]}.
an_verb1(V1, V2, Z) -->
[X], {verb1_list(L), member(X, L), Z=..[X, V1, V2]}.
an_verb2(V, Z) -->
[X], {verb2_list(L), member(X, L), Z=..[X, V]}.
name_list([Джон, Мери, Рекс, Чарли]). noun_list([man, woman, dog, cat]). verb1_list([loves, pursues]). verb2_list([lives, walks]).
test1([every, man, that, lives, loves, a, woman]). test2([every, dog, that, pursues, a, cat, loves, a, man, that,
loves, a, woman, that, walks]). test3([a, dog, pursues, Чарли]). test4([Рекс, loves, Джон]). test5([Мери, walks]).
Дадим пояснения некоторым предикатам данной программы: an_ng – анализ группы существительного,
an_vg – анализ группы глагола,
an_aux – анализ вспомогательного предложения (that ...), an_kv – анализ «квантора» (every, a),
an_name – анализ «имени» (наличие в списке «конкретных действующих лиц»),
an_noun – анализ существительного (наличие в списке «сущностей»),
an_verb1 – анализ «переходного» глагола (например, loves), an_verb2 – анализ «непереходного» глагола (например, lives).
93
После отработки целевых утверждений
?-test1(L), an_ph(Res, L, []). ?-test2(L), an_ph(Res, L, []). ?-test3(L), an_ph(Res, L, []). ?-test4(L), an_ph(Res, L, []). ?-test5(L), an_ph(Res, L, []).
в качестве значения переменной Res будут возвращены следующие
структуры данных:
Res = all(X, man(X) & lives(X) =>
exists(Y, woman(Y) & loves(X, Y))).
Res = all(X, dog(X) & exists(Y, cat(Y) & pursues(X, Y)) => exists(Z, (man(Z) & exists(W, (woman(W) & walks(W)) & loves(Z, W))) & loves(X, Z))).
Res = exists(X, dog(X) & pursues(X, Чарли)). Res = loves(Рекс, Джон).
Res = walks(Мери).
94
Лекция 7
Программирование эффективных синтаксических анализаторов (продолжение)
В данной лекции завершается обсуждение вопросов, относящихся к проблеме синтаксического анализа на Прологе. В частности, будут рассмотрены два примера, демонстрирующие анализ ограниченного естественного языка (ОЕЯ). Первый пример – это анализ синонимических конструкций ОЕЯ, так называемых активных и пассивных форм, производимый с целью построения канонической структуры, выражающей единый для этих форм смысл. Второй пример иллюстрирует так называемый морфологический анализ – грамматический разбор отдельных слов ОЕЯ: выделение приставок, корней, суффиксов, окончаний слова с важным побочным эффектом этого разбора – определением значения рода, числа, падежа и тому подобных грамматических категорий. Третий пример, который будет обсуждаться в данной лекции, относится к анализу программ – текстов на языке программирования операторного
типа. Для определённости будет представлена «учебная» модель такого языка – язык PL (Programming Language), – точнее, неболь-
шое подмножество этого языка, содержащее наиболее характерные для операторного языка конструкции.
1. Анализ активных и пассивных форм ОЕЯ
Речь будет идти о весьма распространенном в ограниченных естественных языках явлении – представлении одной и той же информации различными способами.
Рассмотрим задачу преобразования так называемых поверхностных структур ограниченного естественного языка в структуры, которые принято называть глубинными. Не утруждая себя точными определениями этих понятий, поясним их на следующем примере.
Поверхностным структурам русского языка
«Мой сосед купил дачу», «Дача куплена моим соседом»
соответствует глубинная структура
predicate(action(купить), agent(мой_сосед), object(дача)).
95