Skip to content

A star * repetition followed an immediate sibling anchor . only matches the first match when a parent match is present #3683

@TACIXAT

Description

@TACIXAT

Problem

Something I don't fully understand is happening here. The first two queries work as expected. The third and fourth only match the first match.

// this one has two comments
// ooOoOoOOOo
extern int baz;

// this one has a comment
extern int bar;

extern int foo;
s-expression:
(translation_unit 
  (comment) 
  (comment) 
  (declaration (storage_class_specifier) type: (primitive_type) declarator: (identifier)) 
  (comment) 
  (declaration (storage_class_specifier) type: (primitive_type) declarator: (identifier)) 
  (declaration (storage_class_specifier) type: (primitive_type) declarator: (identifier)))

== QUERY ==

(
  (comment)*
  .
  (declaration)
) @decl


-----------
// this one has two comments
// ooOoOoOOOo
extern int baz;
-----------

-----------
// this one has a comment
extern int bar;
-----------

-----------
extern int foo;
-----------

===========

== QUERY ==

(translation_unit
  (comment) @comment
  .
  (declaration) @decl
)


-----------
// ooOoOoOOOo
extern int baz;
-----------

-----------
// this one has a comment
extern int bar;
-----------

===========

== QUERY ==

(translation_unit
  (comment)* @comment
  .
  (declaration) @decl
)


-----------
// this one has two comments
// ooOoOoOOOo
extern int baz;
-----------

===========

== QUERY ==

(translation_unit
  (
    (comment)*
    .
    (declaration)
  ) @decl
)


-----------
// this one has two comments
// ooOoOoOOOo
extern int baz;
-----------

Steps to reproduce

use tree_sitter;
use tree_sitter_cpp;

pub fn main() {
  let source_code = "
    // this one has two comments
    // ooOoOoOOOo
    extern int baz;

    // this one has a comment
    extern int bar;

    extern int foo;
  ";

  let query_strings = vec![
    "
(
  (comment)*
  .
  (declaration)
) @decl
    ",
    "
(translation_unit 
  (comment) @comment
  .
  (declaration) @decl
)
    ",
    "
(translation_unit 
  (comment)* @comment
  .
  (declaration) @decl
)
    ",
    "
(translation_unit 
  (
    (comment)* 
    .
    (declaration)
  ) @decl
)
    ",
  ];

  let mut parser = tree_sitter::Parser::new();
  parser.set_language(&tree_sitter_cpp::LANGUAGE.into()).unwrap();

  let tree = parser.parse(source_code, None).unwrap();
  let root_node = tree.root_node();

  println!("s-expression:\n{}\n", root_node.to_sexp());

  let mut cursor = tree_sitter::QueryCursor::new();
  for query_string in query_strings {
    println!("== QUERY ==\n{}\n", query_string);
    let query = tree_sitter::Query::new(
      &tree_sitter_cpp::LANGUAGE.into(), query_string).unwrap();
    let matches = cursor.matches(&query, root_node, source_code.as_bytes());
    for m in matches {
      println!("-----------");
      for c in m.captures {
        println!("{}", c.node.utf8_text(source_code.as_bytes()).unwrap());
      }
      println!("-----------\n");
    }
    println!("===========\n");
  }
} 

Expected behavior

I could match declarations optionally preceded by comments with a parent match restricting things.

Tree-sitter version (tree-sitter --version)

0.23 (Rust)

Operating system/version

Windows 11

Metadata

Metadata

Assignees

No one assigned

    Labels

    queryRelated to query execution

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions