1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use std::mem::transmute;
use std::ops::Index;
use std::iter::Iterator;
use onig_sys;
#[repr(C)]
#[derive(Debug)]
pub struct CaptureTreeNode {
raw: onig_sys::OnigCaptureTreeNode,
}
impl CaptureTreeNode {
pub fn group(&self) -> usize {
self.raw.group as usize
}
pub fn pos(&self) -> (usize, usize) {
(self.raw.beg as usize, self.raw.end as usize)
}
pub fn len(&self) -> usize {
self.raw.num_childs as usize
}
pub fn children<'t>(&'t self) -> CaptureTreeNodeIter<'t> {
CaptureTreeNodeIter { idx: 0, node: self }
}
}
impl Index<usize> for CaptureTreeNode {
type Output = CaptureTreeNode;
fn index(&self, index: usize) -> &CaptureTreeNode {
if index >= self.len() {
panic!("capture tree node index overflow")
}
unsafe { transmute(*self.raw.childs.offset(index as isize)) }
}
}
#[derive(Debug)]
pub struct CaptureTreeNodeIter<'t> {
idx: usize,
node: &'t CaptureTreeNode,
}
impl<'t> Iterator for CaptureTreeNodeIter<'t> {
type Item = &'t CaptureTreeNode;
fn next(&mut self) -> Option<&'t CaptureTreeNode> {
if self.idx < self.node.len() {
self.idx += 1;
Some(&self.node[self.idx - 1])
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.node.len();
(size, Some(size))
}
}
#[cfg(test)]
mod tests {
use super::super::*;
#[test]
fn test_regex_search_with_region_tree() {
let mut region = Region::new();
let mut syntax = Syntax::ruby().clone();
syntax.enable_operators(SyntaxOperator::SYNTAX_OPERATOR_ATMARK_CAPTURE_HISTORY);
let regex = Regex::with_options(
"(?@a+(?@b+))|(?@c+(?@d+))",
RegexOptions::REGEX_OPTION_NONE,
&syntax,
).unwrap();
let r = regex.search_with_options(
"- cd aaabbb -",
0,
13,
SearchOptions::SEARCH_OPTION_NONE,
Some(&mut region),
);
assert_eq!(r, Some(2));
assert_eq!(region.len(), 5);
let tree = region.tree().unwrap();
assert_eq!(tree.len(), 1);
assert_eq!(tree.group(), 0);
assert_eq!(tree.pos(), (2, 4));
assert_eq!(tree[0].len(), 1);
assert_eq!(tree[0].group(), 3);
assert_eq!(tree[0].pos(), (2, 4));
assert_eq!(tree[0][0].len(), 0);
assert_eq!(tree[0][0].group(), 4);
assert_eq!(tree[0][0].pos(), (3, 4));
}
}