in crates/concrete-syntax/src/models/concrete_syntax/interpreter.rs [110:164]
fn match_sequential_siblings(
cursor: &mut TreeCursor, source_code_ref: &[u8], cs_elements: &[ResolvedCsElement],
) -> PatternMatchResult {
let parent_node = cursor.node();
let mut child_seq_match_start = 0;
if cursor.goto_first_child() {
// Iterate through siblings to find a match
loop {
// Clone the cursor in order to attempt matching the sequence starting at cursor.node
// Cloning here is necessary other we won't be able to advance to the next sibling if the matching fails
let result = {
match_cs_pattern(
&mut MatchingContext {
cursor: cursor.clone(),
source_code: source_code_ref,
top_node: &parent_node,
},
cs_elements,
true,
)
};
// If we got a successful match, extract the mapping and index
if let PatternMatchResult::Success {
captures: mapping,
consumed_nodes: last_node_index,
range: None,
} = result
{
// Determine the last matched node. Remember, we are matching subsequences of children [n ... k]
let last_node = parent_node.child(last_node_index);
let start_range = cursor.node().range();
let end_range = last_node.unwrap().range();
let range = Range::span_ranges(start_range, end_range);
if last_node_index != child_seq_match_start || parent_node.child_count() == 1 {
return PatternMatchResult::Success {
captures: mapping,
consumed_nodes: last_node_index,
range: Some(range),
};
}
// This is to prevent double matches when unrolling a node. i.e., matching the statement in a function body,
// as well as the statement itself when unrolled.
return PatternMatchResult::failed();
}
child_seq_match_start += 1;
if !cursor.goto_next_sibling() {
break;
}
}
} // Not currently handing matching of leaf nodes. Current semantics would never match it anyway.
PatternMatchResult::failed()
}