rulex 0.4.4

DEPRECATED: Use pomsky instead. A new regular expression language
Documentation
use std::collections::HashMap;

use crate::{
    compile::{CompileResult, CompileState},
    error::{CompileError, ParseError},
    features::RulexFeatures,
    options::{CompileOptions, ParseOptions},
    repetition::RegexQuantifier,
    rule::Rule,
    span::Span,
};

#[derive(Clone)]
pub(crate) struct StmtExpr<'i> {
    stmt: Stmt<'i>,
    rule: Rule<'i>,
    pub(crate) span: Span,
}

#[derive(Clone)]
pub(crate) enum Stmt<'i> {
    Enable(BooleanSetting),
    Disable(BooleanSetting),
    Let(Let<'i>),
}

#[derive(Clone, PartialEq, Eq)]
pub(crate) enum BooleanSetting {
    Lazy,
}

#[derive(Clone)]
pub(crate) struct Let<'i> {
    name: &'i str,
    rule: Rule<'i>,
    pub(crate) name_span: Span,
}

impl<'i> Let<'i> {
    pub(crate) fn new(name: &'i str, rule: Rule<'i>, name_span: Span) -> Self {
        Self { name, rule, name_span }
    }

    pub(crate) fn name(&self) -> &'i str {
        self.name
    }
}

impl<'i> StmtExpr<'i> {
    pub(crate) fn new(stmt: Stmt<'i>, rule: Rule<'i>, span: Span) -> Self {
        Self { stmt, rule, span }
    }

    pub(crate) fn get_capturing_groups(
        &self,
        count: &mut u32,
        map: &'i mut HashMap<String, u32>,
        within_variable: bool,
    ) -> Result<(), CompileError> {
        if let Stmt::Let(l) = &self.stmt {
            l.rule.get_capturing_groups(count, map, true)?;
        }
        self.rule.get_capturing_groups(count, map, within_variable)
    }

    pub(crate) fn compile<'c>(
        &'c self,
        options: CompileOptions,
        state: &mut CompileState<'c, 'i>,
    ) -> CompileResult<'i> {
        match &self.stmt {
            Stmt::Enable(BooleanSetting::Lazy) => {
                let prev = state.default_quantifier;
                state.default_quantifier = RegexQuantifier::Lazy;
                let res = self.rule.comp(options, state)?;
                state.default_quantifier = prev;
                Ok(res)
            }
            Stmt::Disable(BooleanSetting::Lazy) => {
                let prev = state.default_quantifier;
                state.default_quantifier = RegexQuantifier::Greedy;
                let res = self.rule.comp(options, state)?;
                state.default_quantifier = prev;
                Ok(res)
            }
            Stmt::Let(r#let) => {
                state.variables.push((r#let.name, &r#let.rule));
                let res = self.rule.comp(options, state)?;
                state.variables.pop();
                Ok(res)
            }
        }
    }

    pub(crate) fn validate(&self, options: &ParseOptions) -> Result<(), ParseError> {
        match &self.stmt {
            Stmt::Enable(BooleanSetting::Lazy) => {
                options.allowed_features.require(RulexFeatures::LAZY_MODE, self.span)?;
            }
            Stmt::Disable(_) => {}
            Stmt::Let(l) => {
                options.allowed_features.require(RulexFeatures::VARIABLES, l.name_span)?;
                l.rule.validate(options)?;
            }
        }

        self.rule.validate(options)
    }
}

#[cfg(feature = "dbg")]
impl std::fmt::Debug for StmtExpr<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        struct DisplayDebug<T>(T);
        impl<T: std::fmt::Display> std::fmt::Debug for DisplayDebug<T> {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                write!(f, "{}", self.0)
            }
        }

        let mut x = f.debug_tuple("StmtExpr");
        let mut x = &mut x;
        match &self.stmt {
            Stmt::Enable(BooleanSetting::Lazy) => x = x.field(&DisplayDebug("enable lazy")),
            Stmt::Disable(BooleanSetting::Lazy) => x = x.field(&DisplayDebug("disable lazy")),
            Stmt::Let(r#let) => x = x.field(r#let),
        }
        x.field(&self.rule).finish()
    }
}

#[cfg(feature = "dbg")]
impl std::fmt::Debug for Let<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "let {} = {:#?}", self.name, self.rule)
    }
}