Parsing 从prolog语句解析器处理信息

Parsing 从prolog语句解析器处理信息,parsing,prolog,Parsing,Prolog,我在prolog中创建了一个句子解析器。它成功地解析了用…输入的句子。。。 ?-句子([输入,句子,此处],解析)。 这是我用来分析句子的代码: np([X|T],np(det(X),NP2),Rem):- /* Det NP2 */ det(X), np2(T,NP2,Rem). np(Sentence,Parse,Rem):- np2(Sentence,Parse,Rem). /* NP2 */ np(Sentence,np(NP,PP),Rem):- /* NP PP */

我在prolog中创建了一个句子解析器。它成功地解析了用…输入的句子。。。
?-句子([输入,句子,此处],解析)。

这是我用来分析句子的代码:

np([X|T],np(det(X),NP2),Rem):- /* Det NP2 */
    det(X),
    np2(T,NP2,Rem).
np(Sentence,Parse,Rem):- np2(Sentence,Parse,Rem). /* NP2 */
np(Sentence,np(NP,PP),Rem):- /* NP PP */
    np(Sentence,NP,Rem1),
    pp(Rem1,PP,Rem).

np2([H|T],np2(noun(H)),T):- noun(H). /* Noun */
np2([H|T],np2(adj(H),Rest),Rem):- adj(H),np2(T,Rest,Rem).

pp([H|T],pp(prep(H),Parse),Rem):- /* PP NP */
    prep(H),
    np(T,Parse,Rem).

vp([H| []], vp(verb(H))):- /* Verb */
    verb(H).

vp([H|T], vp(verb(H), Rem)):- /* VP PP */
    vp(H, Rem),
    pp(T, Rem, _).

vp([H|T], vp(verb(H), Rem)):- /* Verb NP */
    verb(H),
    np(T, Rem, _).
我应该提到的是,输出将是:
句子(np(det(a)、np2(adj(very)、np2(adj(young)、np2(名词(boy‘‘‘)’))、vp(动词(loves)、np(det(a)、np2(adj(manual)、np2(名词(problem‘‘)’)))。

使用预定义的词汇表:
det(a)、adj(very)、adj(young)、名词(boy)、动词(loves)、det(a)、adj(manual)、名词(problem)

我想做的是将解析后的输出传递给谓词,谓词将单词分为三个不同的类别,即“主语、动词和宾语”

(1) 主语将包含前两个形容词,然后是一个名词

(2) 动词将保留“动词短语”中的动词

(3) 宾语将包含“动词短语”中的形容词和名词

所有限定词都应该被忽略

例如,我想要一个在输出中查找形容词的谓词


我已经尝试了很多方法,试图让它工作,但没有一个工作。任何帮助都将不胜感激。

下面的DCG会产生这种行为:

?- s(Sem,[a,young,boy,loves,a,manual,problem],[]).
Sem = [noun(boy),verb(loves),noun(problem)]
你的语法有一些问题。您的第三个
np
子句直接调用自身(不使用中间的输入),这意味着无限循环。您发布的语法似乎无法生成您的输出(非常年轻)。无论如何,这里是DCG:

s(Sem) -->
  np(Sem1), vp(Sem2), { append(Sem1,Sem2,Sem) }.

np(Sem) -->
  [W], { det(W) },
  np2(Sem).
np(Sem) -->
  np2(Sem).
np(Sem) -->
  np2(Sem1),
  pp(Sem2), { append(Sem1,Sem2,Sem) }.

np2([noun(W)]) -->
  [W], { noun(W) }.
np2(Sem) -->
  [W], { adj(W) },
  np2(Sem).

pp(Sem) -->
  [W], { prep(W) },
  np(Sem).

vp([verb(W)]) -->
  [W], { verb(W) }.
vp(Sem) -->
  [W], { verb(W) },
  np(Sem0), { Sem = [verb(W)|Sem0] }.
vp(Sem) -->
  [W], { verb(W) },
  pp(Sem0), { Sem = [verb(W)|Sem0] }.
另外:如果你想处理修改(例如形容词),那么有一些简单的明显的解决方案很快变得不切实际,还有一些更通用的技术,比如在
np
中添加一个逻辑变量

np(X,Sem) -->
  [W], { det(W) },
  np2(X,Sem).
np(X,Sem) -->
  np2(X,Sem).
np(X,Sem) -->
  np2(X,Sem1),
  pp(Sem2), { append(Sem1,Sem2,Sem) }.

np2(X,[noun(X,W)]) -->
  [W], { noun(W) }.
np2(X,[adj(X,W)|Sem]) -->
  [W], { adj(W) },
  np2(X,Sem).
此变量(
X
)从未实例化,它仅用于将名词短语的部分意思链接在一起

?- s(Sem,[a,young,boy,loves,a,manual,problem],[]).
Sem = [adj(_A,young),noun(_A,boy),verb(loves),adj(_B,manual),noun(_B,problem)]
还有各种其他的可能性。好书有Gazdar&Mellish,Prolog中的NLP,以及Norvig,AI编程的范例(如果你说Lisp),还有Pereira&Shieber,Prolog和自然语言分析

补充#2:在再次阅读您的问题之后,我意识到您实际上想要三个独立的列表。没问题

s(L1,L2,L3) -->
  np(_,L1), vp(L2,L3).

np(X,L) -->
  [W], { det(W) },
  np2(X,L).
np(X,L) -->
  np2(X,L).
np(X,L) -->
  np2(X,L),
  pp(_).

np2(X,[noun(X,W)]) -->
  [W], { noun(W) }.
np2(X,[adj(X,W)|L]) -->
  [W], { adj(W) },
  np2(X,L).

pp(L) -->
  [W], { prep(W) },
  np(_,L).

vp([verb(W)],[]) -->
  [W], { verb(W) }.
vp([verb(W)],L) -->
  [W], { verb(W) },
  np(_,L).
vp([verb(W)],L) -->
  [W], { verb(W) },
  pp(L).
输出:

| ?- s(L1,L2,L3,[a,young,boy,loves,a,manual,problem],[]).
L1 = [adj(_A,young),noun(_A,boy)],
L2 = [verb(loves)],
L3 = [adj(_B,manual),noun(_B,problem)] ? 

现在,也许你不需要逻辑变量,但另一方面,你可以有更复杂的修饰符,比如“一个小男孩喜欢涉及红色螺栓和白色立方体的手工问题”。然后变量将跟踪哪个形容词修饰哪个名词。

那么,我正在进行第二次尝试

输出将是:
句子(np(det(a),np2(adj(very),
np2(形容词(年轻的),np2(名词(男孩‘‘)’)),vp(动词(爱),np(形容词(a),
np2(形容词(手动),np2(名词(问题‘‘‘‘‘)’)
。[…]我想做的是 将解析后的输出传递给将分隔单词的谓词 分为三个不同的类别,即“主语、动词和” 对象”

您可以编写这样的过程,从结构映射到单词列表

handle_sent(sentence(NP1,vp(V,NP2)),Subj,Verb,Obj) :-
  handle_np(NP1,Subj), handle_verb(V,Verb), handle_np(NP2,Obj).

handle_verb(verb(V),[V]).

handle_np(np(_,np2(adj(A),np2(noun(N)))),[A,N]).
handle_np(np(_,np2(adj(A1),np2(adj(A2),np2(noun(N))))),[A1,A2,N]).
这将产生:

?- handle_sent(...,Subj,Verb,Obj).
Subj = [very,young,boy]
Verb = [loves]
Obj = [manual,problem]

好啊我已经添加了我用来解析句子的代码。我是否可以通过使用单独的谓词来完成这项工作,比如通过将解析后的值传递给它们来实现“ExtractNounophase(np(det(A),):-”?这就像有两个解析器,因为您当前生成的输出与语法规则是同构的。DCG更好。我知道DSG更好(因为人们一直告诉我),但我仍然要学习这一点。我想知道你是否可以用我一直在做的方式告诉我怎么做。