目前我在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])。) 谢谢!
答案 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标记与其名称相关联。