请Prolog DCG插图

时间:2010-11-04 20:13:00

标签: prolog grammar dcg

目前我在Prolog中使用DCG来解析XML文件。我能够获得以下代码片段,它能够解析一个简单的XML,例如:

<author> <name> <f> arthur </f>
        <m> conan </m>
        <l> doyle </l>
     </name>
     <bday> <d> 22 </d>
        <m> 5  </m>
        <y> 1859 </y>
     </bday>
</author>

<author> <name> <f> william </f>
        <l> shakespeare </l>
     </name>
     <bday> <d> 23 </d>
        <m> 4  </m>
        <y> 1564 </y>
     </bday>
</author>
$

,DCG定义为:

xml([E]) --> element(E).
xml([E|L]) --> element(E), xml(L).

element(E) -->  begintag(N), elements(L), endtag(N), {E =.. [N|L]}.

elements(L) --> xml(L).
elements([E]) --> [E].

begintag(N) --> ['<', N, '>'].
endtag(N) -->   ['<', '/', N, '>'].

有人请说明DCG在这种情况下的工作原理吗?我很难理解DCG中的参数(例如xml中的[E]([E]); xml中的[E | L]([E | L])。) 谢谢!

1 个答案:

答案 0 :(得分:3)

以声明的方式思考:DCG总是描述一个列表。在DCG正文中,逗号(“,”)被读作“然后”。因此,例如,xml // 1(通过其第一个规则)描述单个元素,或(通过其第二个规则)元素然后再次由xml // 1描述的内容。 element // 1是一个begintag,然后是元素,然后是endtag等.DCG头中使用的参数让你将DCG体所描述的序列与其他信息联系起来,比如你特别感兴趣的子序列。示例begintag // 1 - 您可以问:

?- phrase(begintag(T), [<, test, >]).
T = test.

以及另一个方向:

?- phrase(begintag(test), Ls).
Ls = [<, test, >].

对于begintag // 1,标记名称似乎对您很重要,因此您为其引入了一个参数,一方面,您可以生成具有给定名称的开始标记,以及另一方面,让你解析一个标签并提取它的名字,第三方面,甚至询问最常见的查询:

?- phrase(begintag(T), Ls).
Ls = [<, T, >].

抽象地将开放XML标记与其名称相关联。