use regexr::Regex;
fn spans(pattern: &str, text: &str) -> Vec<(usize, usize)> {
let re = Regex::new(pattern).expect("pattern should compile");
re.find_iter(text).map(|m| (m.start(), m.end())).collect()
}
const TOKENIZER: &str =
r#"[a-zA-Z_][a-zA-Z0-9_]*|[0-9]+(?:\.[0-9]+)?|[+\-*/=<>!&|^%]+|[(){}\[\];,.]|"[^"]*"|'[^']*'"#;
#[test]
fn class_alternation_spans_are_unchanged() {
assert_eq!(
spans(r"[a-z]+|[0-9]+", "abc 123 x9"),
vec![(0, 3), (4, 7), (8, 9), (9, 10)]
);
}
#[test]
fn character_class_spans_are_unchanged() {
let text = "abc 123 45 6789 x";
let expected = vec![(4, 7), (8, 10), (11, 15)];
assert_eq!(spans(r"[0-9]+", text), expected);
assert_eq!(spans(r"\b[0-9]+\b", text), expected);
}
#[test]
fn tokenizer_spans_are_unchanged() {
assert_eq!(
spans(TOKENIZER, "x = 1.5 + foo(y);"),
vec![
(0, 1),
(2, 3),
(4, 7),
(8, 9),
(10, 13),
(13, 14),
(14, 15),
(15, 16),
(16, 17),
]
);
}
#[test]
fn tokenizer_spans_are_unchanged_with_strings() {
assert_eq!(
spans(TOKENIZER, r#"s = "a b" + 'c';"#),
vec![(0, 1), (2, 3), (4, 9), (10, 11), (12, 15), (15, 16)]
);
}
#[test]
fn word_boundaries_still_hold() {
assert_eq!(spans(r"\b\w", "ab cd"), vec![(0, 1), (3, 4)]);
}
#[test]
fn word_boundary_negation_still_holds() {
assert_eq!(spans(r"\B\w", "ab cd"), vec![(1, 2), (4, 5)]);
}
#[test]
fn start_anchor_still_holds() {
assert_eq!(spans(r"^foo", "foo foo"), vec![(0, 3)]);
}
#[test]
fn multiline_anchors_still_hold() {
assert_eq!(spans(r"(?m)^x", "x\nyx\nx"), vec![(0, 1), (5, 6)]);
}
#[test]
fn literal_prefilter_spans_are_unchanged() {
assert_eq!(spans(r"hello", "say hello, hello"), vec![(4, 9), (11, 16)]);
}
#[test]
fn end_anchor_spans_are_unchanged() {
assert_eq!(spans(r"[0-9]+$", "12 345"), vec![(3, 6)]);
}
#[test]
fn multibyte_haystack_spans_stay_on_codepoint_boundaries() {
let text = "héllo wörld café";
assert_eq!(
spans(r"[a-z]+", text),
vec![(0, 1), (3, 6), (7, 8), (10, 13), (14, 17)]
);
assert_eq!(spans(r"[^ ]+", text), vec![(0, 6), (7, 13), (14, 19)]);
}
#[test]
fn empty_matches_are_unchanged() {
assert_eq!(spans(r"a*", "bab"), vec![(0, 0), (1, 2), (3, 3)]);
}