use regex_syntax::ast::Ast;
use regex_syntax::hir::Hir;
pub fn to_hir(s: &str) -> Hir {
regex_syntax::Parser::new().parse(s).unwrap()
}
pub fn to_hir_with_expand(s: &str, name: &str, value: &str) -> Hir {
let mut ast = to_ast(s);
expand_capture(&mut ast, |group_name| {
if group_name == name {
Some(to_ast(®ex_syntax::escape(value)))
} else {
None
}
});
let s = format!("{}", &ast);
regex_syntax::hir::translate::Translator::new()
.translate(&s, &ast)
.unwrap()
}
fn to_ast(s: &str) -> Ast {
regex_syntax::ast::parse::Parser::new().parse(s).unwrap()
}
fn replace_ast(ast: &mut Ast, f: &mut impl FnMut(&mut Ast) -> bool) {
if !f(ast) {
return;
}
use regex_syntax::ast::*;
match ast {
Ast::Empty(..)
| Ast::Flags(..)
| Ast::Literal(..)
| Ast::Dot(..)
| Ast::Assertion(..)
| Ast::Class(..) => {}
Ast::Repetition(Repetition { ast, .. }) | Ast::Group(Group { ast, .. }) => {
replace_ast(ast, f)
}
Ast::Alternation(Alternation { asts, .. }) | Ast::Concat(Concat { asts, .. }) => {
for ast in asts {
replace_ast(ast, f)
}
}
}
}
fn expand_capture(ast: &mut Ast, mut f: impl FnMut(&str) -> Option<Ast>) {
let f = &mut f;
replace_ast(ast, &mut |ast| {
use regex_syntax::ast::*;
if let Ast::Group(g) = &ast {
if let GroupKind::CaptureName(name) = &g.kind {
if let Some(ast_new) = f(&name.name) {
*ast = ast_new;
return false;
}
}
}
true
})
}