Skip to content

[Bug] Parser incorrectly falls back to implicit 'program' when 'module' is preceded by multiple preprocessor blocks #180

@uwabami

Description

@uwabami

Description

The parser incorrectly identifies a file as an implicit program instead of a module when the module definition is preceded by multiple preprocessor directives (#ifdef) interleaved with comments.

The module keyword is not recognized as the start of a module, but rather as an identifier inside an implicit program body, leading to parse errors.

Steps to Reproduce

  1. Create a file named repro.f90 with the following content:
#ifdef A
! comment 1
#endif
#ifdef B
! comment 2
#endif
#ifdef C
! comment 2
#endif
! comment ...
module my_mod
  integer :: a
  integer :: b
contains
  function foo
  end function foo
end module my_mod
  1. Run the tree-sitter CLI: tree-sitter parse repro.f90

Actual Behavior

The parser produces a program node at the root and fails to parse the module keyword, treating it as an identifier erro

(translation_unit [0, 0] - [17, 0]
  (program [0, 0] - [17, 0]
    (preproc_ifdef [0, 0] - [2, 6]
      name: (identifier [0, 7] - [0, 8])
      (comment [1, 0] - [1, 11]))
    (preproc_ifdef [3, 0] - [5, 6]
      name: (identifier [3, 7] - [3, 8])
      (comment [4, 0] - [4, 11]))
    (preproc_ifdef [6, 0] - [8, 6]
      name: (identifier [6, 7] - [6, 8])
      (comment [7, 0] - [7, 11]))
    (comment [9, 0] - [9, 13])
    (ERROR [10, 0] - [11, 0]       <-- 'module' keyword fails here
      (identifier [10, 0] - [10, 6]))
    (variable_declaration [11, 0] - [11, 12]
      type: (intrinsic_type [11, 0] - [11, 7])
      declarator: (identifier [11, 11] - [11, 12]))
    (variable_declaration [12, 0] - [12, 12]
      type: (intrinsic_type [12, 0] - [12, 7])
      declarator: (identifier [12, 11] - [12, 12]))
    (internal_procedures [13, 0] - [16, 0]
      (contains_statement [13, 0] - [13, 8])
      (function [14, 0] - [16, 0]
        (function_statement [14, 0] - [15, 0]
          name: (name [14, 9] - [14, 12]))
        (end_function_statement [15, 0] - [16, 0]
          (name [15, 13] - [15, 16]))))
    (end_program_statement [16, 0] - [17, 0]
      (name [16, 4] - [16, 10])
      (ERROR [16, 11] - [16, 17]))))

Expected Behavior

The translation_unit should contain a module node instead of a program node. The preprocessor directives and comments preceding the module statement should be parsed as siblings of the module node (or correctly recognized as trivia), and the module statement itself should be parsed without errors.

(translation_unit
  (preproc_ifdef ...)
  ...
  (module ...))

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions