expression = value-expression | reference-expression | designational-expression value-expression = arithmetic-expression | Boolean-expression | character-expression reference-expression = object-expression | text-expression
The primary constituents of programs describing algorithmic processes are expressions. Constituents of these expressions, except for certain delimiters, are constants, variables, function designators, labels, class and attribute identifiers, switch designators and elementary operators. Since the syntactic definition of both variables and function designators (see below) contain expressions, the definition of expressions and their constituents is necessarily recursive.
A value expression is a rule for obtaining a value.
An object expression is a rule for obtaining an object reference.
A text expression is a rule for obtaining an identification of a text variable (and thereby a text reference).
A designational expression is a rule for obtaining a reference to a program point.
Any value expression or reference expression has an associated type, which is textually defined.
variable = simple-variable-1 | subscripted-variable simple-variable-1 = identifier-1 subscripted-variable = array-identifier-1 "(" subscript-list ")" array-identifier-1 = identifier-1 subscript-list = subscript-expression { , subscript-expression } subscript-expression = arithmetic-expression
A variable local to a block instance is a memory device whose "contents" are either a value or a reference, according to the type of the variable. The contents of a variable may be changed by an appropriate assignment operation, see 4.1. A reference is a piece of information which identifies a value, called the "referenced" value. The distinction between a reference and the referenced value is determined by context.
Variables are of two kinds, corresponding to the values being represented, namely value type variables and reference type variables.
A value type variable has a value which is the contents of the variable. A reference type variable is said to have a value which is the one referenced by the contents of the variable.
The value of an array identifier is the ordered set of values of the corresponding array of subscripted variables.
Examples
delta a17 q(7,2) x(sin(n*pi/2),q(3,n,4))
A simple-variable-1 is any variable which is not a subscripted variable. The corresponding values are described in chapter 2.
Note: Certain syntax classes (such as simple-variable-1) are marked with a "-1". The corresponding program terms may contain a remote identifier (see 5.5.6).
Value type variables have values of integer type, real type, Boolean or character.
An object reference variable has an object as its value (or the value none). Text variables are described below.
A text variable is conceptually an instance of a composite structure with four constituent components (attributes):
ref (TEXTOBJ) OBJ; integer START, LENGTH, POS;
Let X be a text variable. Then X.OBJ, X.START, X.LENGTH and X.POS denote the components of X, respectively. These four components are not directly accessible to the user. Instead, certain properties of a text variable are represented by procedures accessible through the dot notation. These procedures are described in chapter 8.
The components OBJ, START and LENGTH constitute the text reference part of the variable. They identify the frame referenced (see 2.5.1). POS is used for accessing the individual characters of the frame referenced (see 9.2).
The components of a text variable always satisfy one of the following two sets of conditions:
1) OBJ =/= none START >= 1 LENGTH >= 1 START + LENGTH <= OBJ.SIZE + 1 1 <= POS <= LENGTH + 1 2) OBJ == none START = 1 LENGTH = 0 POS = 1
The latter alternative defines the contents of a variable which references no frame. Note that this alternative thereby defines the special text reference notext.
Subscripted variables designate values which are components of multi- dimensional arrays. Each arithmetic expression of the subscript list occupies one subscript position of the subscripted variable and is called a subscript. The complete list of subscripts is enclosed by the subscript parentheses ( ) . The array component referred to by a subscripted variable is specified by the actual value of its subscripts.
Each subscript position acts like a variable of type integer and the evaluation of the subscript is understood to be equivalent to an assignment to this fictitious variable. The value of the subscripted variable is defined only if the actual integer value of each subscript expression is within the associated subscript bounds of the array. A subscript expression value outside its associated bounds causes a run time error.
function-designator = procedure-identifier-1 [ actual-parameter-part ] procedure-identifier-1 = identifier-1 actual-parameter-part = "(" actual-parameter { , actual-parameter } ")" actual-parameter = expression | array-identifier-1 | switch-identifier | procedure-identifier-1
A function designator defines a value which results through the application of a given set of rules defined by a procedure declaration (see 5.4) to a fixed set of actual parameters. The rules governing specification of actual parameters are given in 4.6.
Note: Not every procedure declaration defines rules for determining the value of a function designator (cf. 5.4.1).
Examples
sin(a-b) j(v+s,n) r ss(s-5, !Temperature; T, !Pressure; P) compile ("( := )", !Stack; q)
identifier-1 = identifier | remote-identifier remote-identifier = simple-object-expression . attribute-identifier | text-primary . attribute-identifier attribute-identifier = identifier
Let X be a simple object expression qualified by the class C, and let A be an appropriate attribute identifier. Then the remote identifier "X.A", if valid, is an attribute identification whose object is the value X and whose qualification is C (cf. 5.5.6).
The remote identifier X.A is valid if the following conditions are satisfied:
Note: Condition 1 corresponds to a check which causes an error if the
value of X is none.
Condition 2 is an ad hoc rule intended to simplify the language and
its implementations.
A remote identifier of the form
text-primary.attribute-identifier
identifies an attribute of the text variable identified by evaluating the text primary, provided that the attribute identifier is one of the procedure identifiers defined in chapter 8.
Note: Even if the text primary references notext, the attribute access is legal (in contrast to object expressions).
Example
Let P1 and P2 be variables declared and initialized as in example 2 of 4.1.4. Then the value of the expression
P1.plus (P2)is a new "point" object which represents the vector sum of P1 and P2. The value of the expression
P1 qua polar.plus (P2)is a new "polar" object representing the same vector sum.
Boolean-expression = simple-Boolean-expression | if-clause simple-Boolean-expression else Boolean-expression simple-Boolean-expression = Boolean-tertiary { or else Boolean-tertiary } Boolean-tertiary = equivalence { and then equivalence } equivalence = implication { eqv implication } implication = Boolean-term { imp Boolean-term } Boolean-term = Boolean-factor { or Boolean-factor } Boolean-factor = Boolean-secondary { and Boolean-secondary } Boolean-secondary = [ not ] Boolean-primary Boolean-primary = logical-value | variable | function-designator | relation | "(" Boolean-expression ")"
A Boolean expression is of type Boolean. It is a rule for computing a logical value. Except for the operators and then and or else (see 3.4) the semantics are entirely analogous to those given for arithmetic expressions.
Variables and function designators entered as Boolean primaries must be of type Boolean.
Examples
x = -2 Y>v or z<q a+b> -5 and z-d>q**2 p and not q or x<>y t.more and then t.getchar x == none or else x.a>0 if k<1 then s>w else h<=c if if if a then b else c then d else f then g else h<k
relation = arithmetic-relation | character-relation | text-value-relation | object-relation | object-reference-relation | text-reference-relation value-relational-operator = < | <= | = | >= | > | <> reference-comparator = == | =/=
The value relational operators have the conventional meaning. Their specific interpretation is described below in connection to the respective types. The reference comparators have the same priority level as the relational operators.
arithmetic-relation = simple-arithmetic-expression value-relational-operator simple-arithmetic-expression
The relational operators <, <=, =, >=, > and <> have their conventional meaning (less than, less than or equal to, equal to, greater than or equal to, greater than, not equal to). Arithmetic relations assume the value true whenever the corresponding relation is satisfied for the expressions involved, otherwise false. If the two constituent expressions are of different arithmetic types conversion to the type with maximum value range is assumed. Consequently overflow cannot occur during the evaluation.
character-relation = simple-character-expression value-relational-operator simple-character-expression
Character values may be compared for equality and inequality and ranked with respect to the collating sequence. Let X and Y be simple character expressions, and let rel be any value relational operator. Then the relation "X rel Y" has the same Boolean value as the relation "rank(X) rel rank(Y)".
Note: Because of variations in collating sequences the value of a character relation (and by implication that of a text relation, see below) is implementation-defined. Implementation-independent comparison of character values is obtained by using the procedure "isorank".
text-value-relation = simple-text-expression value-relational-operator simple-text-expression
Two text values are equal if they are both empty, or if they are both instances of the same character sequence, otherwise they are unequal.
A text value T ranks lower than a text value U if and only if they are unequal and one of the following conditions is fulfilled:
object-relation = simple-object-expression is class-identifier | simple-object-expression in class-identifier
The operators is and in may be used to test the class membership of an object.
The relation "X is C" has the value true if X refers to an object belonging to the class C, otherwise the value is false.
The relation "X in C" has the value true if X refers to an object belonging to a class C or a class inner to C, otherwise the value is false.
object-reference-relation = simple-object-expression reference-comparator simple-object-expression
The reference comparators == and =/= may be used for the comparison of references (as distinct from the corresponding referenced values). Two object references X and Y are said to be "identical" if they refer to the same object or if they both are none. In that event the relation "X==Y" has the value true, otherwise the value is false.
The value of the relation "X=/=Y" is the negation of that of "X==Y".
text-reference-relation = simple-text-expression reference-comparator simple-text-expression
Let T and U be text variables. The relation "T==U" is equivalent to
T.OBJ == U.OBJ and T.START = U.START and T.LENGTH = U.LENGTH
Note: The POS components are ignored. Also observe that the relations "T=/=U" and "T=U" may both have the value true. (T and U reference different text frames which contain the same text value.)
The following relations are all true (cf. 2.5)
T = notext eqv T == notext "" == notext "ABC" =/= "ABC" (different occurrences)
Example
class C; begin text T; T:- "ABC" end;
The relation "new C.T == new C.T" is true here.
The meaning of the logical operators not, and, or, imp, and eqv is given by the following function table:
b1 false false true true b2 false true false true --------------------------------------------------------- not b1 true true false false b1 and b2 false false false true b1 or b2 false true true true b1 imp b2 true true false true b1 eqv b2 true false false true ----------------------------------------------------------
The operation "b1 and then b2" denotes "conditional and". If the value of b1 is false the operation yields the result false, otherwise it yields the result of evaluating b2.
The operation "b1 or else b2" denotes "conditional or". If the value of b1 is true the operator yields the result true, otherwise it yields the result of evaluating b2.
Note: The value of "b1 and then b2" is given by textual substitution of the Boolean expression "(if b1 then b2 else false)". Similarly, the operation "b1 or else b2" is defined by substitution of "(if b1 then true else b2)". These definitions imply that the evaluation of the second operand is suppressed when the evaluation result is already evident from the value of the first operand alone.
The sequence of operations within one expression is generally from left to right, with the following additional rules.
According to the syntax given in 3.2 the following rules of precedence hold:
first: non-Boolean expressions second: < <= = >= > <> == =/= is in third: not fourth: and fifth: or sixth: imp seventh: eqv eighth: and then nineth: or else
The use of parentheses is interpreted in the sense given in 3.5.2.
arithmetic-expression = simple-arithmetic-expression | if-clause simple-arithmetic-expression else arithmetic-expression simple-arithmetic-expression = [ + | - ] term { ( + | - ) term } term = factor { ( * | / | // ) factor } factor = primary { ** primary } primary = unsigned-number | variable | function-designator | "(" arithmetic-expression ")"
An arithmetic expression is a rule for computing a numerical value. In the case of simple arithmetic expressions this value is obtained by executing the indicated arithmetic operations on the actual numerical values of the primaries of the expression, as explained in detail in 3.5.1 below. The value of a primary is obvious in the case of numbers. For variables it is the current value (assigned last in the dynamic sense), and for function designators it is the value arising from the computing rules defining the procedure when applied to the current values of the procedure parameters given in the expression. Finally, for arithmetic expressions enclosed by parentheses the value must through a recursive analysis be expressed in terms of the values of primaries of the other three kinds.
In the more general arithmetic expressions, which include if-clauses, one out of several simple arithmetic expressions is selected on the basis of the actual values of the Boolean expressions (see 3.2). This selection is made as follows: The Boolean expressions of the if-clauses are evaluated one by one in sequence from left to right until one having the value true is found. The value of the arithmetic expression is then the value of the first arithmetic expression following this Boolean (the longest arithmetic expression found in this position is understood). If none of the Boolean expressions has the value true, then the value of the arithmetic expression is the value of the expression following the final else.
In evaluating an arithmetic expression, all primaries within that expression are evaluated with the following exceptions:
Primaries are always evaluated in strict lexical order.
Examples:
Primaries: 7.394_604&-8 sum w(i + 2,8) cos( y + z*3.141_592_653_589_793_324&&0 ) ( a - 3/y + vu**8) Factors: omega sum ** cos( y + z*3 ) 7.394&-8 ** w(i + 2,8) ** ( a - 3/y + vu ** 8 ) Terms: u omega * sum ** cos(y + z*3)/7.394&-8 ** (a - 3/y + vu**8) Simple arithmetic expression: u - yu + omega*sum**cos(y+z*3)/7.394&-8 **(a-3/y+vu**8) Arithmetic expressions: w*u - q(s+cu)**2 if q>0 then s+3*q//a else 2*s+3*q if a<0 then u+v else if a*b>17 then u/v else if k >= y then v/u else 0 0.57&12 * a( n*(n-1)//2 ,0 ) ( a*arctan(y)+z ) ** (7+Q) if q then n-1 else n
Apart from the Boolean expressions of if-clauses, the constituents of arithmetic expressions must be of arithmetic types. The meaning of the basic operators and the types of the expressions to which they lead are given by the following rules, where "i" and "j" are of integer type, "r" of real type, and "x" is any arithmetic type:
integer procedure DIV(i, j); integer i, j; if j=0 then error("..." !div by zero;) else begin integer m, n; m:= 0; n:= abs(i); for n:= n - abs(j) while n>=0 do m:= m + 1; DIV:= if i<0 eqv j>0 then -m else m end DIV;
x**r: <type of r> procedure EXPR(x,r);x; r; if x<0 or (x=0 and r<=0.0) then error("..." !EXPR undefined;); else EXPR := if x>0 then exp(r*ln(x)) else 0.0; i**j: integer procedure EXPI(i,j); integer i,j; if j<0 or i=0 and j=0 then error("..." !EXPI undefined;) else begin integer k,result; result:= 1; for k:= 1 step 1 until j do result:= result*i; EXPI:= result end EXPI r**i: <type of r> procedure EXPN(r, i); r; integer i; if i=0 and r=0.0 then error("..." !EXPN undefined;) else begin result; integer n; result:= 1.0; for n:= abs(i) step -1 until 1 do result := result*r; EXPN:= if i<0 then 1.0/result else result end EXPN;
It is understood that the finite deviations of using the exponentiation operator may be different from those of using the procedures EXPR and EXPN.
If the operands of an arithmetic operator are of different types, or both short integer, an appropriate type conversion function is understood to be automatically invoked, except as explicitly noted above, before the operation is evaluated as follows:
If one operand is of type long real the other is converted to long real, else if one operand is of type real the other is converted to real, else short integer operands are converted to integer.
Note: The result of evaluating an arithmetic expression can never be of type short integer.
Conversion from short integer to integer is always exact. Conversion from an integer type to a real type is exact within an implementation-defined range which includes zero. Conversion from real to long real is exact within an implementation-defined range which includes zero.
The type of the operation (and by repeated application also the type of the arithmetic expression) is a consequence of the type conversion rule as follows:
SI I R LR SI I I R LR SI: short integer I I I R LR I: integer R R R R LR R: real LR LR LR LR LR LR: long real
The rule also determines the type of a conditional expression, i.e. an arithmetic expression of the form
"if B then SAE else AE":
The expression is of type long real if either SAE or AE is long real. Otherwise, if either SAE or AE is of type real, the type of the expression is real, else the type is integer.
Note: The type of a conditional expression is independent of the actual value of the Boolean expression, i.e. it is completely determined by the program text.
The sequence of operations within one expression is generally from left to right, with the following additional rules:
According to the syntax given in 3.3.1 the following rules of precedence hold:
first: ** second: * / // third: + -
The expression between a left parentheses and the matching right parenthesis is evaluated by itself and this value is used in subsequent calculations. Consequently the desired order of execution of operations within an expression can always be arranged by appropriate positioning of parentheses.
Note: The order of evaluation of the primaries is not influenced by the use of parenthesis.
Numbers and variables of real type must be interpreted in the sense of numerical analysis, i.e. as entities defined inherently with only a finite accuracy. Similarly, the possibility of the occurrence of a finite deviation from the mathematically defined result in any arithmetic expression is explicitly understood. No exact arithmetic will be specified, however, and it is indeed understood that, different implementations may evaluate arithmetic expressions differently. The control of the possible consequences of such differences must be carried out by the methods of numerical analysis. This control must be considered a part of the process to be described, and is therefore expressed in terms of the language itself.
character-expression = simple-character-expression | if-clause simple-character-expression else character-expression simple-character-expression = character-constant | variable | function-designator | "(" character-expression ")"
A character expression is of type character. It is a rule for obtaining a character value (see 2.1.3). Apart from possible if-clauses, all constituents of a character expression must be of type character.
text-expression = simple-text-expression | if-clause simple-text-expression else text-expression simple-text-expression = text-primary { & text-primary } text-primary = notext | string | variable | function-designator | "(" text-expression ")"
A text expression is of type text. It is a rule for obtaining an identification of a text variable. Apart from possible if-clauses, all constituents of a text expression must be of type text.
Each textual occurrence of a non-empty string corresponds to a unique constant main text frame. A given occurrence always references that same frame, while different occurrences of the same non-empty string always reference different text frames.
The empty string ("") is textually equivalent to notext.
The operator & permits text concatenation. The simple text expression "TP1 & TP2 & ... & TPn", where TPi is a text primary (1<=i<=n), references a new alterable main frame whose contents is formed by concatenating copies of the frames referenced by TP1, TP2, ... , TPn (in that order). The expression is equivalent to CONCATENATE_n(T1,T2,...,Tn) defined by
text procedure CONCATENATE_ _n(T1,T2,...,Tn); text T1,T2,...,Tn; begin text temp; CONCATENATE_ _n :- temp :- blanks(T1.length+T2.length+ ... +Tn.length); temp.sub(1,t1.length) := T1; temp.sub(1+T1.length,T2.length) := T2; ... temp.sub(1+T1.length+T2.length+... ,Tn.length) := Tn; end;
Note: It follows that the text primary constituents of a simple text
expression are evaluated in strict lexical order. The evaluation
of Ti may influence the result of evaluating Tj, if i<j (due to
the specified "by reference" transmission of parameters to the
procedures CONCATENATE_n).
Observe further that it follows from the syntax (cfr. 3.1.5) that
. is evaluated before &, thus the two expressions
"T1 & T2.sub(1,2) & T3.main" and "T1 & (T2.sub(1,2)) & (T3.main)"
are equivalent.
The result of evaluating
For further information on the text concept, see chapter 8.
object-expression = simple-object-expression | if-clause simple-object-expression else object-expression simple-object-expression = none | variable | function-designator | object-generator | local-object | qualified-object | "(" object-expression ")" object-generator = new class-identifier [ actual-parameter-part ] local-object = this class-identifier qualified-object = simple-object-expression qua class-identifier
An object expression is of type ref(qualification). It is a rule for obtaining a reference to an object. The value of the expression is the referenced object or none. Apart from a possible if-clause all constituents must be of object reference type.
The qualification of an object expression is defined by the following rules:
The value of an object generator is the object generated as the result of its evaluation. See 4.7.
A local object "this C" is valid provided that the expression is used within
The value of a local object in a given context is the object which is, or is connected by, the smallest textually enclosing block instance in which the local object is valid. If there is no such block the local object is illegal (in the given context). For an instance of a procedure or a class body, "textually enclosing" means containing its declaration.
Let X represent any simple reference expression, and let C and D be class identifiers such that D is the qualification of X. The qualified object "X qua C" is then a legal object expression, provided that C is outer to or equal to D or is a subclass of D. Otherwise, since C and D belong to disjoint prefix sequences, the expression is illegal.
If the value of X is none or is an object belonging to a class outer to C, the evaluation of X qua C constitutes a run-time error. Otherwise, the value of X qua C is that of X. Instantaneous qualification restricts or extends the visibility of attributes of a concatenated class object accessible through inspection or remote accessing (cf. 3.1.5 and 4.8).
designational-expression = simple-designational-expression | if-clause simple-designational-expression else designational-expression simple-designational-expression = label | switch-designator | "(" designational-expression ")" switch-designator = switch-identifier "(" subscript-expression ")" switch-identifier = identifier label = identifier
A designational expression is a rule for obtaining a reference to a program point. The principle of the evaluation is entirely analogous to that of arithmetic expressions. In the general case the Boolean expressions of the if-clauses select a simple designational expression. If this is a label the desired result is already found. A switch designator refers to the corresponding switch declaration and by the actual numerical value of its subscript expression selects one of the designational expressions listed in the switch declaration by counting these from left to right. Since the expression thus selected may again be a switch designator this evaluation is obviously a recursive process.
The evaluation of the subscript expression is analogous to that of subscripted variables. The value of a switch designator is defined only if the subscript expression assumes one of the values 1, 2, ... , n, where n is the number of entries in the switch list. A value outside this range causes a run time error.
Note: It is a consequence of the syntax that class attributes which are labels or switches cannot be accessed by the dot notation.