use crate::{
compile::CompileResult,
error::{ParseError, ParseErrorKind},
features::RulexFeatures,
options::ParseOptions,
regex::Regex,
span::Span,
};
#[derive(Clone, Copy, PartialEq, Eq)]
pub(crate) struct Boundary {
kind: BoundaryKind,
pub(crate) span: Span,
}
impl Boundary {
pub(crate) fn new(kind: BoundaryKind, span: Span) -> Self {
Boundary { kind, span }
}
pub(crate) fn negate(&mut self) -> Result<(), ParseErrorKind> {
match self.kind {
BoundaryKind::Start | BoundaryKind::End => Err(ParseErrorKind::UnallowedNot),
BoundaryKind::NotWord => Err(ParseErrorKind::UnallowedDoubleNot),
BoundaryKind::Word => {
self.kind = BoundaryKind::NotWord;
Ok(())
}
}
}
}
impl Boundary {
pub(crate) fn compile(&self) -> CompileResult<'static> {
Ok(Regex::Boundary(self.kind))
}
pub(crate) fn validate(&self, options: &ParseOptions) -> Result<(), ParseError> {
options.allowed_features.require(RulexFeatures::BOUNDARIES, self.span)
}
}
#[cfg(feature = "dbg")]
impl core::fmt::Debug for Boundary {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self.kind {
BoundaryKind::Start => write!(f, "<%"),
BoundaryKind::Word => write!(f, "%"),
BoundaryKind::NotWord => write!(f, "!%"),
BoundaryKind::End => write!(f, "%>"),
}
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "dbg", derive(Debug))]
pub(crate) enum BoundaryKind {
Start,
Word,
NotWord,
End,
}
impl BoundaryKind {
pub(crate) fn codegen(&self, buf: &mut String) {
match self {
BoundaryKind::Start => buf.push('^'),
BoundaryKind::Word => buf.push_str("\\b"),
BoundaryKind::NotWord => buf.push_str("\\B"),
BoundaryKind::End => buf.push('$'),
}
}
}