DCG (грамматики с определенными предложениями) - это компактный способ описания списков в Прологе.

DCG (грамматики с определенными предложениями) - это компактный способ описания списков в Прологе.

DCG обычно связаны с прологом, но подобные языки, такие как mercury, также включают DCG. Их называют грамматиками с определенными предложениями, потому что они представляют грамматику как набор определенных предложений в логике первого порядка.

Некоторые интересные материалы доступны в виде пакетов SWI-Prolog, например

  • dcg_util Майкла Хендрикса
  • dcgutils Самера Абдаллаха
  • dot_dcg, автор: Ли Кумбер
  • pac от Кунаики Мукаи (продвинутый Пролог, не только DCG!)
  • edgc от Peter Van Roy, Майкл Хендрикс
  • а может еще какой.

Мне нравится думать о DCG как о практических грамматиках атрибутов.


Ссылки:

DCG обеспечивают абстракцию состояния потоковой передачи: не нарушайте ее


Примечание: при использовании DCG с SWI-Prolog помните о строковом типе и его синтаксисе в двойных кавычках.

Другими словами, многие примеры DCG здесь, в блогах и в статьях используют традиционное определение Пролога для двойных кавычек. Если вы возьмете такой код и будете использовать его с SWI-Prolog, он иногда выйдет из строя.

Чтобы избежать этой проблемы, есть флаги Пролога для изменения определения двойных и обратных кавычек.

Пример Prolog DCG, который устанавливает флаги Prolog.

:- module(course,
      [ courses//1,
        parse_courses/2
      ]).

:- [library(dcg/basics)].

:- set_prolog_flag(double_quotes, string).
:- set_prolog_flag(back_quotes, codes).

courses([Course|Courses]) -->
    course(Course),
    courses(Courses), !.
courses([]) --> [].

course(course(Course,Students)) -->
    string_without("\n", Course_codes),
    { string_codes(Course,Course_codes ) },
    "\n",
    students(Students),
    (
        empty_line
    ;
        []
    ).

students([Student|Students]) -->
    student(Student),
    students(Students).
students([]) --> [].

student(Student) -->
    spaces_or_tabs_plus,
    (
        (
            string_without("\n",Student_codes),
            { string_codes(Student,Student_codes) },
            "\n"
        )
    ;
        remainder(Student_codes),
        { string_codes(Student,Student_codes) }
    ).

spaces_or_tabs_plus -->
    space_or_tab,
    spaces_or_tabs_star.

spaces_or_tabs_star -->
    space_or_tab,
    spaces_or_tabs_star.
spaces_or_tabs_star --> [].

space_or_tab -->
    (
        "\s"
    |
        "\t"
    ).

empty_line --> "\n".

parse_courses(Codes,Courses) :-
    DCG = courses(Courses),
    phrase(DCG,Codes,Rest),
    assertion( Rest == [] ).

:- begin_tests(course).

:- set_prolog_flag(double_quotes, string).
:- set_prolog_flag(back_quotes, codes).

test(001) :-
    Input = "\c
        MATH2221\n\c
            \t201000001\n\c
            \t201000002\n\c
            \n\c
        MATH2251\n\c
            \t201000002\n\c
            \t201000003\n\c
            \n\c
        COMP2231\n\c
            \t201000003\n\c
            \t201000001\c
        ",
    string_codes(Input,Codes),
    parse_courses(Codes,Courses),

    assertion( Courses ==
        [
            course("MATH2221",["201000001","201000002"]),
            course("MATH2251",["201000002","201000003"]),
            course("COMP2231",["201000003","201000001"])
        ]
    ).

:- end_tests(course).