use crate::Result;
use log::trace;
use std::time::Instant;
use regex_syntax::ast::{parse::Parser, Ast};
pub(crate) fn parse_regex_syntax(input: &str) -> Result<Ast> {
let now = Instant::now();
match Parser::new().parse(input) {
Ok(syntax_tree) => {
let elapsed_time = now.elapsed();
trace!("Parsing took {} milliseconds.", elapsed_time.as_millis());
Ok(syntax_tree)
}
Err(e) => Err(e.into()),
}
}
#[cfg(test)]
mod tests {
use std::error::Error;
use crate::{ScnrError, ScnrErrorKind};
use super::*;
#[test]
fn test_parse_regex_syntax_valid() {
let input = r"\d";
let ast = parse_regex_syntax(input).unwrap();
assert_eq!(format!("{:?}", ast),
"ClassPerl(ClassPerl { span: Span(Position(o: 0, l: 1, c: 1), Position(o: 2, l: 1, c: 3)), kind: Digit, negated: false })");
}
#[test]
fn test_parse_regex_syntax_invalid() {
let input = r"^\d{4}-\d{2}-\d{2}$[";
let result = parse_regex_syntax(input);
assert!(result.is_err());
assert!(matches!(
result,
Err(ref e) if matches!(e, ScnrError{ source } if matches!(**source, ScnrErrorKind::RegexSyntaxError(_, _)))
));
assert_eq!(
result.unwrap_err().source().unwrap().to_string(),
r#"'!' regex parse error:
^\d{4}-\d{2}-\d{2}$[
^
error: unclosed character class"#
);
}
#[test]
fn test_parse_regex_syntax_empty() {
let input = "";
let result = parse_regex_syntax(input);
assert!(result.is_ok());
}
#[test]
#[should_panic(expected = "RegexSyntaxError(Error { kind: UnsupportedLookAround")]
fn test_a_only_if_followed_by_b() {
let input = r"a(?=b)";
let _ = parse_regex_syntax(input).unwrap();
}
}