Statements denote actions. There are elementary and structured statements. Elementary statements are not composed of any parts that are themselves statements. They are the assignment, the procedure call, the return, and the exit statement. Structured statements are composed of parts that are themselves statements. They are used to express sequencing and conditional, selective, and repetitive execution. A statement may also be empty, in which case it denotes no action. The empty statement is included in order to relax punctuation rules in statement sequences.
Statement =
[ Assignment | ProcedureCall | IfStatement |
CaseStatement | WhileStatement | RepeatStatement |
ForStatement | LoopStatement | WithStatement |
EXIT | RETURN [Expression]
].
Assignments replace the current value of a variable by a new value specified by an expression. The expression must be assignment compatible with the variable (see Definition of terms). The assignment operator is written as ":=" and pronounced as becomes.
Assignment = Designator ":=" Expression.
If an expression e of type Te is assigned to a variable v of type Tv, the following happens:
Examples of assignments (refer to examples in Variable declarations):
i := 0 | |
p := i = j | |
x := i + 1 | |
k := log2(i+j) | |
F := log2 | (* see Formal parameters *) |
s := {2, 3, 5, 7, 11, 13} | |
a[i] := (x+y) * (x-y) | |
t.key := i | |
w[i+1].name := "John" | |
t := c |
A procedure call activates a procedure. It may contain a list of actual parameters which replace the corresponding formal parameters defined in the procedure declaration (see section Procedure types). The correspondence is established by the positions of the parameters in the actual and formal parameter lists. There are two kinds of parameters: variable and value parameters.
If a formal parameter is a variable parameter, the corresponding actual parameter must be a designator denoting a variable. If it denotes an element of a structured variable, the component selectors are evaluated when the formal/actual parameter substitution takes place, i.e. before the execution of the procedure. If a formal parameter is a value parameter, the corresponding actual parameter must be an expression. This expression is evaluated before the procedure activation, and the resulting value is assigned to the formal parameter (see also Formal parameters).
ProcedureCall = Designator [ActualParameters].
Examples:
WriteInt(i*2+1) | (* see Formal parameters *) |
INC(w[k].count) | |
t.Insert("John") | (* see Modules *) |
Statement sequences denote the sequence of actions specified by the component statements which are separated by semicolons.
StatementSequence = Statement {";" Statement}.
IfStatement = IF Expression THEN StatementSequence { ELSIF Expression THEN StatementSequence } [ ELSE StatementSequence ] END.
If statements specify the conditional execution of guarded statement sequences. The Boolean expression preceding a statement sequence is called its guard. The guards are evaluated in sequence of occurrence, until one evaluates to TRUE, whereafter its associated statement sequence is executed. If no guard is satisfied, the statement sequence following the symbol ELSE is executed, if there is one.
Example:
IF (ch >= "A") & (ch <= "Z") THEN ReadIdentifier ELSIF (ch >= "0") & (ch <= "9") THEN ReadNumber ELSIF (ch = " ' ") OR (ch = '"') THEN ReadString ELSE SpecialCharacter END;
Case statements specify the selection and execution of a statement sequence according to the value of an expression. First the case expression is evaluated, then that statement sequence is executed whose case label list contains the obtained value. The case expression must either be of an integer type that includes the types of all case labels, or both the case expression and the case labels must be of type CHAR. Case labels are constants, and no value must occur more than once. If the value of the expression does not occur as a label of any case, the statement sequence following the symbol ELSE is selected, if there is one, otherwise the program is aborted.
CaseStatement = CASE Expression OF Case {"|" Case}
[ ELSE StatementSequence ]
END.
Case = [CaseLabelList ":" StatementSequence].
CaseLabelList = CaseLabels {"," CaseLabels}.
CaseLabels = ConstExpression [ ".." ConstExpression].
Example:
CASE ch OF "A" .. "Z": ReadIdentifier | "0" .. "9": ReadNumber | "'", '"' : ReadString ELSE SpecialCharacter END
While statements specify the repeated execution of a statement sequence while the Boolean expression (its guard) yields TRUE. The guard is checked before every execution of the statement sequence.
WhileStatement = WHILE Expression DO StatementSequence END.
Examples:
WHILE i > 0 DO i := i DIV 2; k := k + 1 END WHILE (t # NIL) & (t.key # i) DO t := t.left END
A repeat statement specifies the repeated execution of a statement sequence until a condition specified by a Boolean expression is satisfied. The statement sequence is executed at least once.
RepeatStatement = REPEAT StatementSequence UNTIL Expression.
A for statement specifies the repeated execution of a statement sequence for a fixed number of times while a progression of values is assigned to an integer variable called the control variable of the for statement.
ForStatement = FOR ident":="Expression TO Expression
[ BY ConstExpression ] DO StatementSequence
END.
The statement
FOR v := beg TO end BY step DO statements END
is equivalent to
temp := end; v := beg; IF step > 0 THEN WHILE v <= temp DO statements; v := v + step END ELSE WHILE v >= temp DO statements; v := v + step END END;
temp has the same type as v. step must be a non-zero constant expression. If step is not specified, it is assumed to be 1.
Examples:
FOR i := 0 TO 79 DO k := k + a[i] END FOR i := 79 TO 1 BY -1 DO a[i] := a[i-1] END
A loop statement specifies the repeated execution of a statement sequence. It is terminated upon execution of an exit statement within that sequence (see Return and exit statements).
LoopStatement = LOOP StatementSequence END.
Example:
LOOP ReadInt(i); IF i < 0 THEN EXIT END; WriteInt(i) END
Loop statements are useful to express repetitions with several exit points or cases where the exit condition is in the middle of the repeated statement sequence.
A return statement indicates the termination of a procedure. It is denoted by the symbol RETURN, followed by an expression if the procedure is a function procedure. The type of the expression must be assignment compatible (see Definition of terms) with the result type specified in the procedure heading (see section Procedure declarations).
Function procedures require the presence of a return statement indicating the result value. In proper procedures, a return statement is implied by the end of the procedure body. Any explicit return statement therefore appears as an additional (probably exceptional) termination point.
An exit statement is denoted by the symbol EXIT. It specifies termination of the enclosing loop statement and continuation with the statement following that loop statement. Exit statements are contextually, although not syntactically associated with the loop statement which contains them.
With statements execute a statement sequence depending on the result of a type test and apply a type guard to every occurrence of the tested variable within this statement sequence.
WithStatement = WITH Guard DO StatementSequence
{ "|" Guard DO StatementSequence }
[ ELSE StatementSequence ]
END.
Guard = Qualident ":" Qualident.
If v is a variable parameter of record type or a pointer variable, and if it is of a static type T0, the statement
WITH v: T1 DO S1 |v: T2 DO S2 ELSE S3 END
has the following meaning: if the dynamic type of v is T1, then the statement sequence S1 is executed where v is regarded as if it had the static type T1; else if the dynamic type of v is T2, then S2 is executed where v is regarded as if it had the static type T2; else S3 is executed. T1 and T2 must be extensions of T0. If no type test is satisfied and if an else clause is missing the program is aborted.
Example:
WITH t: CenterTree DO i := t.width; c := t.subnode END