我在prolog中创建了一个句子解析器。它成功解析输入的句子......
?- sentence([input,sentence,here],Parse).
这是我用来解析句子的代码:
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, _).
我应该提到输出为:sentence(np(det(a), np2(adj(very), np2(adj(young), np2(noun(boy))))), vp(verb(loves), np(det(a), np2(adj(manual), np2(noun(problem)))))).
使用预定义词汇表:det(a), adj(very), adj(young), noun(boy), verb(loves), det(a), adj(manual), noun(problem)
。
我想要做的是将解析后的输出传递给谓词,谓词将单词分成三个不同的类别,即主题,动词和对象"。
(1)主语将持有前两个形容词,然后是名词。
(2)动词将保留"动词短语"中的动词。
(3)并且该对象将在"动词短语"中保留形容词和名词。
应忽略所有决定者。
例如,我想要一个在输出中寻找形容词的谓词。
我尝试了许多尝试让它工作但没有工作。任何帮助将不胜感激。
答案 0 :(得分:2)
我正在进行第二次尝试。
输出为:
sentence(np(det(a), np2(adj(very), np2(adj(young), np2(noun(boy))))), vp(verb(loves), np(det(a), np2(adj(manual), np2(noun(problem))))))
。 [...]我想做的是 将解析后的输出传递给将单词分隔的谓词 分为三个不同的类别,分别是主语,动词和 对象"
您可以编写这样的程序,从您的结构映射到单词列表。
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]
答案 1 :(得分:1)
以下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, NLP in Prolog ,Norvig,范例的AI编程(如果你说Lisp),以及Pereira& Shieber, Prolog和自然语言分析。
添加#2:再次阅读您的问题后,this other question,我意识到您确实需要三个单独的列表。没问题。
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)] ?
现在也许你不需要逻辑变量,但另一方面,你可能有更复杂的修饰符,比如"一个小男孩喜欢涉及红色螺栓和白色立方体的手动问题" 。然后变量将跟踪哪个形容词修改哪个名词。