Next Chapter Return to Table of Contents Previous Chapter


This section is meant for people who do most of their programming in FORTRAN. FORTRAN has the distinction of being essentially the earliest higher level programming language, developed about 1957 by a group at IBM. Since then it and its derivatives have become established as the primary language for scientific and engineering computation. But, with our greater understanding of the process of creating programs has come a realization of the deficiencies of FORTRAN. Creating a program is properly thought of as taking a real world problem and translating it into a computer solution. Concepts in the real world such as a geneology tree or a queue of airplanes must be translated into computer concepts. A language is good if it enables one to describe these abstractions of the real world in a natural way. Perhaps because of its very early development, FORTRAN lacks many such features. In this appendix we explore the idea of writing a preprocessor for FORTRAN which inexpensively adds some of these missing features.

A preprocessor is a program which translates statements written in a language X into FORTRAN. In our case X is called SPARKS. Such a program is normally called a compiler so why give it the special name preprocessor? A preprocessor is distinguished from a compiler in the following way: the source and target language have many statements in common.

Such a translator has many advantages. Most importantly it preserves a close connection with FORTRAN. Despite FORTRAN's many negative attributes, it has several practical pluses: 1) it is almost always available and compilers are often good, 2) there is a language standard which allows a degree of portability not obtainable with other languages, 3) there are extensive subroutine libraries, and 4) there is a large labor force familiar with it. These reasons give FORTRAN a strong hold in the industrial marketplace. A structured FORTRAN translator preserves these virtues while it augments the language with improved syntactical constructs and other useful features.

Another consideration is that at many installations a nicely structured language is unavailable. In this event a translator provides a simple means for supplementing an existing FORTRAN capability. The translator to be described here can be obtained by writing to the address given at the end of this appendix.

In order to see the difference between FORTRAN and SPARKS consider writing a program which searches for X in the sorted array of integers A (N), N 100. The output is the integer J which is either zero if X is not found or A(J) = X, 1 J N. The method used here is the well known binary search algorithm. The FORTRAN version looks something like this:




BOT= 1


J = 0


MID = (BOT + TOP)/2

IF (X. GE. A (MID)) GO TO 101

TOP = MID - 1

GO TO 100

101   IF (X. EQ. A (MID)) GO TO 102

BOT = MID + 1

GO TO 100

102   J = MID



This may not be the "best" way to write this program, but it is a reasonable attempt. Now we write this algorithm in SPARKS.




BOT = 1; TOP = N; J = 0


MID = (BOT + TOP)/2


: X. LT. A(MID): TOP = MID - 1

: X. GT. A(MID): BOT = MID + 1






The difference between these two algorithms may not be dramatic, but it is significant. The WHILE and CASE statements allow the algorithm to be described in a more natural way. The program can be read from top to bottom without your eyes constantly jumping up and down the page. When such improvements are consistently adopted in a large software project, the resulting code is bound to be easier to comprehend.

We begin by defining precisely the SPARKS language. A distinction is made between FORTRAN statements and SPARKS statements. The latter are recognized by certain keywords and/or delimiters. All other statements are regarded as FORTRAN and are passed directly to the FORTRAN compiler without alteration. Thus, SPARKS is compatible with FORTRAN and a FORTRAN program is a SPARKS program. SPARKS statements cause the translator to produce ANSI FORTRAN statements which accomplish the equivalent computation. Hence, the local compiler ultimately defines the semantics of all SPARKS statements.

The reserved words and special symbols are:


ENDIF    EOJ     EXIT    FOR   IF     LOOP


;         //

Reserved words must always be surrounded by blanks. Reserved means they cannot be used by the programmer as variables.

We now define the SPARKS statements by giving their FORTRAN equivalents. In the following any reference to the term "statements" is meant to include both SPARKS and FORTRAN statements. There are six basic SPARKS statements, two which improve the testing of cases and four which improve the description of looping.

IF cond THEN           IF(.NOT. (cond)) GO TO 100

      S1                   S1

  ELSE                     GO TO 101

      S2           100   S2

