is_real Function

private elemental function is_real(self, allow_spaces)

Arguments

TypeIntentOptionalAttributesName
class(string), intent(in) :: self
logical, intent(in), optional :: allow_spaces

Return Value logical


Contents

Source Code


Source Code

   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