diff --git a/extmod/modre.c b/extmod/modre.c index 2a3fdfd350..3a203644a8 100644 --- a/extmod/modre.c +++ b/extmod/modre.c @@ -195,10 +195,11 @@ static void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t } static mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { - (void)n_args; mp_obj_re_t *self; + bool was_compiled = false; if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) { self = MP_OBJ_TO_PTR(args[0]); + was_compiled = true; } else { self = MP_OBJ_TO_PTR(mod_re_compile(1, args)); } @@ -206,6 +207,27 @@ static mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { size_t len; subj.begin_line = subj.begin = mp_obj_str_get_data(args[1], &len); subj.end = subj.begin + len; + + if (was_compiled && n_args > 2) { + // Arg #2 is starting-pos + size_t startpos = mp_obj_get_int(args[2]); + if (startpos >= len) { + startpos = len; + } + subj.begin += startpos; + if (n_args > 3) { + // Arg #3 is ending-pos + size_t endpos = mp_obj_get_int(args[3]); + if (endpos > len) { + endpos = len; + } + else if (endpos < startpos) { + endpos = startpos; + } + subj.end = subj.begin_line + endpos; + } + } + int caps_num = (self->re.sub + 1) * 2; mp_obj_match_t *match = m_new_obj_var(mp_obj_match_t, caps, char *, caps_num); // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char diff --git a/tests/extmod/re_start_end_pos.py b/tests/extmod/re_start_end_pos.py new file mode 100644 index 0000000000..f8405b7852 --- /dev/null +++ b/tests/extmod/re_start_end_pos.py @@ -0,0 +1,59 @@ +# test start and end pos specification + +try: + import re +except ImportError: + print("SKIP") + raise SystemExit + + +def print_groups(match): + print("----") + try: + if match is not None: + i = 0 + while True: + print(match.group(i)) + i += 1 + except IndexError: + pass + +p = re.compile(r"o") +m = p.match("dog") +print_groups(m) + +m = p.match("dog", 1) +print_groups(m) + +m = p.match("dog", 2) +print_groups(m) + +m = p.match("dog", 3) # Past end of input +print_groups(m) + +m = p.match("dog", 0, 1) +print_groups(m) + +# Caret only matches the actual beginning +p = re.compile(r"^o") +m = p.match("dog", 1) +print_groups(m) + +# End at begging means searching empty string +p = re.compile(r"o") +m = p.match("dog", 1, 1) +print_groups(m) + +# Search also works +print('--search') + +p = re.compile(r"o") +m = p.search('dog') +print_groups(m) + +m = p.search('dog', 1) +print_groups(m) + +m = p.search('dog', 2) +print_groups(m) + diff --git a/tests/extmod/re_start_end_pos.py.exp b/tests/extmod/re_start_end_pos.py.exp new file mode 100644 index 0000000000..e02177fccd --- /dev/null +++ b/tests/extmod/re_start_end_pos.py.exp @@ -0,0 +1,14 @@ +---- +---- +o +---- +---- +---- +---- +---- +--search +---- +o +---- +o +----