tree-sitter / tree-sitter-c

C grammar for tree-sitter
MIT License
225 stars 100 forks source link

bug: preprocessor directives inside an `enum_specifier` cause ERROR nodes in the parse tree #181

Closed jcreekmore closed 7 months ago

jcreekmore commented 8 months ago

Did you check existing issues?

Tree-Sitter CLI Version, if relevant (output of tree-sitter --version)

tree-sitter 0.20.8 (660481dbf71413eba5a928b0b0ab8da50c1109e0)

Describe the bug

Both the struct_specifier and union_specifier allow preprocessor directives inside of their definitions. This is fairly common in C code to allow flags to selectively enable and disable portions of the struct and union. This is also fairly common in C code to allow flags to selectively add and remove variants to an enum (or, to include a set of enum variants from a header file).

The existing grammar supports correctly parsing the struct_specifier and union_specifier in the presence of preprocessor directives, but does not allow the enum_specifier to be correctly parsed.

Steps To Reproduce/Bad Parse Tree

(translation_unit [0, 0] - [7, 0]
  (ERROR [0, 0] - [0, 10]
    (identifier [0, 5] - [0, 8]))
  (preproc_if [1, 0] - [6, 2]
    condition: (identifier [1, 4] - [1, 7])
    (ERROR [2, 2] - [2, 5]
      (identifier [2, 2] - [2, 5]))
    alternative: (preproc_else [3, 0] - [6, 2]
      (expression_statement [4, 2] - [6, 2]
        (identifier [4, 2] - [4, 5])
        (ERROR [5, 0] - [6, 1])))))

Expected Behavior/Parse Tree

(translation_unit [0, 0] - [7, 0]
  (enum_specifier [0, 0] - [6, 1]
    name: (type_identifier [0, 5] - [0, 8])
    body: (enumerator_list [0, 9] - [6, 1]
      (preproc_if [1, 0] - [5, 6]
        condition: (identifier [1, 4] - [1, 7])
        (enumerator [2, 2] - [2, 5]
          name: (identifier [2, 2] - [2, 5]))
        alternative: (preproc_else [3, 0] - [4, 5]
          (enumerator [4, 2] - [4, 5]
            name: (identifier [4, 2] - [4, 5])))))))

Repro

enum foo {
#if FOO
  FOO
#else
  BAR
#endif
};
amaanq commented 7 months ago

Fixed on master