============================================
Include Statements
============================================

PROGRAM TEST
  INCLUDE 'fftw.f03'
  a = 1.0
  INCLUDE 'debug_point.f03'
END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (include_statement (filename))
    (assignment_statement (identifier) (number_literal))
    (include_statement (filename))
  (end_program_statement)))

============================================
Use Statements
============================================

PROGRAM TEST
  USE ISO_C_BINDING
  USE ISO_FORTRAN_ENV, ONLY : ERROR_UNIT, OUTPUT_UNIT
  USE MY_MODULE, ONLY:FUNC1
END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (use_statement (module_name))
    (use_statement (module_name)
      (included_items (identifier) (identifier)))
    (use_statement (module_name)
      (included_items (identifier)))
  (end_program_statement)))

============================================
Implicit Statements
============================================

PROGRAM TEST
  IMPLICIT INTEGER(i - n), REAL(8)(r-z),  COMPLEX*8(a - c, d, e-h)
  IMPLICIT NONE
END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (implicit_statement
      (intrinsic_type) (implicit_range)
      (intrinsic_type) (size (argument_list (number_literal))) (implicit_range)
      (intrinsic_type) (size) (implicit_range) (implicit_range) (implicit_range))
    (implicit_statement (none))
  (end_program_statement)))

============================================
Save Statements
============================================

MODULE TEST
  SAVE
  SAVE :: a, b, c, d_1
END MODULE

----

(translation_unit
  (module (module_statement (name))
    (save_statement)
    (save_statement (identifier) (identifier) (identifier) (identifier))
    (end_module_statement)))

============================================
Private Statements
============================================

MODULE TEST
  PRIVATE
  PRIVATE :: a, b_1, operator(.and.), operator(+)
END MODULE

----

(translation_unit
  (module (module_statement (name))
    (private_statement)
    (private_statement (identifier) (identifier) (operator) (operator))
    (end_module_statement)))

============================================
Public Statements
============================================

MODULE TEST
  PUBLIC
  PUBLIC :: a, b_1, operator(.and.), operator(+)
END MODULE

----

(translation_unit
  (module (module_statement (name))
    (public_statement)
    (public_statement (identifier) (identifier) (operator) (operator))
    (end_module_statement)))

============================================
Intrinsic Variable Declarations
============================================

PROGRAM TEST
  INTEGER, PARAMETER :: N = 100, MXLN = 255
  INTEGER :: i, j, k, l(*)
  REAL(16) :: data(0:N**2), rhs(N)
  REAL*8, TARGET :: tmp
  REAL(KIND=8), POINTER :: nxt => tmp
  LOGICAL, DIMENSION(:), ALLOCATABLE :: mask
  CHARACTER(LEN=:) :: message
  CHARACTER(LEN=*) :: options
  CHARACTER*(MXLN) :: errflag
END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (variable_declaration (intrinsic_type) (type_qualifier)
      (assignment_statement (identifier) (number_literal))
      (assignment_statement (identifier) (number_literal)))
    (variable_declaration (intrinsic_type)
      (identifier)
      (identifier)
      (identifier)
      (call_expression (identifier) (argument_list (assumed_size))))
    (variable_declaration (intrinsic_type) (size (argument_list (number_literal)))
      (call_expression (identifier)
        (argument_list
          (extent_specifier (number_literal) (math_expression (identifier) (number_literal)))))
      (call_expression (identifier) (argument_list (identifier))))
    (variable_declaration (intrinsic_type) (size) (type_qualifier) (identifier))
    (variable_declaration
      (intrinsic_type) (size (argument_list (keyword_argument (identifier) (number_literal))))
      (type_qualifier)
      (pointer_association_statement (identifier) (identifier)))
    (variable_declaration
      (intrinsic_type)
      (type_qualifier (argument_list (extent_specifier)))
      (type_qualifier) (identifier))
    (variable_declaration
      (intrinsic_type)
        (size (argument_list (keyword_argument (identifier) (assumed_shape))))
      (identifier))
    (variable_declaration
      (intrinsic_type)
      (size (argument_list (keyword_argument (identifier) (assumed_size))))
      (identifier))
    (variable_declaration
      (intrinsic_type) (size (parenthesized_expression (identifier)))
      (identifier))
  (end_program_statement)))

