【问题标题】:Creating a DCG capable of parsing trees in Prolog在 Prolog 中创建能够解析树的 DCG
【发布时间】:2020-09-27 05:10:05
【问题描述】:

我必须在 Prolog 中创建一个具有以下功能的 DCG:

  1. 处理主客体区分
  2. 单数/复数区别
  3. 能够生成解析树
  4. 使用单独的词典

这是给定的词典:

lex(the,det,_).
lex(a,det,singular).
lex(man,n,singular).
lex(men,n,plural).
lex(woman,n,singular).
lex(women,n,plural).
lex(apple,n,singular).
lex(apples,n,plural).
lex(pear,n,singular).
lex(pears,n,plural).

lex(eat,v,plural).
lex(eats,v,singular).
lex(know,v,plural).
lex(knows,v,singular).

lex(i,pronoun,singular,subject).
lex(we,pronoun,plural,subject).
lex(me,pronoun,singular,object).
lex(us,pronoun,plural,object).
lex(you,pronoun,_,_).
lex(he,pronoun,singular,subject).
lex(she,pronoun,singular,subject).
lex(him,pronoun,singular,object).
lex(her,pronoun,singular,object).
lex(they,pronoun,plural,subject).
lex(them,pronoun,plural,object).
lex(it,pronoun,singular,_).

这是我的代码:

s(s(NP,VP)) --> np(NP,X,subject), vp(VP,X).

np(np(DET,N),X,_) --> det(DET,X), n(N,X).
np(np(PRO),X,Y) --> pro(PRO,X,Y).

vp(vp(V,NP),X) --> v(V,X), np(NP,_,object).
vp(vp(V),X) --> v(V,X).

det(det(DET),X) --> [DET], {lex(DET,det,X)}.

n(n(N),X) --> [N], {lex(N,n,X)}.

pro(pro(PRO),X,Y) --> [PRO], {lex(PRO,pro,X,Y)}.

v(v(V),X) --> [V], {lex(V,v,X)}.

当我输入时:

s(X, [the, man, eats, the, apple], []).

我应该得到:

X = s(np(det(the, singular), n(man, singular, subject)), vp(v(eats, singular), np(det(the, singular), n(apple, singular, object))))

但是我得到了:

X = s(np(det(the), n(man)), vp(v(eats), np(det(the), n(apple)))) 

我不确定为什么它没有输出完整的东西。

【问题讨论】:

    标签: parsing tree prolog grammar dcg


    【解决方案1】:

    像这样调用 DCGs

    rule(Args, List, Rest)
    

    仍然有许多来源教授的有点“旧式”,但更“现代”的方式是改用phrase/[2,3]

    ?- phrase(s(Tree), [the, man, eats, the, apple]).
    Tree = s(np(det(the), n(man)), vp(v(eats), np(det(the), n(apple)))) ;
    false.
    
    ?- phrase(s(Tree), [the, man, eats, the, apple], Rest).
    Tree = s(np(det(the), n(man)), vp(v(eats), np(det(the), n(apple)))),
    Rest = [] ;
    Tree = s(np(det(the), n(man)), vp(v(eats))),
    Rest = [the, apple] ;
    false.
    

    在您想要完整解析的常见情况下,双参数形式使您无需将其余部分指定为[]。您还将 DCG 规则的参数与要解析的列表分开。因此,在phrase 调用中,s 采用单个参数作为语法树,就像在其定义中一样。

    至于你的问题,好在 Prolog 是一种非常可测试的语言。如果一些大问题——比如解析一个完整的句子——出错了,我们可以分解问题并测试较小的部分——比如解析一个名词短语,或者只是一个名词。

    因此,将主题分解为越来越小的部分:

    ?- phrase(np(Tree, Number, Role), [the, man]).
    Tree = np(det(the), n(man)),
    Number = singular ;
    false.
    
    ?- phrase(det(Tree, Role), [the]).
    Tree = det(the).
    
    ?- phrase(n(Tree, Number), [man]).
    Tree = n(man),
    Number = singular.
    

    您想将名词短语解析为np(det(the, singular), n(man, singular, subject)),但您从detn 获得的实际树已经缺少一些额外的参数。你需要调整这些:

    det(det(DET, Number), Number) --> [DET], {lex(DET, det, Number)}.
    
    n(n(N, Number, _Role), Number) --> [N], {lex(N, n, Number)}.
    

    这样你得到:

    ?- phrase(det(Tree, Role), [the]).
    Tree = det(the, Role).
    
    ?- phrase(n(Tree, Number), [man]).
    Tree = n(man, singular, _2114),
    Number = singular.
    
    ?- phrase(np(Tree, Number, Role), [the, man]).
    Tree = np(det(the, singular), n(man, singular, _2178)),
    Number = singular ;
    false.
    

    整个句子的解析现在是:

    ?- phrase(s(Tree), [the, man, eats, the, apple]).
    Tree = s(np(det(the, singular), n(man, singular, _2210)), vp(v(eats), np(det(the, singular), n(apple, singular, _2240)))) ;
    false.
    

    限定词和名词上的额外参数现在在那里。缺少的是对动词和名词短语做同样的事情,以便正确绑定“角色”(主语或宾语)。

    【讨论】:

    • 感谢您的回答,但我实际上无法使用 Phrase。我无法编辑测试用例的输入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-02
    • 1970-01-01
    相关资源
    最近更新 更多