Пролог DCG иллюстрация пожалуйста - PullRequest
2 голосов
/ 04 ноября 2010

В настоящее время я играю с 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] в xml ([E]); [E | L] в xml ([E | L]).) Спасибо!

1 Ответ

3 голосов
/ 05 ноября 2010

Думайте декларативно: DCG всегда описывает список. В теле DCG запятая (",") читается как "и затем". Так, например, xml // 1 описывает (по своему первому правилу) либо отдельный элемент, либо (по второму правилу) элемент , а затем что-то, что снова описывается с помощью xml // 1. элемент // 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 с его именем.

...