.\" @(#)m3 6.1 (Berkeley) 4/29/86
was originally written in
The language is specified by a context free grammar
and the compiler constructed using
grammar is simple and straightforward, being essentially
stat : \f3if\fP (...) stat
| \f3if\fP (...) stat \f3else\fP stat
| \f3for\fP (...; ...; ...) stat
| \f3repeat\fP stat \f3until\fP (...)
| \f3switch\fP (...) { \f3case\fP ...: prog ...
| anything unrecognizable
follows directly from the rule that says a statement is
``anything unrecognizable''.
In fact most of Fortran falls into this category,
since any statement that does not begin with one of the keywords
is by definition ``unrecognizable.''
Code generation is also simple.
If the first thing on a source line is
the entire statement is simply copied to the output
with appropriate character translation and formatting.
(Leading digits are treated as a label.)
Keywords cause only slightly more complicated actions.
is recognized, two consecutive labels L and L+1
are generated and the value of L is stacked.
The condition is then isolated, and the code
if (.not. (condition)) goto L
(which may be some distance away and include nested \f3if\fP's, of course),
is generated, unless there is an
Code generation for the various loops is equally simple.
One might argue that more care should be taken
should be left alone, not converted into
if (.not. (i .gt. 0)) goto 100
But what are optimizing compilers for, if not to improve code?
It is a rare program indeed where this kind of ``inefficiency''
will make even a measurable difference.
In the few cases where it is important,
the offending lines can be protected by `%'.
The use of a compiler-compiler is definitely the preferred method
The language is well-defined,
with few syntactic irregularities.
Implementation is quite simple;
the original construction took under a week.
is sufficiently simple, however, that an
recognizer can be readily constructed to do the same job
if no compiler-compiler is available.
C compilers are not as widely available as Fortran, however,
and originally bootstrapped with the C version.
was written so as to translate into the portable subset
of Fortran described in [1],
having been run essentially without change
on at least twelve distinct machines.
(The main restrictions of the portable subset are:
only one character per machine word;
avoiding expressions in places like
consistency in subroutine argument usage,
itself will not gratuitously generate non-standard Fortran.)
version is about 1500 lines of
(compared to about 1000 lines of C);
this compiles into 2500 lines of Fortran.
This expansion ratio is somewhat higher than average,
since the compiled code contains unnecessary occurrences
The execution time of the
two routines that read and write cards.
Clearly these routines could be replaced
by machine coded local versions;
unless this is done, the efficiency of other parts of the translation process