use syntax;
use backtrack::BacktrackCache;
use compile::{Compiled, Compiler};
use dfa::DfaCache;
use inst::Insts;
use nfa::NfaCache;
use pool::{Pool, PoolGuard};
use literals::Literals;
use Error;
#[derive(Clone, Debug)]
pub struct Program {
pub original: String,
pub insts: Insts,
pub cap_names: Vec<Option<String>>,
pub prefixes: Literals,
pub anchored_begin: bool,
pub anchored_end: bool,
pub cache: EngineCache,
}
pub struct ProgramBuilder {
re: String,
compiler: Compiler,
}
impl ProgramBuilder {
pub fn new(re: &str) -> Self {
ProgramBuilder {
re: re.to_owned(),
compiler: Compiler::new(),
}
}
pub fn size_limit(mut self, size_limit: usize) -> Self {
self.compiler = self.compiler.size_limit(size_limit);
self
}
pub fn bytes(mut self, yes: bool) -> Self {
self.compiler = self.compiler.bytes(yes);
self
}
pub fn dfa(mut self, yes: bool) -> Self {
self.compiler = self.compiler.dfa(yes);
self
}
pub fn reverse(mut self, yes: bool) -> Self {
self.compiler = self.compiler.reverse(yes);
self
}
pub fn compile(self) -> Result<Program, Error> {
let expr = try!(syntax::Expr::parse(&self.re));
let Compiled { insts, cap_names } = try!(self.compiler.compile(&expr));
let (prefixes, anchored_begin, anchored_end) = (
insts.prefix_matcher(),
insts.anchored_begin(),
insts.anchored_end(),
);
Ok(Program {
original: self.re,
insts: insts,
cap_names: cap_names,
prefixes: prefixes,
anchored_begin: anchored_begin,
anchored_end: anchored_end,
cache: EngineCache::new(),
})
}
}
impl Program {
pub fn is_prefix_match(&self) -> bool {
self.prefixes.at_match() && self.prefixes.preserves_priority()
}
pub fn is_reversed(&self) -> bool {
self.insts.is_reversed()
}
pub fn num_captures(&self) -> usize {
self.cap_names.len()
}
pub fn alloc_captures(&self) -> Vec<Option<usize>> {
vec![None; 2 * self.num_captures()]
}
pub fn cache_nfa(&self) -> PoolGuard<Box<NfaCache>> {
self.cache.nfa.get()
}
pub fn cache_backtrack(&self) -> PoolGuard<Box<BacktrackCache>> {
self.cache.backtrack.get()
}
pub fn cache_dfa(&self) -> PoolGuard<Box<DfaCache>> {
self.cache.dfa.get()
}
pub fn approximate_size(&self) -> usize {
self.original.len()
+ self.insts.approximate_size()
+ self.prefixes.approximate_size()
}
}
#[derive(Debug)]
pub struct EngineCache {
nfa: Pool<Box<NfaCache>>,
backtrack: Pool<Box<BacktrackCache>>,
dfa: Pool<Box<DfaCache>>,
}
impl EngineCache {
fn new() -> Self {
EngineCache {
nfa: Pool::new(Box::new(|| Box::new(NfaCache::new()))),
backtrack: Pool::new(Box::new(|| Box::new(BacktrackCache::new()))),
dfa: Pool::new(Box::new(|| Box::new(DfaCache::new()))),
}
}
}
impl Clone for EngineCache {
fn clone(&self) -> EngineCache {
EngineCache::new()
}
}