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
117
118
119
120
121
122
123
124
125
126
use regex::{Match, Regex};
use crate::obj::objstr::PyStringRef;
use crate::obj::objtype::PyClassRef;
use crate::pyobject::{PyObjectRef, PyRef, PyResult, PyValue};
use crate::vm::VirtualMachine;
impl PyValue for Regex {
fn class(vm: &VirtualMachine) -> PyClassRef {
vm.class("re", "Pattern")
}
}
#[derive(Debug)]
struct PyMatch {
start: usize,
end: usize,
}
impl PyValue for PyMatch {
fn class(vm: &VirtualMachine) -> PyClassRef {
vm.class("re", "Match")
}
}
type PyRegexRef = PyRef<Regex>;
type PyMatchRef = PyRef<PyMatch>;
fn re_match(pattern: PyStringRef, string: PyStringRef, vm: &VirtualMachine) -> PyResult {
let regex = make_regex(vm, &pattern.value)?;
do_match(vm, ®ex, &string.value)
}
fn re_search(pattern: PyStringRef, string: PyStringRef, vm: &VirtualMachine) -> PyResult {
let regex = make_regex(vm, &pattern.value)?;
do_search(vm, ®ex, &string.value)
}
fn do_match(vm: &VirtualMachine, regex: &Regex, search_text: &str) -> PyResult {
do_search(vm, regex, search_text)
}
fn do_search(vm: &VirtualMachine, regex: &Regex, search_text: &str) -> PyResult {
match regex.find(search_text) {
None => Ok(vm.get_none()),
Some(result) => create_match(vm, &result),
}
}
fn make_regex(vm: &VirtualMachine, pattern: &str) -> PyResult<Regex> {
match Regex::new(pattern) {
Ok(regex) => Ok(regex),
Err(err) => Err(vm.new_value_error(format!("Error in regex: {:?}", err))),
}
}
fn create_match(vm: &VirtualMachine, match_value: &Match) -> PyResult {
Ok(PyMatch {
start: match_value.start(),
end: match_value.end(),
}
.into_ref(vm)
.into_object())
}
fn re_compile(pattern: PyStringRef, vm: &VirtualMachine) -> PyResult<Regex> {
make_regex(vm, &pattern.value)
}
fn re_escape(pattern: PyStringRef, _vm: &VirtualMachine) -> String {
regex::escape(&pattern.value)
}
impl PyRegexRef {
fn match_(self, text: PyStringRef, vm: &VirtualMachine) -> PyResult {
do_match(vm, &self, &text.value)
}
fn search(self, text: PyStringRef, vm: &VirtualMachine) -> PyResult {
do_search(vm, &self, &text.value)
}
}
impl PyMatchRef {
fn start(self, _vm: &VirtualMachine) -> usize {
self.start
}
fn end(self, _vm: &VirtualMachine) -> usize {
self.end
}
}
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
let ctx = &vm.ctx;
let match_type = py_class!(ctx, "Match", ctx.object(), {
"start" => ctx.new_rustfunc(PyMatchRef::start),
"end" => ctx.new_rustfunc(PyMatchRef::end)
});
let pattern_type = py_class!(ctx, "Pattern", ctx.object(), {
"match" => ctx.new_rustfunc(PyRegexRef::match_),
"search" => ctx.new_rustfunc(PyRegexRef::search)
});
py_module!(vm, "re", {
"compile" => ctx.new_rustfunc(re_compile),
"escape" => ctx.new_rustfunc(re_escape),
"Match" => match_type,
"match" => ctx.new_rustfunc(re_match),
"Pattern" => pattern_type,
"search" => ctx.new_rustfunc(re_search)
})
}