============================================
Derived Type Variable Declarations
============================================

PROGRAM TEST
  TYPE(CUSTOM_TYPE) :: CT
END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (variable_declaration (derived_type (type_name)) (identifier))
  (end_program_statement)))

============================================
Variable Modification Statements
============================================

PROGRAM TEST
  ALLOCATABLE :: i
  DIMENSION i(:, :), r(10)
  TARGET :: i
  PARAMETER (MAXLEN = 255, PI = 3.1415, SCALE_FACTOR = SIN(2 * PI))
  EQUIVALENCE (a, b, c), (d, e, f, r(1))
END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (variable_modification (type_qualifier) (identifier))
    (variable_modification (type_qualifier)
      (call_expression (identifier) (argument_list (extent_specifier) (extent_specifier)))
      (call_expression (identifier) (argument_list (number_literal))))
    (variable_modification (type_qualifier) (identifier))
    (parameter_statement
      (parameter_assignment (identifier) (number_literal))
      (parameter_assignment (identifier) (number_literal))
      (parameter_assignment (identifier)
        (call_expression (identifier)
          (argument_list (math_expression (number_literal) (identifier))))))
    (equivalence_statement
      (equivalence_set (identifier) (identifier) (identifier))
      (equivalence_set
        (identifier)
        (identifier)
        (identifier)
        (call_expression (identifier) (argument_list (number_literal)))))
  (end_program_statement)))

============================================
Do Loops
============================================

PROGRAM TEST
    DO i = 1, 10
      x = 6**x
      OPEN(i, FILE="qwerty")
      CALL MYSUB(i, TEST=.TRUE.)
    END DO

    DO i = 1, UBOUND(arr), step
      CONTINUE
      GOTO 44
    ENDDO

    out44: DO i = 1,INT(SIN(9.0*i))
      DO j = 1, 100, -1
        CYCLE out44
      END DO
    END DO out44

    DO WHILE (is_true)
        j = 0
    END DO
END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (do_loop_statement
      (loop_control_expression (identifier) (number_literal) (number_literal))
      (assignment_statement
        (identifier)
        (math_expression (number_literal) (identifier)))
      (call_expression (identifier)
        (argument_list
          (identifier)
          (keyword_argument (identifier) (string_literal))))
      (subroutine_call
        (name)
        (argument_list (identifier) (keyword_argument (identifier) (boolean_literal))))
    (end_do_loop_statement))
    (do_loop_statement
      (loop_control_expression
        (identifier)
        (number_literal)
        (call_expression (identifier) (argument_list (identifier)))
        (identifier))
      (keyword_statement)
      (keyword_statement (statement_label))
    (end_do_loop_statement))
    (do_loop_statement
      (block_label_start_expression)
      (loop_control_expression
        (identifier)
        (number_literal)
        (call_expression
          (identifier)
          (argument_list
            (call_expression (identifier)
              (argument_list
                (math_expression (number_literal) (identifier)))))))
      (do_loop_statement
        (loop_control_expression
          (identifier)
          (number_literal)
          (number_literal)
          (unary_expression (number_literal)))
        (keyword_statement (identifier))
      (end_do_loop_statement))
    (end_do_loop_statement (block_label)))
    (do_loop_statement
      (while_statement
        (parenthesized_expression
          (identifier )))
      (assignment_statement
        (identifier) (number_literal))
      (end_do_loop_statement))
  (end_program_statement)))

============================================
If Statements
============================================

PROGRAM TEST
  IF (x<7) y = 9
  if(ix.ge.1.and.2.le.nx)x=1.4

  IF (arg(1:1) == ADJUSTL(' r')) THEN
    r = 0
  ELSE IF (arg(1:1) .NE. CHAR(l(1))) THEN
    l = 67
  ELSE IF (arg(1:1) .NE. CHAR(m(1))) THEN
  ELSE
    n = 0
  ENDIF

  cond1: IF (y < 0) THEN
     y = 9
  ELSE  IF (x > 0) THEN cond1
   r = 9
   IF (arg(1:1)) THEN
     r = 0
   ELSE
     n = 0
   END IF
  ELSE cond1
    y = 10
  END IF cond1
