Fortran Syntax
Two source forms: free and fixed
Fortran has two source layouts because it has two centuries of history in one file system. Modern Fortran (1990 onward) uses free form: statements start anywhere, whitespace is free, comments use !. Legacy Fortran 77 used fixed form, where columns 1–5 held statement labels, column 6 a continuation marker, and columns 7–72 the statement itself — a layout inherited from 80-column punch cards.
The file extension tells the compiler which layout to expect: .f90 .f95 .f03 .f08 .f18 .f23 mean free form; lowercase .f and .for mean fixed form. Because a wrong guess produces baffling errors (e.g. "Unclassifiable statement"), always use a free-form extension. This track uses .f90 everywhere.
Free form rules that matter
- Case is insignificant:
Program,programandPROGRAMare the same keyword. Convention is lowercase. - A statement may be as long as you like; break a long one with a trailing
&and continue on the next line:
total = alpha * beta * gamma + delta * epsilon &
+ zeta * eta * theta
! (^ the & ends the line; indentation is decorative)
- Multiple statements share one line only if separated by
;— rare and discouraged. - A comment runs from the first
!to end of line; code may precede it, so comments explain statements inline. - Names (identifiers) are 1–63 characters, start with a letter, then letters, digits, and underscores.
convergence_criterion_2is a fine name;2_convergenceis not.
The program skeleton
Every Fortran file contains one or more program units. The next complete program shows a main program that calls a subroutine living in the same file — the two-unit shape you will use for the rest of this phase. Read the annotations: they mark the three mandatory elements of a modern unit.
program skeleton
! Main program unit: the entry point the runtime starts at.
implicit none ! 1) ban implicit typing
integer :: i ! 2) declare every variable
do i = 1, 3
call announce(i) ! 3) call a named subprogram
end do
contains ! internal procedures live here
subroutine announce(n)
integer, intent(in) :: n ! input-only argument (see Functions)
print '(a,i0)', 'iteration ', n
end subroutine announce
end program skeleton
Compile as usual — gfortran -Wall skeleton.f90 — and run. Subroutines inside contains see the host program's variables directly (host association), a power and a hazard you will manage with modules starting with the modules lesson.
Fig. 1 — One program, three kinds of program unit; the module is the shared library of the future modules lesson.
Statements and the implicit typing trap
Each line of executable code is a statement. Fortran's most famous footgun is implicit typing: without implicit none, names starting with i, j, k, l, m, n are automatically integer and everything else real — carryover from FORTRAN I's design goal of forgiving math input. A misspelled variable silently becomes a new zero-initialized variable, corrupting results with no error. This is why every example in this track (and every serious modern codebase) starts with implicit none.
Declarations use the type [, attributes] :: name_list pattern. The double colon :: is conventional; it separates attributes from names and makes the declaration unmistakable:
program declarations
implicit none
integer :: n ! a scalar integer
real :: x = 1.5 ! initialization is allowed
integer, parameter :: steps = 10 ! compile-time constant, never changes
real :: y(steps) ! fixed-size array of ten reals (Arrays)
character(len=20) :: label ! a twenty-character string
print *, n, x, y(steps), label
end program declarations
END: the statement that closes every unit
Every program unit — program, module, subroutine, function, type — closes with an end statement that names its kind, optionally repeating the unit's name: end program declarations. Repeating the name lets the compiler verify you closed the right unit — in a long file the difference between end and end subroutine has caught more than one engineer. Applied consistently, this single rule makes Fortran files self-documenting at their seams.
Standard conformance and file endings
The ISO standard is the contract between your code and every compiler. gfortran's -std=f2018 (or -std=f2023) enforces it and reports a whole family of retired features as errors: the arithmetic IF, computed GO TO, PAUSE, statement functions, and the old CHARACTER*10 spelling. Mainstream open-source code has virtually stopped using these — but if you ever inherit a 1985 subroutine, -std=legacy gets it compiling today while you plan the rewrite.
Finally, a hygiene rule worth internalizing now: one program unit per file, named exactly as the unit is named — solver.f90 contains program solver or module solver. Editors, language servers, and fpm all assume it, and you will thank yourself at linking time.