ENDIF              101   CONTINUE

S1 and S2 are arbitrary size groups of statements. Cond must be a legal FORTRAN conditional. The ELSE clause is optional but the ENDIF is required and it always terminates the innermost IF.

S1,S2, ...,Sn+1 are arbitrary size groups of statements. Cond1, cond2, ..., condn are legal FORTRAN conditionals. The symbol ELSE surrounded by colons designates that Sn+l will be automatically executed if all previous conditions are false. This part of the case statement is optional.

The four looping statements are:

WHILE cond DO        100   IF(.NOT. (cond)) GO TO 101

   S                            S

REPEAT                     GO TO 100

                     101   CONTINUE

S is an arbitrary group of statements and cond a legal FORTRAN conditional.

LOOP                 100   CONTINUE

   S                       S

UNTIL cond REPEAT            IF(.NOT. (cond)) GO TO 100

S and cond are the same as for the while statement immediately preceding.

LOOP            100        CONTINUE

   S                       S

REPEAT                     GO TO 100

                101        CONTINUE

S is an arbitrary size group of statements.

FOR vble = expl TO exp2 BY exp3 DO



This has a translation of:

     vble = expl

     GO TO 100

102  vble = vble + exp3

100  IF ((vble - (exp2))*(exp3).GT. 0) GO TO 101


       GO TO 102


The three expressions exp1, exp2, exp3 are allowed to be arbitrary FORTRAN arithmetic expressions of any type. Similarly vble may be of any type. However, the comparison test is made against integer zero. Since exp2 and exp3 are re-evaluated each time through the loop, care must be taken in its use.

EXIT is a SPARKS statement which causes a transfer of control to the first statement outside of the innermost LOOP-REPEAT statement which contains it. One example of its use is:

LOOP              100      CONTINUE

 S1                            S1

 IF cond THEN EXIT         IF(.NOT. (cond)) GO TO 102

 ENDIF                       GO TO 101

 S2               102      CONTINUE

REPEAT                     S2

                           GO TO 100

                  101      CONTINUE

A generalization of this statement allows EXIT to be used within any of the four SPARKS looping statements: WHILE, LOOP, LOOP-UNTIL and FOR. When executed, EXIT branches to the statement immediately following the innermost looping statement which contains it.

The statement CYCLE is also used within any SPARKS looping statement. Its execution causes a branch to the end of the innermost loop which contains it. A test may be made and if passed the next iteration is taken. An example of the use of EXIT and CYCLE follow.

