parse_number Subroutine

private subroutine parse_number(unit, value)

Arguments

Type IntentOptional AttributesName
integer, intent(inout) :: unit
type(fson_value), pointer:: value

Contents

Source Code


Source Code

  subroutine parse_number(unit, value)
    use fson_value_m, only: TYPE_INTEGER, TYPE_REAL
    implicit none

    integer, intent(inout) :: unit
    type(fson_value), pointer :: value
    logical :: eof, negative, decimal, scientific
    character :: c
    integer :: integral, exp, digit_count
    real(kind(1.0D0)) :: frac

    ! first character is either - or a digit
    c = pop_char(unit, eof=eof, skip_ws=.true.)
    if (eof) then
       print *, "ERROR: Unexpected end of file while parsing number."
       call exit (1)
    else if ("-" == c) then
       negative = .true.
    else
       negative = .false.
       call push_char(c)
    end if

    ! parse the integral
    integral = parse_integer(unit)

    decimal = .false.
    scientific = .false.

    do
       ! first character is either - or a digit
       c = pop_char(unit, eof=eof, skip_ws=.true.)
       if (eof) then
          print *, "ERROR: Unexpected end of file while parsing number."
          call exit (1)
       else
          select case (c)
          case (".")
             ! this is already fractional number
             if (decimal) then
                ! already found a decimal place
                print *, "ERROR: Unexpected second decimal place while parsing number."
                call exit(1)
             end if
             decimal = .true.
             frac = parse_integer(unit, digit_count)
             frac = frac / (10.0D0 ** digit_count)
          case ("e", "E")
             ! this is already an exponent number
             if (scientific) then
                ! already found a e place
                print *, "ERROR: Unexpected second exponent while parsing number."
                call exit(1)
             end if
             scientific = .true.
             ! this number has an exponent
             exp = parse_integer(unit)

          case default
             ! this is a integer
             if (decimal) then

                ! add the integral
                frac = frac + integral

                if (scientific) then
                   ! apply exponent
                   frac = frac * (10.0D0 ** exp)
                end if

                ! apply negative
                if (negative) then
                   frac = frac * (-1)
                end if

                value % value_type = TYPE_REAL
                value % value_real = frac
                value % value_double = frac
             else
                if (scientific) then
                   ! apply exponent
                   integral = integral * (10.0D0 ** exp)
                end if

                ! apply negative
                if (negative) then
                   integral = integral * (-1)
                end if

                value % value_type = TYPE_INTEGER
                value % value_integer = integral
                !+PJK
                !  Following two lines are included in case the decimal point of
                !  a floating point number has been (accidentally) left out
                value % value_real = integral
                value % value_double = integral
                !-PJK
             end if
             call push_char(c)
             exit
          end select
       end if
    end do

  end subroutine parse_number