Well (|)/2 is an operator similar to (,)/2. But you can
easily get confused. The main point is in the production
rules for infix operator and postfix operator.
Where you would allow more atoms than in the rules for
compound functor. So that (|)/2 and (,)/2 can act as
deleminter in argument lists and normal lists.
The characters of (|)/2 and (,)/2 have double role,
namely they can be operators and they can be delemiters,
namely they their second role besides operator is:
- (|)/2 as delemiter:
in normal lists,
examples [a,b,c|d], [X|Y]
- (,)/2 as delemiter:
in argument lists and normal lists,
examples f(1,2), [a,b,c|d], [1,2]
But you don't need to touch any token rules. Especially
not any quoted token rules. You only need to touch the
heigher level production rules for infix, postfix,
and for the lists. This can be admitedly a challenge
to get the grammar right. But you can check implementations
for how they are doing it. Or their documentation.
So the following new production is already step forward:
op = bar ;
For example one might think this is the correct production
for expressions, thats actually the simple view:
expression(M) --> "(" term(1200) ")" { M=0 }
| op(M,fx) term(M-1)
| op(M,fy) term(M)
| term(M-1) op(M,xfx) term(M-1)
| term(M-1) op(M,xfy) term(M)
| term(M) op(M,yfx) term(M-1)
| term(M-1) op(M,xf)
| term(M) op(M,yf).
op(M,I) --> atom(O) { current_op(M,I,O) }.
Unfortunately this is also more or less the syntax
found in the good old DEC-10 Prolog manual. Just check
page 78 here:
Naive Syntax, already purported by DEC-10 Prolog
https://www.cs.cmu.edu/Groups/AI/lang/prolog/doc/intro/prolog.doc
But in my opinion, the more elaborate syntax reads
as follows, and gives better results. Namely there
are two types of operators:
expression(M) --> "(" term(1200) ")" { M=0 }
| op1(M,fx) term(M-1)
| op1(M,fy) term(M)
| term(M-1) op2(M,xfx) term(M-1)
| term(M-1) op2(M,xfy) term(M)
| term(M) op2(M,yfx) term(M-1)
| term(M-1) op2(M,xf)
| term(M) op2(M,yf).
op1(M,I) --> atom(O) { current_op(M,I,O) }.
op2(M,I) --> operator(O) { current_op(M,I,O) }.
operator --> atom
| "|" | "," | ".".
You can also add features. Like for example the array
index notation, which is available in a few Prolog
systems, like SWI-Prolog, Jekejeke Prolog, just use:
operator --> atom
| "[" arguments "]"
| "|" | "," | ".".
http://www.jekejeke.ch/idatab/doclet/prod/en/docs/05_run/10_docu/02_reference/06_syntax/02_term/04_expressions.html
But I guess the ISO standard is not up to adding
array index notation. But array index notation is
cute, you find it also in Picat, here is a SWI-Prolog
documentation about it:
Block operators
http://www.swi-prolog.org/pldoc/man?section=ext-blockop
So what is the bottomline of this post? Well I
say op = bar is a good idea. But upon reflection,
its also a bad idea. A much better idea would have
to have two ops, op1 for prefix and op2 for
infix and postfix, you can then do the following,
only add bar to op2:
op1 = ... ; /* as before */
op2 = ... /* as before */
| bar ; /* new addition, maybe */
Disclaimer: I didn't check the ISO/IEC document,
and gave a ready to use fix of the ISO/IEC document.
I only wanted to communicate that there are op1 and op2,
that this is one solution to fix the syntax problem.
Of course one can then redefine the syntax on paper,
but one can also directly implement it then as such.