LOOP              100      CONTINUE

   S1                           S1

 CASE                      IF(.NOT. (cond1) GO TO 103

  : cond1 : EXIT           GO TO 102

  : cond2 : CYCLE          IF(.NOT. (cond2)) GO TO 104

ENDCASE           103      GO TO 101

S2                             CONTINUE

REPEAT            104        S2

                           GO TO 100

                  101      CONTINUE


EOJ or end of job must appear at the end of the entire SPARKS program. As a statement, it must appear somewhere in columns 7 through 72 and surrounded by blanks.

ENDIF is used to terminate the IF and ENDCASE to terminate the CASE statement. REPEAT terminates the looping statements WHILE, LOOP and FOR.

Labels follow the FORTRAN convention of being numeric and in columns one to five.

The use of doubleslash is as a delimiter for comments. Thus one can write

//This is a comment//

and all characters within the double slashes will be ignored. Comments are restricted to one line and FORTRAN comments are allowed.

The semi-colon can be used to include more than one statement on a single line For example, beginning in column one the statement

99999 A = B + C; C = D + E; X = A

would be legal in SPARKS. To include a semicolon in a hollerith field it should be followed by a second semicolon. This will be deleted in the resulting FORTRAN.

We are now ready to describe the operation of the translator. Two design approaches are feasible. The first is a table-driven method which scans a program and recognizes keywords. This approach is essentially the way a compiler works in that it requires a scanner, a symbol table (though limited), very limited parsing and the generation of object (FORTRAN) code. A second approach is to write a general macro preprocessor and then to define each SPARKS statement as a new macro. Such a processor is usually small and allows the user to easily define new constructs. However, these processors tend to be slower than the approach of direct translation. Moreover, it is hard to build in the appropriate error detection and recovery facilities which are sorely needed if SPARKS is to be used seriously. Therefore, we have chosen the first approach. Figure A.1 contains a flow description of the translator.

Figure A.1: Overview of SPARKS Translator

The main processing loop consists of determining the next statement and branching within a large CASE. This does whatever translation into FORTRAN is necessary. When EOJ is found the loop is broken and the program is concluded.

The SPARKS translator was first written in SPARKS. The original version was hand translated into FORTRAN to produce our first running system. Since that time it has been used by a variety of people and classes. Thus it is running far better than the original version. Nevertheless, the translator has not been proved correct and so it must be used with caution.


Below is a list of possible extensions for SPARKS. Some are relatively easy to implement, while others require a great deal of effort.

E.1 Special cases of the CASE statement

      CASE SGN  : exp:             CASE: integer variable:

        : .EQ.0 : S1                   : 1 : S1

        : .LT.0 : S2        and       : 2 : S2

        : .GT.0 : S3                   

      ENDCASE                        : n : Sn


The first gets translated into the FORTRAN arithmetic IF statement. The second form is translated into a FORTRAN computed go to.

E.2 A simple form of the FOR statement would look like

      LOOP exp TIMES



where exp is an expression which evaluates to a non-negative integer. The statements meaning can be described by the SPARKS for statement:

   FOR ITEMP = 1 TO exp DO



An internal integer variable ITEMP must be created.

E.3 If F appears in column one then all subsequent cards are assumed to be pure FORTRAN. They are passed directly to the output until an F is encountered in column one.

E.4 Add the capability of profiling a program by determining the number of executions of each loop during a single execution and the value of conditional expressions.

HINT: For each subroutine declare a set of variables which can be inserted after encountering a WHILE, LOOP, REPEAT, FOR, THEN or ELSE statement. At the end of each subroutine a write statement prints the values of these counters.

E.5 Add the multiple replacement statement so that

A = B = C = D + E

is translated into

C = D + E; B = C; A = B

E.6 Add the vector replacement statement so that

(A,B,C) = (X + Y, 10,2*E)

produces A = X + Y: B = 10 ; C = 2*E

E.7 Add an array "fill" statement so that

NAME(*) exp1,exp2,exp3

gets translated into

NAME(1) = exp1; NAME(2) = exp2; NAME(3) = exp3

E.8 Introduce appropriate syntax and reasonable conventions so that SPARKs programs can be recursive.

HINT: Mutually recursive programs are gathered together in a module, MODULE (X(A,B,C)(100)) whose name is X, whose parameters are A,B,C and whose stack size should be 100.

E.9 Add a character string capability to SPARKS.

E.10 Add an internal procedure capability to aid the programmer in doing top-down program refinement.

E.11 Attach sequence numbers to the resulting FORTRAN output which relates each statement back to the original SPARKS statement which generated it. This is particularly helpful for debugging.

E.12 Along with the indented SPARKS source print a number which represents the level of nesting of each statement.

E.13 Generalize the EXIT statement so that upon its execution it can be assigned a value, e.g.,



        IF condl THEN EXIT : exp1: ENDIF


        IF cond2 THEN EXIT : exp2: ENDIF



will assign either expl or exp2 as the value of the variable EXIT.

E.14 Supply a simplified read and write statement. For example, allow for hollerith strings to be included within quotes and translated to the nH x1 ... xn format.

All further questions about the definition of SPARKS should be addressed to:

Chairman, SPARKS Users Group

Computer Science, Powell Hall

University of Southern California

Los Angeles, California 9007

To receive a complete ANSI FORTRAN version of SPARKS send $20.00 (for postage and handling) to Dr. Ellis Horowitz at the above address.

Go to Appendix B     Back to Table of Contents