Expressions are constructs denoting rules of computation whereby constants and current values of variables are combined to compute other values by the application of operators and function procedures. Expressions consist of operands and operators. Parentheses may be used to express specific associations of operators and operands.

With the exception of set constructors and literal constants (numbers, character constants, or strings), operands are denoted by *designators*. A designator consists of an identifier referring to a constant, variable, or procedure. This identifier may possibly be qualified by a module identifier (see sections Declarations and scope rules and Modules) and may be followed by selectors if the designated object is an element of a structure.

Designator = Qualident { "." ident | "[" ExpressionList "]" | "^" | "(" Qualident ")" }. ExpressionList = Expression {"," Expression}.

If a designates an array, then a[e] denotes that element of a whose index is the current value of the expression e. The type of e must be an integer type. A designator of the form a[e0,e1,...,en] stands for a[e0][e1]...[en]. If r designates a record, then r.f denotes the field f of r or the procedure f bound to the dynamic type of r (section Type-bound procedures). If p designates a pointer, p^denotes the variable which is referenced by p. The designators p^.f and p^[e] may be abbreviated as p.f and p[e], i.e. record and array selectors imply dereferencing. If a or r are read-only, then also a[e] and r.f are read-only.

A *type guard * v(T) asserts that the dynamic type of v is T (or an extension of T), i.e. program execution is aborted, if the dynamic type of v is not T (or an extension of T). Within the designator, v is then regarded as having the static type T. The guard is applicable, if

- v is a variable parameter of record type or v is a pointer, and if
- T is an extension of the static type of v

If the designated object is a constant or a variable, then the designator refers to its current value. If it is a procedure, the designator refers to that procedure unless it is followed by a (possibly empty) parameter list in which case it implies an activation of that procedure and stands for the value resulting from its execution. The actual parameters must correspond to the formal parameters as in proper procedure calls (see Formal parameters).

Examples of designators (refer to examples in Variable declarations):

i (INTEGER) a[i] (REAL) w[3].name[i] (CHAR) t.left.right (Tree) t(CenterNode).subnode (Tree)

Four classes of operators with different precedences (binding strengths) are syntactically distinguished in expressions. The operator `~` has the highest precedence, followed by multiplication operators, addition operators, and relations. Operators of the same precedence associate from left to right. For example, `x-y-z` stands for `(x-y)-z`.

Expression = SimpleExpression [ Relation SimpleExpression]. SimpleExpression = ["+" | "-"] Term {AddOperator Term}. Term = Factor {MulOperator Factor}. Factor = Designator [ActualParameters] | number | character | string | NIL | Set | "(" Expression ")" | "~" Factor. Set = "{"[Element {","Element}]"}". Element = Expression [".."Expression]. ActualParameters = "(" [ExpressionList] ")". Relation = "=" | "#" | "<" | "<=" | ">" | ">=" | IN | IS. AddOperator = "+" | "-" | OR. MulOperator = "*" | "/" | DIV | MOD | "&".

The available operators are listed in the following tables. Some operators are applicable to operands of various types, denoting different operations. In these cases, the actual operation is identified by the type of the operands. The operands must be *expression compatible* with respect to the operator (see Definition of terms).

OR |
logical disjunction | p OR q |
"if p then TRUE, else q" |

& |
logical conjunction | p & q |
"if p then q, else FALSE" |

~ |
negation | ~p |
"not p" |

These operators apply to BOOLEAN operands and yield a BOOLEAN result.

+ |
sum |

- |
difference |

* |
product |

/ |
real quotient |

DIV |
integer quotient |

MOD |
modulus |

The operators `+`, `-`, `*`, and `/` apply to operands of numeric types. The type of the result is the type of that operand which includes the type of the other operand, except for division (`/`), where the result is the smallest real type which includes both operand types. When used as monadic operators, - denotes sign inversion and + denotes the identity operation. The operators DIV and MOD apply to integer operands only. They are related by the following formulas defined for any x and positive divisors y:

x = (x DIV y) * y + (x MOD y) 0 <= (x MOD y) < y

Examples:

x | y | x DIV y | x MOD y |

5 | 3 | 1 | 2 |

-5 | 3 | -2 | 1 |

+ |
union |

- |
difference (x - y = x * (-y)) |

* |
intersection |

/ |
symmetric set difference (x / y = (x-y) + (y-x)) |

Set operators apply to operands of type SET and yield a result of type SET. The monadic minus sign denotes the complement of x, i.e. -x denotes the set of integers between 0 and MAX(SET) which are not elements of x. Set operators are not associative (`(a+b)-c # a+(b-c)`).

A set constructor defines the value of a set by listing its elements between curly brackets. The elements must be integers in the range 0..MAX(SET). A range a..b denotes all integers in the interval [a, b].

= |
equal |

# |
unequal |

< |
less |

<= |
less or equal |

> |
greater |

>= |
greater or equal |

IN |
set membership |

IS |
type test |

Relations yield a BOOLEAN result. The relations `=`, `#`, `<`, `<=`, `>` and `>=` apply to the numeric types, CHAR, strings, and character arrays containing 0X as a terminator. The relations `=` and `#` also apply to BOOLEAN and SET, as well as to pointer and procedure types (including the value NIL). `x IN s` stands for "x is an element of s". x must be of an integer type, and s of type SET. `v IS T` stands for "the dynamic type of v is T (or an extension of T)" and is called a *type test*. It is applicable if

- v is a variable parameter of record type or v is a pointer, and if
- T is an extension of the static type of v

Examples of expressions (refer to examples in Variable declarations):

1991 INTEGER i DIV 3 INTEGER ~p OR q BOOLEAN (i+j) * (i-j) INTEGER s - {8, 9, 13} SET i + x REAL a[i+j] * a[i-j] REAL (0<=i) & (i<100) BOOLEAN t.key = 0 BOOLEAN k IN {i..j-1} BOOLEAN w[i].name <= "John" BOOLEAN t IS CenterNode BOOLEAN