pomsky 0.12.0

A new regular expression language
Documentation
use pomsky_syntax::exprs::{Rule, Variable};

use crate::{
    compile::{CompileResult, CompileState},
    diagnose::CompileErrorKind,
    features::PomskyFeatures,
    options::CompileOptions,
};

use super::Compile;

impl Compile for Variable {
    fn compile<'c>(
        &'c self,
        options: CompileOptions,
        state: &mut CompileState<'c>,
    ) -> CompileResult {
        let rule = state
            .variables
            .iter()
            .enumerate()
            .rev()
            .find(|&(i, &(name, _))| name == self.name && !state.current_vars.contains(&i));

        if let Some((i, &(_, rule))) = rule {
            match rule {
                Rule::Boundary(_) => {
                    options.allowed_features.require(PomskyFeatures::BOUNDARIES, self.span)?;
                }
                Rule::Grapheme => {
                    options.allowed_features.require(PomskyFeatures::GRAPHEME, self.span)?;
                }
                _ => {}
            }

            state.current_vars.insert(i);
            let res = rule.compile(options, state)?;
            state.current_vars.remove(&i);
            Ok(res)
        } else {
            let recursive_rule = state.variables.iter().rev().find(|&&(name, _)| name == self.name);
            if recursive_rule.is_some() {
                Err(CompileErrorKind::RecursiveVariable.at(self.span))
            } else {
                Err(CompileErrorKind::UnknownVariable {
                    found: self.name.clone().into(),
                    #[cfg(feature = "suggestions")]
                    similar: pomsky_syntax::find_suggestion(
                        &self.name,
                        state.variables.iter().map(|&(var, _)| var),
                    ),
                }
                .at(self.span))
            }
        }
    }
}