END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (if_statement
      (parenthesized_expression (relational_expression (identifier) (number_literal)))
      (assignment_statement (identifier) (number_literal)))
    (if_statement
      (parenthesized_expression
        (logical_expression
          (relational_expression (identifier) (number_literal))
          (relational_expression (number_literal) (identifier))))
    (assignment_statement (identifier) (number_literal)))
    (if_statement
      (parenthesized_expression
        (relational_expression
          (call_expression (identifier)
            (argument_list (extent_specifier (number_literal) (number_literal))))
          (call_expression (identifier)
            (argument_list (string_literal)))))
      (assignment_statement (identifier) (number_literal))
      (elseif_clause
        (parenthesized_expression
          (relational_expression
            (call_expression (identifier)
              (argument_list (extent_specifier (number_literal) (number_literal))))
            (call_expression (identifier)
              (argument_list
                (call_expression (identifier)
                  (argument_list (number_literal)))))))
        (assignment_statement (identifier) (number_literal)))
      (elseif_clause
        (parenthesized_expression
          (relational_expression
            (call_expression (identifier)
              (argument_list (extent_specifier (number_literal) (number_literal))))
            (call_expression (identifier)
              (argument_list
                (call_expression (identifier) (argument_list (number_literal))))))))
      (else_clause
        (assignment_statement (identifier) (number_literal)))
    (end_if_statement))
    (if_statement
      (block_label_start_expression)
      (parenthesized_expression
        (relational_expression (identifier) (number_literal)))
      (assignment_statement (identifier) (number_literal))
      (elseif_clause
        (parenthesized_expression
          (relational_expression (identifier) (number_literal)))
        (block_label)
        (assignment_statement (identifier) (number_literal))
        (if_statement
          (parenthesized_expression
            (call_expression (identifier)
              (argument_list (extent_specifier (number_literal) (number_literal)))))
          (assignment_statement (identifier) (number_literal))
          (else_clause
            (assignment_statement (identifier) (number_literal)))
        (end_if_statement)))
      (else_clause (block_label)
        (assignment_statement (identifier) (number_literal)))
      (end_if_statement (block_label)))
  (end_program_statement)))

============================================
Where Statements
============================================

program test

WHERE(A .NE. 0) C = B / A

WHERE(PRESSURE .GE. 1.0)
  PRESSURE = PRESSURE + 1.0
  TEMP = TEMP - 10.0
ELSEWHERE (PRESSURE .LE. 2.0)
  PRESSURE = PRESSURE - 1.0
ELSEWHERE
  PRECIPITATION = .TRUE.
ENDWHERE

cond1: WHERE(PRESSURE .GE. 1.0)
  PRESSURE = PRESSURE + 1.0
ELSEWHERE (PRESSURE .LE. 2.0) cond1
  PRESSURE = PRESSURE - 1.0
ELSEWHERE cond1
  PRECIPITATION = .TRUE.
ENDWHERE cond1

end program

----

(translation_unit
  (program 
    (program_statement (name))
    (where_statement
      (parenthesized_expression (relational_expression (identifier) (number_literal)))
      (assignment_statement (identifier) (math_expression (identifier) (identifier))))
    (where_statement
      (parenthesized_expression (relational_expression  (identifier) (number_literal)))
      (assignment_statement (identifier) (math_expression (identifier) (number_literal)))
      (assignment_statement (identifier) (math_expression (identifier) (number_literal)))
      (elsewhere_clause
        (parenthesized_expression (relational_expression (identifier) (number_literal)))
        (assignment_statement
          (identifier) (math_expression (identifier) (number_literal))))
      (elsewhere_clause
        (assignment_statement (identifier) (boolean_literal)))
    (end_where_statement))
    (where_statement
      (block_label_start_expression)
      (parenthesized_expression (relational_expression (identifier) (number_literal)))
      (assignment_statement
        (identifier) (math_expression (identifier) (number_literal)))
      (elsewhere_clause
        (parenthesized_expression (relational_expression (identifier) (number_literal)))
        (block_label)
        (assignment_statement
          (identifier)
          (math_expression (identifier) (number_literal))))
      (elsewhere_clause (block_label)
        (assignment_statement (identifier) (boolean_literal)))
      (end_where_statement (block_label)))
  (end_program_statement)))

