This section describes the control flow constructions provided by
Bartels User Language. Control flow statements specify the order in which computations are processed. According to the principles of structured programming
Bartels User Language distinguishes between concatenation (sequential program element), alternation and repetition (CAR - Concatenation, Alternation, Repetition).
2.5.1 Concatenations
Statements
A statement consists of an expression (see
chapter 2.4) followed by a semicolon
(; ), as in
tabulator = '\t' ;
distance = sqrt(a*a+b*b) ;
filename += extension = ".ddb" ;
++ary[i] ;
printf("Part %s ;\n",partname) ;
The semicolon is a statement terminator. An empty statement is encountered by
;
where the expression at the left of the semicolon is omitted. Empty statements can be used to define dependent (dummy) statements (e.g., inside loops). A statement is indicated as dependent statement, if it is context-dependent to an alternation or a repetition (see below).
Bartels User Language allows the specification of statements without side-effect as in
27+16.3;
++11;
Statements without side-effect are worthless since they neither change any variable value by assignment nor do they activate any function. I.e.,
User Language Compiler issues a warning message if a statement without side-effects is encountered.
Blocks
A block consists of a sequence of declarations (see
chapter 2.3.2) and statements and is enclosed with braces
({ and
} ). I.e., the braces apply for grouping declarations and statements together into a compound statement or block, which then is syntactically equivalent to a single statement. Compound statements are most commonly used at the definition of functions or for grouping multiple dependent statements of an alternation or repetition.
2.5.2 Alternations
Alternations make decisions according to a special expression value in order to branch to the execution of corresponding dependent (compound) statements.
if- and if-else Statement
The formal syntax of the
if statement is
if (expression)
statement
where the dependent statement of the
if statement is only executed if the expression value is nonzero (i.e., a value different from 0 or the empty string on
string expressions). The formal syntax of the
if-else statement is
if (expression)
statement1
else
statement2
where the
if expression is evaluated, and
statement1 is executed if the expression value is nonzero or else
statement2 is executed if the expression value is zero. Dependent statements of an
if and/or
if-else statement can be
if or
if-else statements again, i.e.,
if and
if-else statements can nest as in
if (expression)
statement
else if (expression) {
if (expression)
statement
}
else if (expression)
statement
:
else
statement
Since the
else part of an
if-else statement is optional, there is an ambiguity when an
else is omitted from a nested
if sequence. This is resolved in a way that the
else is associated with the closest previous
else -less
if . The
if and/or
if-else statement can be utilized as in
string classname="SCM ";
if (bae_planddbclass()==800)
classname+="Sheet";
else if (bae_planddbclass()==801 || bae_planddbclass()==803)
classname+="Symbol/Label";
else if (bae_planddbclass()==802)
classname+="Marker";
else {
classname="***INVALID***";
printf("No valid element loaded!\n");
}
where the class of the currently loaded SCM element is determined and the value of the variable
classname is set accordingly.
switch Statement
The
switch statement is a special multi-way decision maker that tests whether an expression matches one of a number of other expressions, and branches accordingly. The formal syntax of the
switch statement is
switch (expression)
statement
Each dependent statement of the
switch statement can be preceded with an arbitrary number of
case labels of the form
case expression :
or
default :
The statements between the
case labels are strictly dependent to the closest previous
case label. The dependent statements of a
case label are only executed if the value of the
case expression matches the value of the
switch expression. The
default label specifies an arbitrary value, i.e., the statements following to the
default label is always executed.
case labels do not have any effect on the sequence of computing (the execution continues as if there is no
case label). The
break statement (see also
chapter 2.5.4) can be used in a
case segment to leave the
switch control structure. The
switch statement can be utilized as in
string classname="SCM ";
switch (bae_planddbclass()) {
case 800 :
classname+="Sheet";
break;
case 801 :
case 803 :
classname+="Symbol/Label";
break;
case 802 :
classname+="Marker";
break;
default :
classname="***INVALID***";
printf("No valid element loaded!\n");
}
where the class of the currently loaded SCM element is determined and the value of the variable
classname is set accordingly.
2.5.3 Repetitions
Repetitions are control structures forming a loop for the repetitive computing of certain parts of a program. Each repetitive statement provides a method for testing a certain condition in order to end the processing of the loop. If a program runs into a loop, where the loop-end condition is never reached, then the control flow cannot be passed back to the caller of the program (i.e., the program runs "forever"). This is a fatal programming error, which the
User Language Compiler can recognize under certain conditions.
while Statement
The formal syntax of the
while statement is
while (expression)
statement
where the dependent statement is repeated until the value of the
while expression is zero (0 or empty string for
string expressions). The
while statement can be utilized as in
// ASCII file view
main()
{
string fname; // File name
int fh; // File handle
string curstr=""; // Current input string
// Set the file error handle mode
fseterrmode(0);
// Print the program banner
printf("ASCII FILE VIEWER STARTED\n");
// Repeatedly ask for the input file name
while (fname=askstr("File Name (press RETURN to exit) : ",40)) {
// Open the input file
printf("\n");
if ((fh=fopen(fname,0))==(-1)) {
printf("File open failure!\n");
continue;
}
// Get the current input string
while (fgets(curstr,128,fh)==0)
// Print the current input string
puts(curstr);
// Test on read errors; close the file
if (!feof(fh) || fclose(fh))
// Read or close error
break;
}
}
where the contents of user-selectable files are listed to the terminal. The
continue statement (see also
chapter 2.5.4) causes the next iteration of the
while loop to begin immediately. The
break statement (see also
chapter 2.5.4) provides an immediate exit from the
while loop.
do-while Statement
The formal syntax of the
do-while
statement is
do
statement
while (expression);
where the dependent statement is repeated until the value of the
do-while expression is zero (0 or empty string for
string expressions). The dependent statement always is executed at least once (contrary to
while ).
for Statement
The formal syntax of the
for
statement is
for (expression1; expression2; expression3)
statement
which is equivalent to
experession1;
while (expression2) {
statement;
expression3;
}
where
expression1 is evaluated, and then the dependent statement is executed and
expression3 is evaluated until
expression2 is zero. I.e.,
expression1 typically is used for initialization,
expression2 applies the loop-end test and
expression3 performs something like an increment. Any of the three expressions can be omitted, although the semicolons must remain. The
for statement can be utilized as in
void strwords(string s)
{
string strlist[];
int strcount,i,j;
char c;
for ( strcount=0,j=0,i=0 ; c=s[i++] ; ) {
if (c==' ' || c=='\t') {
if (j>0) {
strcount++;
j=0;
}
continue;
}
strlist[strcount][j++]=c;
}
for ( i=strcount ; i>=0 ; i-- )
printf("%s\n",strlist[i]);
}
where the function
strwords separates the given
string parameter into words to be stored to a list and printed in reverse order afterwards.
forall Statement
The
forall statement applies for automatic sequential processing of the currently available elements of an
index data type. The formal syntax of the
forall statement is
forall (identifier1 of identifier2 where expression)
statement
where identifier1 must refer to an
index variable type specifying the type of the
forall index to be processed; the
forall statement automatically initializes and "increments" this variable. The
forall loop is terminated after the last element of the
index list has been processed. The
of statement of the
forall statement restricts access to those elements of a currently valid
index element of the next higher hierarchy level; i.e., the
of index must refer to an
index type which allows for the processing of the
forall
index type. The
where expression determines whether the dependent statement should be processed for the current
forall index (if
where expression nonzero) or not (if
where expression zero). Both the
of statement and the
where statement are optional; thus the shortest possible form of a
forall statement is
forall (identifier1)
statement
The
forall statement can be utilized as in
index L_CPART part;
index L_CPIN pin;
forall (part where part.USED) {
forall (pin of part where pin.NET.NAME=="vcc")
printf("Part %s, Pin %s ;\n",part.NAME,pin.NAME);
where the list of part pins connected to the net
vcc is printed to the terminal. See
appendix B of this manual for a description of the
index variable types.
2.5.4 Program Flow Control
Besides the previously described control flow statements
Bartels User Language provides some additional structures for controlling the program flow.
break Statement
The formal syntax of the
break statement is
break;
The
break statement must be dependent to a repetitive statement
(while ,
do-while ,
for or
forall ) or to a
switch statement (otherwise the Compiler issues an error message). The
break statement provides an early exit from a repetition, just as from
switch ; i.e.,
break statements cause the innermost enclosing loop (or
switch ) to be exited immediately.
continue Statement
The formal syntax of the
continue statement is
continue;
The
continue statement must be dependent to a repetitive statement
(while ,
do-while ,
for or
forall ), or otherwise the Compiler issues an error message. The
continue statement causes the innermost enclosing loop to restart immediately at the beginning of the loop. I.e., in
while and
do-while loops,
continue causes the end-condition to be tested immediately; in
for loops,
continue passes control to the execution of the "increment" statement.
Function Call and return Statement
Both the function call facilities and the
return statement have been introduced already. These features are so important for controlling the program flow that they are worth a brief separate discussion at this place.
A function call is an expression which performs a jump to the first statement of the corresponding function definition. The
return statement can only be used in functions; it terminates the execution of the currently active function and jumps back to the instruction immediately following to the previous function call (i.e., it passes the control flow back to the caller of the function). The general formal syntax of the
return statement is
return;
or
return expression;
If the
return statement does not contain any expression, then the return value of the corresponding function is undefined. Otherwise the function return value is set to the
return expression, which must be compatible to the function data type (otherwise, the Compiler issues an error message). If the end of a function block is encountered, and the last statement has not been a
return statement, then the Compiler automatically produces code corresponding to a valid
return statement with a function-compatible default (zero) return value. The generation of a default return value is only possible for basic function data types I.e., a function definition as in
struct structname functionname() { }
causes a Compiler error message since the
Bartels User Language Interpreter would encounter a memory protection fault when trying to access any of the elements of this return value.
Control Structures © 1985-2024 Oliver Bartels F+E • Updated: 02 October 2007, 11:22 [UTC]
|