3

目前我正在使用 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 中的参数(例如 [E] in xml([E]); [E|L] in xml([E|L])。)谢谢!

4

1 回答 1

4

以声明的方式思考:DCG 总是描述一个列表。在 DCG 正文中,逗号 (",") 读作“然后”。例如,xml//1 描述(通过它的第一条规则)单个元素,或者(通过它的第二条规则)一个元素,然后再由 xml//1 描述的东西。element//1 是一个开始标签,然后是元素,然后是一个结束标签等。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 标记与其名称相关联。

于 2010-11-04T22:16:35.953 回答