为了解决后来添加的额外问题:您可以通过添加其他参数来传递信息,但您需要描述句子的顺序。例子phrase(s, [peter, is, father, of, guido]), phrase(s, [he, is, a, male])应该成功,不应该成功的是两个句子一个接一个phrase(ss, [peter, is, father, of, guido, '.', he, is, a, male,'.'])(或者它可能成功,留下“他”作为我们不认识的人的参考。这完全取决于我们有多严格与上下文有关。)。
要正确地做到这一点,我们需要跳很多圈。首先,我们需要在 DCG 规则中添加解析信息。例如,np(np([A,O],object)) --> %... 会将文章后跟一个对象解析为结构np([A,O],object)。让我们用它解析['a', 'male']和[guido]:
?- phrase(np(NP), [a, male]).
NP = np([article(a), object(male, male)], object) ;
false.
?- phrase(np(NP), [guido]).
NP = np([name(guido, male)], name) ;
false.
np 的第一个参数是一个列表,因为其他 np 规则只有在组件上。请注意,我们将性别作为属性添加到name 和object。在其他语言中,例如法语,文章也有一个需要与对象一致的性别,但在英语中我们可以把它放在一边。更复杂的实现也会考虑对象是单数还是复数(动词的不同模式也是如此)。
对于动词,我们需要区分它们需要多少宾语名词短语。这是通过检查is_transitive/1、is_intransitive/1 和is_bitransitive/1 完成的。
为指示代词找到一个好的解决方案很难:代词不需要指代前面的主语,例如在“Gaile 与 Peter 结婚。他比她年长。”中。它甚至根本不需要参考最后一句话,例如“彼得是他想去的地方。”。这意味着 a) 您应该事先决定,您实际上想要涵盖哪些情况; b) 当您拥有完整的结构化信息时,最好在第二次解析运行中做出这些决定。这反映了syntactic, semantic and pragmatic reasoning 之间的语言区别,我会将您想要解决的问题归类为实用问题,这取决于其他两个步骤。
我在这里的解决方案只是将您想要做出的特定决定合并到单个解析运行中,以ss DCG 规则的可读性为代价:我们添加了一个额外的参数来收集已经解析的句子,a所谓的蓄能器。当我们开始解析时,历史记录是空的,这反映在规则ss(S) --> ss(S,[]). 上。对于实际规则,我们需要区分当前句子是否以指示代词开头。在第一种情况下,我们需要解决它,我们在这里通过查看前一句中可能的性别一致的名词短语来解决它。有了这个机器,我们就可以解析句子[peter, is, a father, '.', he, is a father,'.']:
?- phrase(ss(Tree), [peter,is,a,father,'.', he, is, a, father, '.']).
Tree = [s(np([name(peter, male)], name), vp([verb(is), np([article(a), object(father, male)], object)])), s(np([pronoun(he, male)], dpronoun), vp([verb(is), np([article(a), object(..., ...)], object)]))] ;
但我们无法解析[peter,is,a,father,'.', she, is, a, father, '.']:
?- phrase(ss(Tree), [peter,is,a,father,'.', she, is, a, father, '.']).
false.
在适当的语义/语用分析中,我们会用实际引用的名词短语来丰富代词短语,但这将作为对原始分析树的重写来完成。代码如下:
%%%% utility predicates
% gender_of(X,Y) is true if X is the gender of the syntax tree node Y
gender_of(X,name(_,X)).
gender_of(X,pronoun(_,X)).
gender_of(X,object(_,X)).
gender_of(G,np([X],_)) :-
gender_of(G,X).
gender_of(G,np([_,X],_)) :-
gender_of(G,X).
% nps_of(X,Y) is true if X is the list of nps occurring in the syntax tree node Y
nps_of([],vp([_])).
nps_of([NP],vp([_,NP])).
nps_of([NP|Rest],s(NP,VP)) :-
nps_of(Rest, VP).
% nountype_of(X,Y) is true if X is the type of the np node Y
nountype_of(X, np(_,X)).
% is_intransitive(X) is true if the verb X does not require an object phrase
is_intransitive(is).
is_intransitive(walk).
% is_transitive(X) is true if the verb X requires an object phrase
is_transitive(is).
% is_bitransitive(X) is true if the verb X requires two object phrases
is_bitransitive(is).
%%%% DCG rules
% name are distinct from objects because they do not require articles
name(name(peter,male)) --> [peter].
name(name(isabel,female)) --> [isabel].
name(name(guido,male)) --> [guido].
name(name(claudia,female)) --> [claudia].
% nouns that require an article
object(object(mother,female)) --> [mother].
object(object(father,male)) --> [father].
object(object(male,male)) --> [male].
object(object(female,female)) --> [female].
% verbs
verb(verb(is)) --> [is].
verb(verb(walk)) --> [walks].
% pronouns
pronoun(pronoun(he,male)) --> [he].
pronoun(pronoun(she,female)) --> [she].
% articles
article(article(a)) -->
[a].
article(article(the)) -->
[the].
% noun phrases
np(np([A,O],object)) -->
article(A),
object(O).
np(np([N],name)) -->
name(N).
np(np([PN], dpronoun)) -->
pronoun(PN).
% verb phrases
vp(vp([V,NP])) -->
verb(V),
{ V = verb(Name), is_transitive(Name) },
np(NP).
vp(vp([V])) -->
verb(V),
{ V = verb(Name), is_intransitive(Name) }.
end -->
['.'].
% a single sentence
s(s(NP,VP)) -->
np(NP),
vp(VP),
end.
% a list of sentences, with accumulator
ss([],_Acc) -->
[].
ss([S|Sentences],[]) -->
s(S),
ss(Sentences, [S]).
ss([S|Sentences], [LastS | Acc]) -->
{ S = s(np([Pronoun], dpronoun),_) },
s(S),
{ gender_of(G, Pronoun), nps_of(LastNPS, LastS), member(LNP, LastNPS), gender_of(G,LNP) },
ss(Sentences, [S, LastS | Acc]).
ss([S|Sentences], [LastS | Acc]) -->
{ S = s(NP,_), nountype_of(NT,NP), dif(NT,dpronoun) },
s(S),
ss(Sentences, [S, LastS | Acc]).
% wrapper of ss with empty accumulator
ss(S) -->
ss(S,[]).