Syntax extension for |

Ulrich Neumerkel, 2009-12-03
This document provides an overview of the current practice of a syntax extension for | that is not part of 13211-1.

This extension is needed in particular in the context of DCG and CHR.

Status of | in 13211-1

In 13211-1:1995, the unquoted | can be used in a single situation: Within list notation (6.3.5) as a head tail separator (6.5.3).

Yap, SWI, SICStus all have some implementation specific extension to permit the solo character "head tail separator char" (6.5.3) as infix operator. It seems that Yap accepts the subset of SWI, that is also accepted by SICStus. However, the terms are compatible with SWI and not SICStus.

Prolog text YAP SWI SICStus B-Prolog
Default operators
(a|b). '|'(a,b). '|'(a,b). ;(a,b). '|'(a,b).
f(a|b). error f('|'(a,b)). error error
f(a|b,c). error f('|'(a,b),c). error error
f((a|b)). f('|'(a,b)). f('|'(a,b)). f(;(a,b)) f('|'(a,b)).
f(|). error f('|'). error error
f((|)). error f('|'). error error
'|'. '|'. '|'. '|'. '|'.
[|]. error ['|']. ** error error
[a|b|c]. error [a|'|'(b,c)]. ** error error
[a|b,c]. error [a|','(b,c)]. ** error error
(1;2|3;4). '|'(;(1,2),;(3,4)). '|'(;(1,2),;(3,4)). ;(1,;(2,;(3,4))). ;(1,'|'(2,;(3,4)))
current_op(A,xfy,'|'). A = 1105. A = 1105. no A = 1100.
current_op(A,xfy,;). A = 1100. A = 1100. A = 1100. A = 1100.
(fail|true). Success Success Success existence_error
With op(0,xfy,'|'), op(1100,fx,'|'), op(0,xfy,;), op(1100,fx,;).
|1. error '|'(1). error error
'|'1. '|'(1). '|'(1). '|'(1). '|'(1).
||. error '|'('|'). ** error error
;1. ;(1). ;(1). ;(1). ;(1).
;;. ;(;). ;(;). ;(;). ;(;).
Update 2010-06-25: Entries marked ** are now errors/warnings
Prolog text ECLiPSe
default
ECLiPSe
limit_arg_precedence
ECLiPSe
bar_is_no_atom
ECLiPSe
bar_is_no_atom
limit_arg_precedence
Default operators
(a|b). '|'(a,b). '|'(a,b). ;(a,b). ;(a,b)
f(a|b). f('|'(a,b)) error. f(;(a,b)). error
f(a|b,c). f('|'(a,b),c) error. f(;(a,b),c). error
f((a|b)). f('|'(a,b)). f('|'(a,b)). f(;(a,b)). f(;(a,b))
f(|). f('|') f('|') error error
f((|)). f('|') f('|') error. error
'|'. '|'. '|'. '|'. '|'
[|]. ['|'] ['|'] error error
[a|b|c]. error error error. error
[a|b,c]. error error error. error
(1;2|3;4). ;(1,'|'(2,;(3,4))). ;(1,'|'(2,;(3,4))).;(1,;(2,;(3,4)). ;(1,;(2,;(3,4)).
current_op(A,xfy,'|'). A = 1100. A = 1100. A = 1100. A = 1100.
current_op(A,xfy,;). A = 1100. A = 1100. A = 1100. A = 1100.
(fail|true). existence_error existence_error Success Success
With op(0,xfy,'|'), op(1100,fx,'|'), op(0,xfy,;), op(1100,fx,;).
|1. '|'(1) '|'(1) error. error
'|'1. '|'(1). '|'(1). '|'(1). '|'(1).
||. '|'('|'). '|'('|'). error error
;1. ;(1). ;(1). ;(1). ;(1).
;;. ;(;). ;(;). ;(;). ;(;).
The table headers refer to ECLiPSe's syntax options limit_arg_precedence and bar_is_no_atom, which can be set on a per-module basis. They are used in the compatibility packages.
The second row (limit_arg_precedence) seems to be the most promising for standardization.

So it seems, that | is permitted in a very restricted context.

Possible agreements

1 op(1105,xfy,'|') is added to the standard operator table.
This means that ( a '|' b ) is now portable.
2 "|" can be used unquoted as (xfy) infix operator. It represents either ('|')/2 or (;)/2. Implementation defined.
Maybe the respective operator entry should be used?
With both 1 and 2 it is possible to write a portable DCG translator. In the moment, where it is important to distinguish both cases, '|' must be used in place of |. Otherwise things will be represented differently but produce nevertheless same results with the exception of clause/2.
Validated HTML