============================================
Forall Statements
============================================

PROGRAM TEST

FORALL(I = 1:N, J = 1:N, A(I, J) .NE. 0.0) B(I, J) = 1.0 / A(I, J)

FORALL(J=1:8)  PATTERN(J)%P => OBJECT(1+IEOR(J-1,2))


FORALL (I = 1:N, J = 1:N)
  WHERE(A(I, J) .NE. 0.0) B(I, J) = 1.0/A(I, J)
END FORALL

FORALL(I = 3:N + 1, J = 3:N + 1, A(I, J) > 0.0)
  C(I, J) = C(I, J + 2) + C(I, J - 2) + C(I + 2, J) + C(I - 2, J)
  D(I, J) = C(I, J)
END FORALL

END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (forall_statement
      (triplet_spec
        (identifier)
        (number_literal)
        (identifier))
      (triplet_spec
        (identifier)
        (number_literal)
        (identifier))
      (relational_expression
        (call_expression
          (identifier)
          (argument_list
            (identifier)
            (identifier)))
        (number_literal))
      (assignment_statement
        (call_expression
          (identifier)
          (argument_list
            (identifier)
            (identifier)))
        (math_expression
          (number_literal)
          (call_expression
            (identifier)
            (argument_list
              (identifier)
              (identifier))))))
    (forall_statement
      (triplet_spec
        (identifier)
        (number_literal)
        (number_literal))
      (pointer_association_statement
        (derived_type_member_expression
          (call_expression
            (identifier)
            (argument_list
              (identifier)))
          (type_member))
        (call_expression
          (identifier)
          (argument_list
            (math_expression
              (number_literal)
              (call_expression
                (identifier)
                (argument_list
                  (math_expression
                    (identifier)
                    (number_literal))
                  (number_literal))))))))
    (forall_statement
      (triplet_spec
        (identifier)
        (number_literal)
        (identifier))
      (triplet_spec
        (identifier)
        (number_literal)
        (identifier))
      (where_statement
        (parenthesized_expression
          (relational_expression
            (call_expression
              (identifier)
              (argument_list
                (identifier)
                (identifier)))
            (number_literal)))
        (assignment_statement
          (call_expression
            (identifier)
            (argument_list
              (identifier)
              (identifier)))
          (math_expression
            (number_literal)
            (call_expression
              (identifier)
              (argument_list
                (identifier)
                (identifier))))))
    (end_forall_statement))
    (forall_statement
      (triplet_spec
        (identifier)
        (number_literal)
        (math_expression
          (identifier)
          (number_literal)))
      (triplet_spec
        (identifier)
        (number_literal)
        (math_expression
          (identifier)
          (number_literal)))
      (relational_expression
        (call_expression
          (identifier)
          (argument_list
            (identifier)
            (identifier)))
        (number_literal))
      (assignment_statement
        (call_expression
          (identifier)
          (argument_list
            (identifier)
            (identifier)))
        (math_expression
          (math_expression
            (math_expression
              (call_expression
                (identifier)
                (argument_list
                  (identifier)
                  (math_expression
                    (identifier)
                    (number_literal))))
              (call_expression
                (identifier)
                (argument_list
                  (identifier)
                  (math_expression
                    (identifier)
                    (number_literal)))))
            (call_expression
              (identifier)
              (argument_list
                (math_expression
                  (identifier)
                  (number_literal))
                (identifier))))
          (call_expression
            (identifier)
            (argument_list
              (math_expression
                (identifier)
                (number_literal))
              (identifier)))))
      (assignment_statement
        (call_expression
          (identifier)
          (argument_list
            (identifier)
            (identifier)))
        (call_expression
          (identifier)
          (argument_list
            (identifier)
            (identifier))))
    (end_forall_statement))
  (end_program_statement)))

