elemental function is_real(self, allow_spaces)
!< Return true if the string contains a real.
!<
!< The regular expression is `\s*[\+\-]?\d*(|\.?\d*([deDE][\+\-]?\d+)?)\s*`. The parse algorithm is done in stages:
!<
!< | S0 | S1 | S2 | S3 | S4 | S5 | S6 | S7 | S8 |
!< |-----|---------|-----|-----|-----|--------|---------|-----|-----|
!< |`\s*`|`[\+\-]?`|`\d*`|`\.?`|`\d*`|`[deDE]`|`[\+\-]?`|`\d*`|`\s*`|
!<
!< Exit on stages-parsing results in:
!<
!< | S0 | S1 | S2 | S3 | S4 | S5 | S6 | S7 | S8 |
!< |----|----|----|----|----|----|----|----|----|
! | F | F | T | T | T | F | F | T | T |
!<
!< @note This implementation is courtesy of
!< [tomedunn](https://github.com/tomedunn/fortran-string-utility-module/blob/master/src/string_utility_module.f90#L614)
!<
!<```fortran
!< type(string) :: astring
!< logical :: test_passed(6)
!< astring = ' -1212112.d0 '
!< test_passed(1) = astring%is_real().eqv..true.
!< astring = ' -1212112.d0'
!< test_passed(2) = astring%is_real(allow_spaces=.false.).eqv..false.
!< astring = '-1212112.d0 '
!< test_passed(3) = astring%is_real(allow_spaces=.false.).eqv..false.
!< astring = '+2.e20'
!< test_passed(4) = astring%is_real().eqv..true.
!< astring = ' -2.01E13 '
!< test_passed(5) = astring%is_real().eqv..true.
!< astring = ' -2.01 E13 '
!< test_passed(6) = astring%is_real().eqv..false.
!< print '(L1)', all(test_passed)
!<```
!=> T <<<
class(string), intent(in) :: self !< The string.
logical, intent(in), optional :: allow_spaces !< Allow leading-trailing spaces.
logical :: is_real !< Result of the test.
logical :: allow_spaces_ !< Allow leading-trailing spaces, local variable.
logical :: has_leading_digit !< Check the presence of leading digits.
integer :: stage !< Stages counter.
integer :: c !< Character counter.
if (allocated(self%raw)) then
allow_spaces_ = .true. ; if (present(allow_spaces)) allow_spaces_ = allow_spaces
stage = 0
is_real = .true.
has_leading_digit = .false.
do c=1, len(self%raw)
select case(self%raw(c:c))
case(SPACE, TAB)
select case(stage)
case(0, 8)
is_real = allow_spaces_
continue
case(2:4, 7)
is_real = allow_spaces_
stage = 8
case default
is_real = .false.
endselect
case('+', '-')
select case(stage)
case(0)
stage = 1
case(5)
stage = 6
case default
is_real = .false.
endselect
case('0':'9')
select case(stage)
case(0:1)
stage = 2
has_leading_digit = .true.
case(3)
stage = 4
case(5:6)
stage = 7
case default
continue
endselect
case('.')
select case(stage)
case(0:2)
stage = 3
case default
is_real = .false.
endselect
case('e','E','d','D')
select case(stage)
case(2:4)
stage = 5
case default
is_real = .false.
endselect
case default
is_real = .false.
endselect
if (.not.is_real) exit
enddo
endif
if (is_real) then
select case(stage)
case(2, 4, 7, 8)
is_real = .true.
case(3)
is_real = has_leading_digit
case default
is_real = .false.
endselect
endif
endfunction is_real