mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
@@ -6,11 +6,9 @@
|
||||
*/
|
||||
use regex::{Match, Regex};
|
||||
|
||||
use crate::function::PyFuncArgs;
|
||||
use crate::obj::objstr;
|
||||
use crate::obj::objstr::PyStringRef;
|
||||
use crate::obj::objtype::PyClassRef;
|
||||
use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol};
|
||||
use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
impl PyValue for Regex {
|
||||
@@ -19,85 +17,6 @@ impl PyValue for Regex {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create the python `re` module with all its members.
|
||||
pub fn make_module(ctx: &PyContext) -> PyObjectRef {
|
||||
let match_type = py_class!(ctx, "Match", ctx.object(), {
|
||||
"start" => ctx.new_rustfunc(match_start),
|
||||
"end" => ctx.new_rustfunc(match_end)
|
||||
});
|
||||
|
||||
let pattern_type = py_class!(ctx, "Pattern", ctx.object(), {
|
||||
"match" => ctx.new_rustfunc(pattern_match),
|
||||
"search" => ctx.new_rustfunc(pattern_search)
|
||||
});
|
||||
|
||||
py_module!(ctx, "re", {
|
||||
"compile" => ctx.new_rustfunc(re_compile),
|
||||
"Match" => match_type,
|
||||
"match" => ctx.new_rustfunc(re_match),
|
||||
"Pattern" => pattern_type,
|
||||
"search" => ctx.new_rustfunc(re_search)
|
||||
})
|
||||
}
|
||||
|
||||
/// Implement re.match
|
||||
/// See also:
|
||||
/// https://docs.python.org/3/library/re.html#re.match
|
||||
fn re_match(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
required = [
|
||||
(pattern, Some(vm.ctx.str_type())),
|
||||
(string, Some(vm.ctx.str_type()))
|
||||
]
|
||||
);
|
||||
let pattern_str = objstr::get_value(&pattern);
|
||||
let regex = make_regex(vm, &pattern_str)?;
|
||||
let search_text = objstr::get_value(string);
|
||||
|
||||
do_match(vm, ®ex, search_text)
|
||||
}
|
||||
|
||||
/// Implement re.search
|
||||
/// See also:
|
||||
/// https://docs.python.org/3/library/re.html#re.search
|
||||
fn re_search(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
required = [
|
||||
(pattern, Some(vm.ctx.str_type())),
|
||||
(string, Some(vm.ctx.str_type()))
|
||||
]
|
||||
);
|
||||
|
||||
let pattern_str = objstr::get_value(&pattern);
|
||||
let regex = make_regex(vm, &pattern_str)?;
|
||||
let search_text = objstr::get_value(string);
|
||||
|
||||
do_search(vm, ®ex, search_text)
|
||||
}
|
||||
|
||||
fn do_match(vm: &VirtualMachine, regex: &Regex, search_text: String) -> PyResult {
|
||||
// TODO: implement match!
|
||||
do_search(vm, regex, search_text)
|
||||
}
|
||||
|
||||
fn do_search(vm: &VirtualMachine, regex: &Regex, search_text: String) -> 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))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Inner data for a match object.
|
||||
#[derive(Debug)]
|
||||
struct PyMatch {
|
||||
@@ -111,6 +30,38 @@ impl PyValue for PyMatch {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
// TODO: implement match!
|
||||
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))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Take a found regular expression and convert it to proper match object.
|
||||
fn create_match(vm: &VirtualMachine, match_value: &Match) -> PyResult {
|
||||
// let mo = vm.invoke(match_class, PyFuncArgs::default())?;
|
||||
@@ -124,68 +75,45 @@ fn create_match(vm: &VirtualMachine, match_value: &Match) -> PyResult {
|
||||
.into_object())
|
||||
}
|
||||
|
||||
/// Compile a regular expression into a Pattern object.
|
||||
/// See also:
|
||||
/// https://docs.python.org/3/library/re.html#re.compile
|
||||
fn re_compile(pattern: PyStringRef, vm: &VirtualMachine) -> PyResult<PyRef<Regex>> {
|
||||
let regex = make_regex(vm, &pattern.value)?;
|
||||
|
||||
Ok(regex.into_ref(vm))
|
||||
fn re_compile(pattern: PyStringRef, vm: &VirtualMachine) -> PyResult<Regex> {
|
||||
make_regex(vm, &pattern.value)
|
||||
}
|
||||
|
||||
fn pattern_match(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
required = [(zelf, None), (text, Some(vm.ctx.str_type()))]
|
||||
);
|
||||
|
||||
let regex = get_regex(zelf);
|
||||
let search_text = objstr::get_value(text);
|
||||
do_match(vm, ®ex, search_text)
|
||||
}
|
||||
|
||||
fn pattern_search(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
required = [(zelf, None), (text, Some(vm.ctx.str_type()))]
|
||||
);
|
||||
|
||||
let regex = get_regex(zelf);
|
||||
let search_text = objstr::get_value(text);
|
||||
do_search(vm, ®ex, search_text)
|
||||
}
|
||||
|
||||
/// Returns start of match
|
||||
/// see: https://docs.python.org/3/library/re.html#re.Match.start
|
||||
fn match_start(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(zelf, None)]);
|
||||
// TODO: implement groups
|
||||
let m = get_match(zelf);
|
||||
Ok(vm.new_int(m.start))
|
||||
}
|
||||
|
||||
fn match_end(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(zelf, None)]);
|
||||
// TODO: implement groups
|
||||
let m = get_match(zelf);
|
||||
Ok(vm.new_int(m.end))
|
||||
}
|
||||
|
||||
/// Retrieve inner rust regex from python object:
|
||||
fn get_regex(obj: &PyObjectRef) -> &Regex {
|
||||
// TODO: Regex shouldn't be stored in payload directly, create newtype wrapper
|
||||
if let Some(regex) = obj.payload::<Regex>() {
|
||||
return regex;
|
||||
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)
|
||||
}
|
||||
panic!("Inner error getting regex {:?}", obj);
|
||||
}
|
||||
|
||||
/// Retrieve inner rust match from python object:
|
||||
fn get_match(obj: &PyObjectRef) -> &PyMatch {
|
||||
if let Some(value) = obj.payload::<PyMatch>() {
|
||||
return value;
|
||||
impl PyMatchRef {
|
||||
fn start(self, _vm: &VirtualMachine) -> usize {
|
||||
self.start
|
||||
}
|
||||
fn end(self, _vm: &VirtualMachine) -> usize {
|
||||
self.end
|
||||
}
|
||||
panic!("Inner error getting match {:?}", obj);
|
||||
}
|
||||
|
||||
/// Create the python `re` module with all its members.
|
||||
pub fn make_module(ctx: &PyContext) -> PyObjectRef {
|
||||
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!(ctx, "re", {
|
||||
"compile" => ctx.new_rustfunc(re_compile),
|
||||
"Match" => match_type,
|
||||
"match" => ctx.new_rustfunc(re_match),
|
||||
"Pattern" => pattern_type,
|
||||
"search" => ctx.new_rustfunc(re_search)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user