use lexer::re::Regex;
use regex_syntax::{ClassRange, Expr, Repeater};
use std::char;
use std::fmt::{Debug, Formatter, Error as FmtError};
use std::usize;
#[cfg(test)]
mod interpret;
#[cfg(test)]
mod test;
#[derive(Debug)]
pub struct NFA {
states: Vec<State>,
edges: Edges
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Test {
pub start: u32,
pub end: u32,
}
#[derive(Debug, PartialEq, Eq)]
pub struct Noop;
#[derive(Debug, PartialEq, Eq)]
pub struct Other;
#[derive(Debug)]
pub struct State {
kind: StateKind,
first_noop_edge: usize,
first_test_edge: usize,
first_other_edge: usize,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum StateKind {
Accept, Reject, Neither
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct NFAStateIndex(usize);
#[derive(Debug)]
pub struct Edges {
noop_edges: Vec<Edge<Noop>>,
test_edges: Vec<Edge<Test>>,
other_edges: Vec<Edge<Other>>,
}
#[derive(PartialEq, Eq)]
pub struct Edge<L> {
pub from: NFAStateIndex,
pub label: L,
pub to: NFAStateIndex,
}
pub const ACCEPT: NFAStateIndex = NFAStateIndex(0);
pub const REJECT: NFAStateIndex = NFAStateIndex(1);
pub const START: NFAStateIndex = NFAStateIndex(2);
#[derive(Debug, PartialEq, Eq)]
pub enum NFAConstructionError {
NamedCaptures,
NonGreedy,
WordBoundary,
LineBoundary,
TextBoundary,
}
impl NFA {
pub fn from_re(regex: &Regex) -> Result<NFA, NFAConstructionError> {
let mut nfa = NFA::new();
let s0 = try!(nfa.expr(regex, ACCEPT, REJECT));
nfa.push_edge(START, Noop, s0);
Ok(nfa)
}
pub fn edges<L:EdgeLabel>(&self, from: NFAStateIndex) -> EdgeIterator<L> {
let vec = L::vec(&self.edges);
let first = *L::first(&self.states[from.0]);
EdgeIterator { edges: vec, from: from, index: first }
}
pub fn kind(&self, from: NFAStateIndex) -> StateKind {
self.states[from.0].kind
}
pub fn is_accepting_state(&self, from: NFAStateIndex) -> bool {
self.states[from.0].kind == StateKind::Accept
}
pub fn is_rejecting_state(&self, from: NFAStateIndex) -> bool {
self.states[from.0].kind == StateKind::Reject
}
fn new() -> NFA {
let mut nfa = NFA {
states: vec![],
edges: Edges {
noop_edges: vec![],
test_edges: vec![],
other_edges: vec![],
}
};
assert!(nfa.new_state(StateKind::Accept) == ACCEPT);
assert!(nfa.new_state(StateKind::Reject) == REJECT);
assert!(nfa.new_state(StateKind::Neither) == START);
nfa.push_edge(ACCEPT, Other, REJECT);
nfa.push_edge(REJECT, Other, REJECT);
nfa
}
fn new_state(&mut self, kind: StateKind) -> NFAStateIndex {
let index = self.states.len();
self.states.push(State { kind: kind,
first_noop_edge: usize::MAX,
first_test_edge: usize::MAX,
first_other_edge: usize::MAX });
NFAStateIndex(index)
}
fn push_edge<L:EdgeLabel>(&mut self, from: NFAStateIndex, label: L, to: NFAStateIndex) {
let edge_vec = L::vec_mut(&mut self.edges);
let edge_index = edge_vec.len();
edge_vec.push(Edge { from: from, label: label, to: to });
let first_index = L::first_mut(&mut self.states[from.0]);
if *first_index == usize::MAX {
*first_index = edge_index;
} else{
assert_eq!(edge_vec[edge_index - 1].from, from);
}
}
fn expr(&mut self, expr: &Expr, accept: NFAStateIndex, reject: NFAStateIndex)
-> Result<NFAStateIndex, NFAConstructionError> {
match *expr {
Expr::Empty => {
Ok(accept)
}
Expr::Literal { ref chars, casei } => {
Ok(if casei {
chars.iter()
.rev()
.fold(accept, |s, &ch| {
let s1 = self.new_state(StateKind::Neither);
for ch1 in ch.to_lowercase().chain(ch.to_uppercase()) {
self.push_edge(s1, Test::char(ch1), s);
}
self.push_edge(s1, Other, reject);
s1
})
} else {
chars.iter()
.rev()
.fold(accept, |s, &ch| {
let s1 = self.new_state(StateKind::Neither);
self.push_edge(s1, Test::char(ch), s);
self.push_edge(s1, Other, reject);
s1
})
})
}
Expr::AnyCharNoNL => {
let s0 = self.new_state(StateKind::Neither);
for nl_char in "\n\r".chars() {
self.push_edge(s0, Test::char(nl_char), reject);
}
self.push_edge(s0, Other, accept);
Ok(s0)
}
Expr::AnyChar => {
let s0 = self.new_state(StateKind::Neither);
self.push_edge(s0, Other, accept);
Ok(s0)
}
Expr::Class(ref class) => {
let s0 = self.new_state(StateKind::Neither);
for &range in class {
let test: Test = range.into();
self.push_edge(s0, test, accept);
}
self.push_edge(s0, Other, reject);
Ok(s0)
}
Expr::StartLine | Expr::EndLine => {
Err(NFAConstructionError::LineBoundary)
}
Expr::StartText | Expr::EndText => {
Err(NFAConstructionError::TextBoundary)
}
Expr::WordBoundary | Expr::NotWordBoundary => {
Err(NFAConstructionError::WordBoundary)
}
Expr::Group { ref e, i: _, name: None } => {
self.expr(e, accept, reject)
}
Expr::Group { name: Some(_), .. } => {
Err(NFAConstructionError::NamedCaptures)
}
Expr::Repeat { greedy: false, .. } => {
Err(NFAConstructionError::NonGreedy)
}
Expr::Repeat { ref e, r: Repeater::ZeroOrOne, greedy: true } => {
self.optional_expr(e, accept, reject)
}
Expr::Repeat { ref e, r: Repeater::ZeroOrMore, greedy: true } => {
self.star_expr(e, accept, reject)
}
Expr::Repeat { ref e, r: Repeater::OneOrMore, greedy: true } => {
self.plus_expr(e, accept, reject)
}
Expr::Repeat { ref e,
r: Repeater::Range { min, max: None },
greedy: true } => {
let mut s = try!(self.star_expr(e, accept, reject));
for _ in 0..min {
s = try!(self.expr(e, s, reject));
}
Ok(s)
}
Expr::Repeat { ref e,
r: Repeater::Range { min, max: Some(max) },
greedy: true } => {
let mut s = accept;
for _ in min..max {
s = try!(self.optional_expr(e, s, reject));
}
for _ in 0..min {
s = try!(self.expr(e, s, reject));
}
Ok(s)
}
Expr::Concat(ref exprs) => {
let mut s = accept;
for expr in exprs.iter().rev() {
s = try!(self.expr(expr, s, reject));
}
Ok(s)
}
Expr::Alternate(ref exprs) => {
let s0 = self.new_state(StateKind::Neither);
let targets: Vec<_> =
try!(exprs.iter()
.map(|expr| self.expr(expr, accept, reject))
.collect());
for target in targets {
self.push_edge(s0, Noop, target);
}
Ok(s0)
}
}
}
fn optional_expr(&mut self,
expr: &Expr,
accept: NFAStateIndex,
reject: NFAStateIndex)
-> Result<NFAStateIndex, NFAConstructionError> {
let s1 = try!(self.expr(expr, accept, reject));
let s0 = self.new_state(StateKind::Neither);
self.push_edge(s0, Noop, accept); self.push_edge(s0, Noop, s1);
Ok(s0)
}
fn star_expr(&mut self,
expr: &Expr,
accept: NFAStateIndex,
reject: NFAStateIndex)
-> Result<NFAStateIndex, NFAConstructionError> {
let s0 = self.new_state(StateKind::Neither);
let s1 = try!(self.expr(expr, s0, reject));
self.push_edge(s0, Noop, accept);
self.push_edge(s0, Noop, s1);
Ok(s0)
}
fn plus_expr(&mut self,
expr: &Expr,
accept: NFAStateIndex,
reject: NFAStateIndex)
-> Result<NFAStateIndex, NFAConstructionError> {
let s1 = self.new_state(StateKind::Neither);
let s0 = try!(self.expr(expr, s1, reject));
self.push_edge(s1, Noop, accept);
self.push_edge(s1, Noop, s0);
Ok(s0)
}
}
pub trait EdgeLabel: Sized {
fn vec_mut(nfa: &mut Edges) -> &mut Vec<Edge<Self>>;
fn vec(nfa: &Edges) -> &Vec<Edge<Self>>;
fn first_mut(state: &mut State) -> &mut usize;
fn first(state: &State) -> &usize;
}
impl EdgeLabel for Noop {
fn vec_mut(nfa: &mut Edges) -> &mut Vec<Edge<Noop>> { &mut nfa.noop_edges }
fn first_mut(state: &mut State) -> &mut usize { &mut state.first_noop_edge }
fn vec(nfa: &Edges) -> &Vec<Edge<Noop>> { &nfa.noop_edges }
fn first(state: &State) -> &usize { &state.first_noop_edge }
}
impl EdgeLabel for Other {
fn vec_mut(nfa: &mut Edges) -> &mut Vec<Edge<Other>> { &mut nfa.other_edges }
fn first_mut(state: &mut State) -> &mut usize { &mut state.first_other_edge }
fn vec(nfa: &Edges) -> &Vec<Edge<Other>> { &nfa.other_edges }
fn first(state: &State) -> &usize { &state.first_other_edge }
}
impl EdgeLabel for Test {
fn vec_mut(nfa: &mut Edges) -> &mut Vec<Edge<Test>> { &mut nfa.test_edges }
fn first_mut(state: &mut State) -> &mut usize { &mut state.first_test_edge }
fn vec(nfa: &Edges) -> &Vec<Edge<Test>> { &nfa.test_edges }
fn first(state: &State) -> &usize { &state.first_test_edge }
}
pub struct EdgeIterator<'nfa,L:EdgeLabel+'nfa> {
edges: &'nfa [Edge<L>],
from: NFAStateIndex,
index: usize,
}
impl<'nfa,L:EdgeLabel> Iterator for EdgeIterator<'nfa,L> {
type Item = &'nfa Edge<L>;
fn next(&mut self) -> Option<&'nfa Edge<L>> {
let index = self.index;
if index == usize::MAX {
return None;
}
let next_index = index + 1;
if next_index >= self.edges.len() || self.edges[next_index].from != self.from {
self.index = usize::MAX;
} else {
self.index = next_index;
}
Some(&self.edges[index])
}
}
impl Test {
pub fn char(c: char) -> Test {
let c = c as u32;
Test { start: c, end: c + 1 }
}
pub fn inclusive_range(s: char, e: char) -> Test {
Test { start: s as u32, end: e as u32 + 1 }
}
pub fn exclusive_range(s: char, e: char) -> Test {
Test { start: s as u32, end: e as u32 }
}
pub fn is_char(self) -> bool {
self.len() == 1
}
pub fn len(self) -> u32 {
self.end - self.start
}
pub fn contains_u32(self, c: u32) -> bool {
c >= self.start && c < self.end
}
pub fn contains_char(self, c: char) -> bool {
self.contains_u32(c as u32)
}
pub fn intersects(self, r: Test) -> bool {
!self.is_empty() && !r.is_empty() && (
self.contains_u32(r.start) || r.contains_u32(self.start))
}
pub fn is_disjoint(self, r: Test) -> bool {
!self.intersects(r)
}
pub fn is_empty(self) -> bool {
self.start == self.end
}
}
impl From<ClassRange> for Test {
fn from(range: ClassRange) -> Test {
Test::inclusive_range(range.start, range.end)
}
}
impl Debug for Test {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
match (char::from_u32(self.start), char::from_u32(self.end)) {
(Some(start), Some(end)) => {
if self.is_char() {
if ".[]()?+*!".contains(start) {
write!(fmt, "\\{}", start)
} else {
write!(fmt, "{}", start)
}
} else {
write!(fmt, "[{:?}..{:?}]", start, end)
}
}
_ => {
write!(fmt, "[{:?}..{:?}]", self.start, self.end)
}
}
}
}
impl Debug for NFAStateIndex {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
write!(fmt, "NFA{}", self.0)
}
}
impl<L:Debug> Debug for Edge<L> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
write!(fmt, "{:?} -{:?}-> {:?}", self.from, self.label, self.to)
}
}