Skip to main content

has_disjoint_class_separator

Function has_disjoint_class_separator 

Source
pub(super) fn has_disjoint_class_separator(
    prefix: &Hir,
    literals: &[Literal],
) -> bool
Expand description

Return true when an edge of prefix provides a required separator between the start of a match and each literal candidate.

More precisely, this looks at the first and last consuming children of a top-level concatenation. One of those children must be either a character class or a repetition of a character class that matches at least once. Let that child be S. This returns true when both of the following hold:

  • S is disjoint from everything consumed by the other children in prefix.
  • S is disjoint from every literal in literals.

In that case, S acts as a separator whose characters cannot be mistaken for characters belonging to either the rest of the prefix or a literal candidate. A reverse search therefore cannot slide S across either one and produce a later match start from an earlier literal candidate.

For example, consider this prefix and literal:

prefix  = \w+\s+
literal = Holmes

The trailing \s+ is required, is disjoint from \w+ and cannot match anything in Holmes. Thus this proves the reverse suffix optimization safe for \w+\s+Holmes. It also works with multiple literals, such as Holmes and Watson, provided the separator is disjoint from all of them.

The separator may instead be the first consuming child:

prefix  = \s[A-Za-z]{0,12}
literal = ing

Here, the leading \s is disjoint from both [A-Za-z]{0,12} and ing.

This returns false when the possible separator is optional, overlaps another prefix component or can match a character in any literal. For example, neither \s* in [A-Za-z]*\s* nor \w+ in \w+\w+ provides the required separator.