use crate::lexer::nfa::{Nfa, NfaStateIndex, Noop, Other, START, StateKind, Test};
use std::cmp::max;
pub fn interpret<'text>(nfa: &Nfa, text: &'text str) -> Option<&'text str> {
let mut longest: Option<usize> = None;
let mut stack: Vec<(NfaStateIndex, usize)> = vec![(START, 0)];
while let Some((state, offset)) = stack.pop() {
match nfa.kind(state) {
StateKind::Accept => match longest {
None => longest = Some(offset),
Some(o) => longest = Some(max(o, offset)),
},
StateKind::Reject => {
continue;
}
StateKind::Neither => {}
}
for edge in nfa.edges::<Noop>(state) {
push(&mut stack, (edge.to, offset));
}
let ch = match text[offset..].chars().next() {
Some(ch) => ch, None => {
continue;
} };
let offset1 = offset + ch.len_utf8();
let mut tests = 0;
for edge in nfa.edges::<Test>(state) {
if edge.label.contains_char(ch) {
push(&mut stack, (edge.to, offset1));
tests += 1;
}
}
assert!(tests <= 1);
if tests == 0 {
for edge in nfa.edges::<Other>(state) {
push(&mut stack, (edge.to, offset1));
tests += 1;
}
assert!(tests <= 1);
}
}
longest.map(|offset| &text[..offset])
}
fn push<T: Eq>(v: &mut Vec<T>, t: T) {
if !v.contains(&t) {
v.push(t);
}
}