use crate::regex::Regex;
use std::fmt;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Pattern {
pub head: Regex,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Match {
Solved,
Empty,
}
impl Pattern {
#[must_use]
pub fn closed(r: Regex) -> Self {
Self { head: r }
}
#[must_use]
pub fn lit(s: &str) -> Self {
Self::closed(Regex::literal(s))
}
pub fn raw(s: impl AsRef<str>) -> Self {
Self::closed(Regex::literal(&clean(s.as_ref())))
}
#[must_use]
pub fn bottom() -> Self {
Self::closed(Regex::Empty)
}
#[must_use]
pub fn as_regex(&self) -> &Regex {
&self.head
}
#[must_use]
pub fn unify(&self, other: &Self) -> Match {
if self.head.has_intersection(&other.head) {
Match::Solved
} else {
Match::Empty
}
}
#[must_use]
pub fn subset(&self, other: &Self) -> bool {
self.head.subset(&other.head)
}
}
fn clean(s: &str) -> String {
let s = s.trim();
let s = s
.strip_prefix('\'')
.and_then(|x| x.strip_suffix('\''))
.unwrap_or(s);
s.chars().filter(|c| !c.is_whitespace()).collect()
}
impl fmt::Display for Pattern {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.head.literal_value() {
Some(s) => write!(f, "{s}"),
None => write!(f, "{}", self.head),
}
}
}