fn expand_regex()

in cli/src/generate/prepare_grammar/expand_tokens.rs [196:298]


    fn expand_regex(&mut self, ast: &Ast, mut next_state_id: u32) -> Result<bool> {
        match ast {
            Ast::Empty(_) => Ok(false),
            Ast::Flags(_) => Err(Error::regex("Flags are not supported")),
            Ast::Literal(literal) => {
                self.push_advance(CharacterSet::Include(vec![literal.c]), next_state_id);
                Ok(true)
            }
            Ast::Dot(_) => {
                self.push_advance(CharacterSet::Exclude(vec!['\n']), next_state_id);
                Ok(true)
            }
            Ast::Assertion(_) => Err(Error::regex("Assertions are not supported")),
            Ast::Class(class) => match class {
                Class::Unicode(_) => {
                    Err(Error::regex("Unicode character classes are not supported"))
                }
                Class::Perl(class) => {
                    let mut chars = self.expand_perl_character_class(&class.kind);
                    if class.negated {
                        chars = chars.negate();
                    }
                    self.push_advance(chars, next_state_id);
                    Ok(true)
                }
                Class::Bracketed(class) => match &class.kind {
                    ClassSet::Item(item) => {
                        let mut chars = self.expand_character_class(&item)?;
                        if class.negated {
                            chars = chars.negate();
                        }
                        self.push_advance(chars, next_state_id);
                        Ok(true)
                    }
                    ClassSet::BinaryOp(_) => Err(Error::regex(
                        "Binary operators in character classes aren't supported",
                    )),
                },
            },
            Ast::Repetition(repetition) => match repetition.op.kind {
                RepetitionKind::ZeroOrOne => {
                    self.expand_zero_or_one(&repetition.ast, next_state_id)
                }
                RepetitionKind::OneOrMore => {
                    self.expand_one_or_more(&repetition.ast, next_state_id)
                }
                RepetitionKind::ZeroOrMore => {
                    self.expand_zero_or_more(&repetition.ast, next_state_id)
                }
                RepetitionKind::Range(RepetitionRange::Exactly(count)) => {
                    self.expand_count(&repetition.ast, count, next_state_id)
                }
                RepetitionKind::Range(RepetitionRange::AtLeast(min)) => {
                    if self.expand_zero_or_more(&repetition.ast, next_state_id)? {
                        self.expand_count(&repetition.ast, min, next_state_id)
                    } else {
                        Ok(false)
                    }
                }
                RepetitionKind::Range(RepetitionRange::Bounded(min, max)) => {
                    let mut result = self.expand_count(&repetition.ast, min, next_state_id)?;
                    for _ in min..max {
                        if result {
                            next_state_id = self.nfa.last_state_id();
                        }
                        if self.expand_zero_or_one(&repetition.ast, next_state_id)? {
                            result = true;
                        }
                    }
                    Ok(result)
                }
            },
            Ast::Group(group) => self.expand_regex(&group.ast, next_state_id),
            Ast::Alternation(alternation) => {
                let mut alternative_state_ids = Vec::new();
                for ast in alternation.asts.iter() {
                    if self.expand_regex(&ast, next_state_id)? {
                        alternative_state_ids.push(self.nfa.last_state_id());
                    } else {
                        alternative_state_ids.push(next_state_id);
                    }
                }
                alternative_state_ids.sort_unstable();
                alternative_state_ids.dedup();
                alternative_state_ids.retain(|i| *i != self.nfa.last_state_id());

                for alternative_state_id in alternative_state_ids {
                    self.push_split(alternative_state_id);
                }
                Ok(true)
            }
            Ast::Concat(concat) => {
                let mut result = false;
                for ast in concat.asts.iter().rev() {
                    if self.expand_regex(&ast, next_state_id)? {
                        result = true;
                        next_state_id = self.nfa.last_state_id();
                    }
                }
                Ok(result)
            }
        }
    }