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?

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
junius
  • 570
  • 3
  • 14
  • 2
    Please rather use `2` in place of `*`. That is: `:- meta_predicate --(2,2,?,?)`. – false Aug 01 '18 at 09:23
  • Please do not expect to get answers, if you are deleting your [question](https://stackoverflow.com/q/60712682/772868). – false Mar 16 '20 at 21:42

1 Answers1

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.

mat
  • 40,498
  • 3
  • 51
  • 78