Here is an attempt, by identifying the tokens without “read(line,*) token”. It uses two simple DO loop scans of the line string.
It first replaces all other delimiters with a blank then searches for the start and end of all tokens. The list of possible delimiters can always change !
It then identifies the start and end of all tokens, testing if the Fortran READ accepts the token as a real number.
This approach does not include some useful free format extensions, such as:
- the use of , , to identify null tokens
- the use of arithmentc operators + - / * ^ for sumple numeric calculations.
- coping with ascii HT char(9)
character :: line*128
character :: blank = ' '
character :: delimiters*5 = ' ,()='
character :: list_of_tokens(64)*32
real :: list_of_reals(64), val
integer :: nt, nr, fc, k, iostat
line = ' ( v= 1) w = 2.843 unit1 = 5.867 unit2 4.567 1.232 )'
write ( *,10) 'Initial line :', trim(line)
! replace other delimiters with blank
do k = 1, len_trim(line)
if ( index (delimiters, line(k:k)) > 0 ) line(k:k) = blank
end do
write ( *,10) 'Without delim:', trim(line)
! find all tokens in filtered line
nt = 0 ! number of tokens
nr = 0 ! number of reals
fc = 0 ! first character of next token
write ( *,10) 'Search for Tokens'
do k = 1, len_trim(line)+1 ! line must end with a blank
if ( fc == 0 ) then
if ( line(k:k) /= blank ) fc = k ! have start of toktn
else if ( line(k:k) == blank ) then ! have end of token
nt = nt+1
list_of_tokens(nt) = line(fc:k) ! add token to list
read (list_of_tokens(nt), fmt='(f20.0)', iostat=iostat ) val
if ( iostat == 0 ) then
nr = nr+1
list_of_reals(nr) = val ! add reaL to list
write ( *,11) nt, trim(list_of_tokens(nt)), ' val =',val
else
write ( *,11) nt, trim(list_of_tokens(nt))
end if
fc = 0 ! set for start of next token
end if
end do
write ( *,10) 'Summary'
write ( *,11) nt,'tokens identified'
write ( *,11) nr,'real values identified'
10 format (/a,a)
11 format ( i4,2x,a,a,g10.4 )
end