Precedence
Expr := "{" Expr "}"
Expr := "(" Expr ")"
Precedence can be indicated with either curly braces or parentheses. When used for this purpose, the two are exactly equivalent.
For readability, it can be helpful to always use (...)
for singleton relations (scalars) and {...}
for relations that are not singletons.
For example, (x + y) * z
versus {x, y, z: p(x, y, z)}
.
All binary operators associate to the left, unless otherwise stated below.
For example, x - y + z
is equivalent to (x - y) + z
.
From highest precedence to lowest:
_
, variables, names of relations, qualified names, literals,()
, and{}
..
.- Relational application and partial relational application.
^
(associates to the right).- Unary
-
. /
,%
,*
,÷
,×
,⊗
, and⊙
.-
,+
,⊕
,∩
, and⊓
.∪
and⊔
.=
,!=
,≈
,∼
,≠
,<
,>
,<=
,≤
,>=
,≥
,⊆
,⊇
,⊂
,⊃
,≼
,≽
,≺
,≻
,→
, and←
.¬
andnot
.forall
,∀
,exists
, and∃
.∧
andand
.∨
andor
.⇐
,⇒
(associates to the right), andimplies
(associates to the right).≡
,⇔
,⊻
,≢
,⇎
,xor
, andiff
.<:
and:>
.<++
and++>
.,
.;
.:
(associates to the right).
Note that relational application and partial relational application are created with an implicit operator.
The precedence of this operator is lower than that of the composition operator .
, so an expression such as P . Q[x]
is parsed as (P . Q)[x]
.
If this is not what you want, you should use explicit parentheses, for example: P . (Q[x])
.
The following example illustrates this:
// read query
def P = (1, 2)
def Q = {("a", 1); ("a", 2)}
def output:A = Q . P
def output:B = Q . P["a"]
def output:BB = (Q . P)["a"]
def output:BBB = Q . (P["a"])
def output:C = Q . P[1]
def output:CC = (Q . P)[1]
def output:CCC = Q . (P[1])
def output:D = Q . P("a", 2)
def output:DD = (Q . P)("a", 2)
def output:DDD = Q . (P("a", 2))
Next: Relation Literals