Custom DCG Operators
Asked Answered
A

1

5

Suppose I want to write a custom operator for composing DCG rules in a way that would otherwise be repetitive.

For example, suppose I had I a DCG, ws such that:

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

to match zero or more spaces. Obviously, if I want optional whitespace between each token in my grammar, it's obnoxious to have to put , ws everywhere.

I could define a new operator to replace ,/2.

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

This joines the left and right hand of --/2 via the optional whitespace rule. This mostly works fine, however certain things trip it up:

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

If I try and execute this rule, I get an error saying that ;/4 is not defined. I have a vague idea of the problem here, but basically the question is: is there a way to define new operators for DCGs that work with the same generality as ,/2?

Azotemia answered 27/7, 2018 at 17:30 Comment(2)
Please rather use 2 in place of *. That is: :- meta_predicate --(2,2,?,?).Rooks
Please do not expect to get answers, if you are deleting your question.Rooks
S
7

Yes, this is possible.

Currently, the main problem is:

?- callable("foo").
true.

So, I suggest this simpler definition:

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

In addition, I suggest:

:- set_prolog_flag(double_quotes, chars).

Sample query:

?- 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] .

As another example, let us use this rule instead:

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

Now we get for example:

?- 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] .

Note how iterative deepening is used for fair enumeration.

Sawtelle answered 27/7, 2018 at 17:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.