Tree-sitter查询重复捕获数据问题及解决方法咨询
解决Tree-sitter查询重复捕获相同数据的问题
我无法理解为何Tree-sitter查询会重复捕获相同数据,如何让它只捕获一次?
待解析的Bash脚本
pkgname="potato"
Tree-sitter查询语句
(program (variable_assignment name: (variable_name) @variable_name value: (string) @value ))
复现问题的Rust代码片段
for (query_match, _) in query.captures( &Query::new( tree_sitter_bash::language(), "(program (variable_assignment name: (variable_name) @variable_name value: (string) @value ))", ) .unwrap(), tree.root_node(), |_| sourced_code.stdout.clone(), ) { query_match.captures.iter().for_each(|f| { dbg!(f.node.utf8_text(&sourced_code.stdout)).unwrap(); }); dbg!(&query_match.captures); }
执行后的输出
[src/parser/pacbuild.rs:145] f.node.utf8_text(&sourced_code.stdout) = Ok( "pkgname", ) [src/parser/pacbuild.rs:145] f.node.utf8_text(&sourced_code.stdout) = Ok( "\"potato\"", ) [src/parser/pacbuild.rs:148] &query_match.captures = [ QueryCapture { node: {Node variable_name (0, 0) - (0, 7)}, index: 0, }, QueryCapture { node: {Node string (0, 8) - (0, 16)}, index: 1, }, ] [src/parser/pacbuild.rs:145] f.node.utf8_text(&sourced_code.stdout) = Ok( "pkgname", ) [src/parser/pacbuild.rs:145] f.node.utf8_text(&sourced_code.stdout) = Ok( "\"potato\"", ) [src/parser/pacbuild.rs:148] &query_match.captures = [ QueryCapture { node: {Node variable_name (0, 0) - (0, 7)}, index: 0, }, QueryCapture { node: {Node string (0, 8) - (0, 16)}, index: 1, }, ]
问题原因与解决方法
重复捕获的核心原因是你在循环中每次调用Query::new创建了新的查询实例,而不是复用同一个查询。query.captures会针对每个查询实例返回匹配结果,导致同一个匹配被处理两次。
修复步骤:
- 将
Query::new的调用移到循环外部,提前创建并复用查询实例:
// 提前创建查询,只执行一次 let query = Query::new( tree_sitter_bash::language(), "(program (variable_assignment name: (variable_name) @variable_name value: (string) @value ))", ).unwrap(); // 循环处理捕获结果 for (query_match, _) in query.captures( &query, tree.root_node(), |_| sourced_code.stdout.clone(), ) { query_match.captures.iter().for_each(|f| { dbg!(f.node.utf8_text(&sourced_code.stdout)).unwrap(); }); dbg!(&query_match.captures); }
- 如果复用查询后仍有重复,可能是Tree-sitter的查询匹配存在嵌套或多路径匹配,可以给查询添加唯一性约束,比如用
#once指令确保只捕获一次:
(program (variable_assignment name: (variable_name) @variable_name value: (string) @value )) #once
这样就能确保只捕获一次相同的数据,避免重复输出。
内容的提问来源于stack exchange,提问作者Wizard28
相关产品推荐
相关产品推荐