============================================
Select Case Statements
============================================

PROGRAM TEST
  sign_case: SELECT CASE (number)
  CASE (: -1) sign_case
    sign = -1
  CASE (0) sign_case
    sign = 0
  CASE (1 :) sign_case
    sign = 1
  END SELECT sign_case

  SELECT CASE (c)
  CASE ('a' : 'm', 'n' : 'z')
    WRITE(*,*) 'lowercase letter'
  CASE ('A' : 'Z')
    WRITE(*,*) 'uppercase letter'
  CASE (WILDCARD_CHAR)
    WRITE(*,*) 'wildcard letter'
  CASE DEFAULT
    WRITE(*,*)  'Other characters, which may not be letters'
  END SELECT
END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (select_case_statement (block_label_start_expression) (selector (identifier))
      (case_statement (case_value_range_list (extent_specifier (unary_expression (number_literal))))
        (block_label)
        (assignment_statement (identifier) (unary_expression (number_literal))))
      (case_statement (case_value_range_list (number_literal))
        (block_label)
        (assignment_statement (identifier) (number_literal)))
      (case_statement (case_value_range_list (extent_specifier (number_literal)))
        (block_label)
        (assignment_statement (identifier) (number_literal)))
      (end_select_case_statement (block_label)))
    (select_case_statement (selector (identifier))
      (case_statement
        (case_value_range_list
          (extent_specifier (string_literal) (string_literal))
          (extent_specifier (string_literal) (string_literal)))
        (write_statement
          (unit_identifier)
          (format_identifier)
          (output_item_list (string_literal))))
      (case_statement
        (case_value_range_list (extent_specifier (string_literal) (string_literal)))
        (write_statement
          (unit_identifier)
          (format_identifier)
          (output_item_list (string_literal))))
      (case_statement (case_value_range_list (identifier))
        (write_statement
          (unit_identifier)
          (format_identifier)
          (output_item_list (string_literal))))
      (case_statement (default)
        (write_statement
          (unit_identifier)
          (format_identifier)
          (output_item_list (string_literal))))
      (end_select_case_statement))
  (end_program_statement)))

============================================
Format Statements
============================================

PROGRAM TEST
1 FORMAT('1234', a5, a5a5)
2 FORMAT(2F8.3, F6.2, //, :)
3 FORMAT(I0, A(2X, I3), 'test')
4 FORMAT(*(G15.8,:,','))
END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (statement_label)
    (format_statement
      (transfer_items (string_literal) (edit_descriptor) (edit_descriptor)))
    (statement_label)
    (format_statement
      (transfer_items
        (edit_descriptor)
        (edit_descriptor)
        (edit_descriptor)
        (edit_descriptor)))
    (statement_label)
    (format_statement
      (transfer_items
        (edit_descriptor)
        (edit_descriptor)
        (edit_descriptor)
        (edit_descriptor)
        (string_literal)))
    (statement_label)
    (format_statement
      (transfer_items
        (edit_descriptor)
        (edit_descriptor)
        (edit_descriptor)
        (string_literal)))
  (end_program_statement)))

============================================
Read Statements
============================================

PROGRAM TEST
  READ *, x
  READ 9, x
  READ(*)
  READ(*, *)
  READ(10, 100) x, y, z
  READ(10,*,iostat=ioerr)
  READ(IOUNIT, FMT="(FORMAT STRING)") flags(:)
  READ(UNIT=IOUNIT, FMT="(FORMAT STRING)", IOSTAT=IOS, ADVANCE='NO') X
END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (read_statement (format_identifier) (input_item_list (identifier)))
    (read_statement
      (format_identifier (statement_label_reference))
      (input_item_list (identifier)))
    (read_statement (unit_identifier))
    (read_statement (unit_identifier) (format_identifier))
    (read_statement
      (unit_identifier (number_literal))
      (format_identifier (statement_label_reference))
      (input_item_list (identifier) (identifier) (identifier)))
    (read_statement
        (unit_identifier (number_literal))
        (format_identifier)
        (keyword_argument  (identifier) (identifier)))
    (read_statement
      (unit_identifier (identifier))
      (keyword_argument (identifier) (string_literal))
      (input_item_list (call_expression (identifier) (argument_list (extent_specifier)))))
    (read_statement
      (keyword_argument (identifier) (identifier))
      (keyword_argument (identifier) (string_literal))
      (keyword_argument (identifier) (identifier))
      (keyword_argument (identifier) (string_literal))
      (input_item_list (identifier)))
  (end_program_statement)))

============================================
Print Statements
============================================

PROGRAM TEST
  PRINT *
  PRINT *, 'test'
  PRINT IUNIT, x, y, z
END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (print_statement (format_identifier))
    (print_statement (format_identifier) (output_item_list (string_literal)))
    (print_statement
      (format_identifier (identifier))
      (output_item_list (identifier) (identifier) (identifier)))
  (end_program_statement)))

============================================
Write Statements
============================================

PROGRAM TEST
  WRITE(*)
  WRITE(*, *) ''
  WRITE(10, 100) x, y, z
  WRITE(IOUNIT, "(FORMAT STRING)", IOSTAT=IOS)
  WRITE(IOUNIT, FMT="(FORMAT STRING)") flags(:)
  WRITE(UNIT=IOUNIT, FMT="(FORMAT STRING)", IOSTAT=IOS, ADVANCE='NO') X
END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (write_statement (unit_identifier))
    (write_statement
      (unit_identifier)
      (format_identifier)
      (output_item_list (string_literal)))
    (write_statement
      (unit_identifier (number_literal))
      (format_identifier (statement_label_reference))
      (output_item_list (identifier) (identifier) (identifier)))
    (write_statement
      (unit_identifier (identifier))
      (format_identifier (string_literal))
      (keyword_argument (identifier) (identifier)))
    (write_statement
      (unit_identifier (identifier))
      (keyword_argument (identifier) (string_literal))
      (output_item_list
        (call_expression (identifier) (argument_list (extent_specifier)))))
    (write_statement
      (keyword_argument (identifier) (identifier))
      (keyword_argument (identifier) (string_literal))
      (keyword_argument (identifier) (identifier))
      (keyword_argument (identifier) (string_literal))
      (output_item_list (identifier)))
  (end_program_statement)))

============================================
Import Statements
============================================

function test()
  import :: dp, cptr
end function test

----

(translation_unit
  (function
    (function_statement (name))
    (import_statement (identifier) (identifier))
    (end_function_statement (name))))

============================================
Common Statement
============================================

PROGRAM TEST
  COMMON /blk1/ m, n /blk2/ o
  COMMON p
END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (common_statement
      (variable_group (name) (identifier) (identifier))
      (variable_group (name) (identifier)))
    (common_statement (identifier))
    (end_program_statement)))

============================================
Namelist Statement
============================================

PROGRAM TEST
  INTEGER :: i, j
  REAL :: a, b
  namelist /test/ i,j /test2/ a,b
END PROGRAM

----

(translation_unit
  (program 
    (program_statement (name))
    (variable_declaration (intrinsic_type) (identifier) (identifier))
    (variable_declaration (intrinsic_type) (identifier) (identifier))
    (namelist_statement
      (variable_group (name) (identifier) (identifier))
      (variable_group (name) (identifier) (identifier)))
    (end_program_statement)))

============================================
Enum Statements
============================================

PROGRAM test
    ENUM, BIND(C)
        ENUMERATOR :: red = 1
        ENUMERATOR blue, green
    END ENUM
END PROGRAM test

----

(translation_unit
  (program 
    (program_statement (name))
    (enum
      (enum_statement (language_binding (identifier)))
      (enumerator_statement (identifier) (number_literal))
      (enumerator_statement (identifier) (identifier))
      (end_enum_statement))
    (end_program_statement (name))))
