Пользовательские операторы DCG

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

Например, предположим, что у меня есть DCG, ws такой, что:

ws --> [].
ws --> " ", ws.

чтобы соответствовать нулю или большему количеству пробелов. Очевидно, что если я хочу, чтобы между каждым токеном в моей грамматике был необязательный пробел, было бы неприятно помещать , ws везде.

Я мог бы определить новый оператор для замены ,/2.

:- op(1000, xfy, [ -- ]).
:- meta_predicate --(*,*,?,?).
--(L,R) --> ({callable(L)} -> call(L); L), ws, ({callable(R)} -> call(R); R).

Это соединяет левую и правую части --/2 с помощью необязательного правила пробелов. В основном это работает нормально, однако некоторые вещи сбивают его с толку:

rule --> "foo" -- ("bar"; "quux").

Если я попытаюсь выполнить это правило, я получаю сообщение об ошибке, что ;/4 не определено. У меня смутное представление о проблеме, но в основном вопрос заключается в следующем: есть ли способ определить новые операторы для DCG, которые работают с той же общностью, что и ,/2?


person junius    schedule 27.07.2018    source источник
comment
Пожалуйста, используйте 2 вместо *. То есть: :- meta_predicate --(2,2,?,?).   -  person false    schedule 01.08.2018
comment
Не ожидайте ответа, если удаляете свой вопрос.   -  person false    schedule 17.03.2020


Ответы (1)


Да, это возможно.

В настоящее время основная проблема:

?- callable("foo").
true.

Итак, я предлагаю более простое определение:

--(L, R) --> L, ws, R.

Кроме того, предлагаю:

:- set_prolog_flag(double_quotes, chars).

Пример запроса:

?- phrase(rule, Ls).
Ls = [f, o, o, b, a, r] ;
Ls = [f, o, o, q, u, u, x] ;
Ls = [f, o, o, ' ', b, a, r] ;
Ls = [f, o, o, ' ', q, u, u, x] ;
Ls = [f, o, o, ' ', ' ', b, a, r] .

В качестве другого примера давайте воспользуемся этим правилом:

rule --> "foo" -- ("bar" | "quux") -- "test".

Теперь получаем например:

?- length(Ls, _), phrase(rule, Ls).
Ls = [f, o, o, b, a, r, t, e, s, t] ;
Ls = [f, o, o, b, a, r, ' ', t, e, s, t] ;
Ls = [f, o, o, q, u, u, x, t, e, s, t] ;
Ls = [f, o, o, ' ', b, a, r, t, e, s, t] ;
Ls = [f, o, o, b, a, r, ' ', ' ', t, e, s, t] ;
Ls = [f, o, o, q, u, u, x, ' ', t, e, s, t] ;
Ls = [f, o, o, ' ', b, a, r, ' ', t, e, s, t] ;
Ls = [f, o, o, ' ', q, u, u, x, t, e, s, t] ;
Ls = [f, o, o, ' ', ' ', b, a, r, t, e, s, t] ;
Ls = [f, o, o, b, a, r, ' ', ' ', ' ', t, e, s, t] .

Обратите внимание, как итеративное углубление используется для точного перечисления.

person mat    schedule 27.07.2018