use std::collections::HashMap;
use crate::{
alternation::Alternation,
boundary::Boundary,
char_class::CharClass,
compile::{CompileResult, CompileState},
error::{CompileError, CompileErrorKind, ParseError, ParseErrorKind},
grapheme::Grapheme,
group::Group,
literal::Literal,
lookaround::Lookaround,
options::{CompileOptions, ParseOptions},
range::Range,
reference::Reference,
repetition::Repetition,
span::Span,
stmt::StmtExpr,
var::Variable,
};
#[derive(Clone)]
#[non_exhaustive]
pub(crate) enum Rule<'i> {
Literal(Literal<'i>),
CharClass(CharClass),
Grapheme(Grapheme),
Group(Group<'i>),
Alternation(Alternation<'i>),
Repetition(Box<Repetition<'i>>),
Boundary(Boundary),
Lookaround(Box<Lookaround<'i>>),
Variable(Variable<'i>),
Reference(Reference<'i>),
Range(Range),
StmtExpr(Box<StmtExpr<'i>>),
}
impl<'i> Rule<'i> {
pub(crate) fn span(&self) -> Span {
match self {
Rule::Literal(l) => l.span,
Rule::CharClass(c) => c.span,
Rule::Grapheme(g) => g.span,
Rule::Group(g) => g.span,
Rule::Alternation(a) => a.span,
Rule::Repetition(r) => r.span,
Rule::Boundary(b) => b.span,
Rule::Lookaround(l) => l.span,
Rule::Variable(v) => v.span,
Rule::Reference(r) => r.span,
Rule::Range(r) => r.span,
Rule::StmtExpr(m) => m.span,
}
}
pub(crate) fn negate(&mut self) -> Result<(), ParseErrorKind> {
match self {
Rule::Literal(_)
| Rule::Grapheme(_)
| Rule::Group(_)
| Rule::Alternation(_)
| Rule::Variable(_)
| Rule::Reference(_)
| Rule::Range(_)
| Rule::StmtExpr(_) => Err(ParseErrorKind::UnallowedNot),
Rule::CharClass(c) => c.negate(),
Rule::Repetition(r) => r.rule.negate(),
Rule::Boundary(b) => b.negate(),
Rule::Lookaround(l) => l.negate(),
}
}
pub(crate) fn get_capturing_groups(
&self,
count: &mut u32,
map: &mut HashMap<String, u32>,
within_variable: bool,
) -> Result<(), CompileError> {
match self {
Rule::Literal(_) => {}
Rule::CharClass(_) => {}
Rule::Grapheme(_) => {}
Rule::Group(g) => g.get_capturing_groups(count, map, within_variable)?,
Rule::Alternation(a) => a.get_capturing_groups(count, map, within_variable)?,
Rule::Repetition(r) => r.get_capturing_groups(count, map, within_variable)?,
Rule::Boundary(_) => {}
Rule::Lookaround(l) => l.get_capturing_groups(count, map, within_variable)?,
Rule::Variable(_) => {}
Rule::Reference(r) => {
if within_variable {
return Err(CompileErrorKind::ReferenceInLet.at(r.span));
}
}
Rule::Range(_) => {}
Rule::StmtExpr(m) => m.get_capturing_groups(count, map, within_variable)?,
}
Ok(())
}
pub(crate) fn comp<'c>(
&'c self,
options: CompileOptions,
state: &mut CompileState<'c, 'i>,
) -> CompileResult<'i> {
match self {
Rule::Literal(l) => l.compile(),
Rule::CharClass(c) => c.compile(options),
Rule::Group(g) => g.compile(options, state),
Rule::Grapheme(g) => g.compile(options),
Rule::Alternation(a) => a.compile(options, state),
Rule::Repetition(r) => r.compile(options, state),
Rule::Boundary(b) => b.compile(),
Rule::Lookaround(l) => l.compile(options, state),
Rule::Variable(v) => v.compile(options, state),
Rule::Reference(r) => r.compile(options, state),
Rule::Range(r) => r.compile(),
Rule::StmtExpr(m) => m.compile(options, state),
}
}
pub(crate) fn validate(&self, options: &ParseOptions) -> Result<(), ParseError> {
match self {
Rule::Literal(_) => {}
Rule::CharClass(_) => {}
Rule::Grapheme(g) => g.validate(options)?,
Rule::Group(g) => g.validate(options)?,
Rule::Alternation(a) => a.validate(options)?,
Rule::Repetition(r) => r.validate(options)?,
Rule::Boundary(b) => b.validate(options)?,
Rule::Lookaround(l) => l.validate(options)?,
Rule::Variable(_) => {}
Rule::Reference(r) => r.validate(options)?,
Rule::Range(r) => r.validate(options)?,
Rule::StmtExpr(s) => s.validate(options)?,
}
Ok(())
}
}
#[cfg(feature = "dbg")]
impl core::fmt::Debug for Rule<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Rule::Literal(arg0) => arg0.fmt(f),
Rule::CharClass(arg0) => arg0.fmt(f),
Rule::Grapheme(arg0) => arg0.fmt(f),
Rule::Group(arg0) => arg0.fmt(f),
Rule::Alternation(arg0) => arg0.fmt(f),
Rule::Repetition(arg0) => arg0.fmt(f),
Rule::Boundary(arg0) => arg0.fmt(f),
Rule::Lookaround(arg0) => arg0.fmt(f),
Rule::Variable(arg0) => arg0.fmt(f),
Rule::Reference(arg0) => arg0.fmt(f),
Rule::Range(arg0) => arg0.fmt(f),
Rule::StmtExpr(arg0) => arg0.fmt(f),
}
}
}