REAL
Regular Expression Algorithmic Library — constexpr C++20 regex
Loading...
Searching...
No Matches
real::detail::reverse_dfa Class Reference

The start-finder companion to lazy_dfa. Given a match end, it finds the leftmost start (the design guide §7.6 contract). It runs the inverted program — the forward program's edges transposed, its consuming bytes kept — as a cached DFA over the text scanned right-to-left from the end, recording an accept each time it reaches the original start (reverse-kLongest: the furthest-back accept is the start). It needs no priority ordering — its states are plain unordered (sorted) PC sets and its rule is longest — so it is simpler than the forward pass. Dynamic only. More...

#include <lazy_dfa.hpp>

Collaboration diagram for real::detail::reverse_dfa:
[legend]

Public Member Functions

constexpr reverse_dfa (std::span< const instr > code, std::span< const char_class > classes, std::size_t budget=state_budget, const lazy_byte_alphabet *shared_alpha=nullptr, bool ascii_word=false, bool word_quit=false, std::size_t byte_budget=lazy_dfa_default_byte_budget)
 Builds the (initially empty) reverse DFA, transposing the program's edges as it goes.
 
bool eligible () const
 Whether the program can be represented at all (see compute_eligibility).
 
std::size_t bytes () const
 Bytes the cached states hold now, as the byte budget counts them.
 
std::size_t byte_flushes () const
 Flushes over this object's lifetime that the byte budget called, the state budget not reached.
 
std::size_t reverse_start (std::string_view text, std::size_t e, std::size_t resume, std::size_t *read=nullptr)
 The leftmost start of the match ending at e, not before resume. Scans the text backward from e over the inverted program, keeping the furthest-back position that reaches the program start (reverse-kLongest). Precondition: a match ends at e; eligible programs only.
 

Static Public Attributes

static constexpr std::uint32_t dead_state {0}
 The empty state: every transition from it stays here.
 
static constexpr std::uint32_t no_transition {0xFFFFFFFFU}
 A not-yet-computed cached transition.
 
static constexpr std::uint32_t quit_state {0xFFFFFFFEU}
 What resolve() gives when a Unicode word boundary meets a non-ASCII byte; never interned.
 
static constexpr std::size_t quit_pos {npos - 1U}
 What reverse_start() gives when its scan quit.
 
static constexpr std::size_t state_budget {65536}
 Cached states before a flush; the memory cap is lazy_dfa_byte_budget.
 

Private Member Functions

constexpr visit_marks & begin_visit ()
 Starts a closure computation on this DFA's marks.
 
std::uint8_t right_ctx_at (std::string_view text, std::size_t pos) const
 The right context of position pos in the whole text.
 
bool holds_left (assert_kind kind, std::uint8_t ctx, std::uint16_t key) const
 Whether an assertion that looks left holds, given the right context and the key to the left.
 
constexpr void rev_closure_look (std::vector< std::int32_t > &set, visit_marks &seen, std::uint8_t ctx, std::uint16_t key) const
 rev_closure for a program with position assertions: crossing back over an assertion needs it to hold at this position. One that looks only right is decided by ctx; one that looks left is decided by key when known, and otherwise stays in set as a pending pc that the closure does not cross until resolve reads the byte to the left.
 
std::uint32_t resolve (std::uint32_t state, std::uint16_t key)
 state with its pending assertions decided by key, the byte to the left (or the start): each that holds lets the closure continue past it. A state with nothing pending is its own resolution. Cached per (state, key).
 
std::uint32_t start_for (std::uint8_t ctx)
 The state that starts the backward scan at a match end with right context ctx: the backward closure of the forward match there.
 
std::uint32_t step_with (std::uint32_t state, std::uint8_t byte, std::uint8_t ctx)
 One backward step for a program with assertions, with the right context given rather than read from the byte's class: the step onto the text's last byte, where a newline is final.
 
std::size_t reverse_start_look (std::string_view text, std::size_t e, std::size_t resume, std::size_t *read)
 reverse_start for a program with position assertions: each position's state is resolved by the byte to its left before the accept test and the step, and the scan begins with the right context the whole text gives the match end.
 
constexpr void rev_closure (std::vector< std::int32_t > &set, visit_marks &seen) const
 Saturate set with its backward epsilon-closure, then sort it into a canonical key. Unordered by design: the reverse rule is longest, so priority carries no meaning here.
 
std::uint32_t step (std::uint32_t state, std::uint8_t byte)
 Transition state backward over byte, computing and caching the edge on first use.
 
bool consumes (std::int32_t pc, std::uint8_t byte) const
 Whether the instruction at pc is a consuming edge that accepts byte.
 
constexpr std::uint32_t intern (const std::vector< std::int32_t > &pcs)
 Intern a sorted pc-set into a state id (cached), recording whether it reaches the program start.
 
constexpr void flush ()
 Empty the cache back to the dead + start states (the eviction: bounded memory).
 

Static Private Member Functions

static constexpr bool is_pending (std::int32_t entry)
 Whether entry encodes an undecided assertion.
 
static constexpr bool looks_left (assert_kind kind)
 Whether kind needs the text to the left of the position (so backward it waits for the next byte); an assertion that looks only right is decided by the context.
 
static constexpr bool holds_right (assert_kind kind, std::uint8_t ctx)
 Whether an assertion that looks only right holds with right context ctx.
 
static constexpr void mark_context (std::vector< std::int32_t > &set, std::uint8_t ctx)
 Appends ctx to set as a negative sentinel when set holds a pending assertion: the same pcs resolve differently in another context, so the context is part of the state.
 

Private Attributes

std::span< const instr > code_
 The byte program, owned by the caller.
 
std::span< const char_class > classes_
 Its byte classes, likewise borrowed.
 
lazy_byte_alphabet alpha_
 Byte-to-class map; its count is the row stride.
 
bool eligible_ {false}
 dfa_representable's verdict, fixed at construction.
 
bool word_quit_ {false}
 Unicode word boundaries carried, quitting next to a non-ASCII byte.
 
bool quit_hit_ {false}
 Set by holds_left() inside one resolve(): that resolution is quit_state.
 
bool look_ {false}
 The program carries position assertions (the look paths).
 
std::array< std::uint8_t, 256 > class_ctx_ {}
 Class -> the right context a byte of it gives (look programs).
 
std::array< std::uint32_t, 16 > starts_ {}
 Right context -> start state, per flush (look programs).
 
std::int32_t match_pc_ {-1}
 The forward match pc — this pass's start; -1 when absent.
 
std::uint32_t start_state_ {0}
 Id of match_pc_'s backward closure, re-interned by each flush.
 
std::size_t budget_ {state_budget}
 Cached states tolerated before a flush.
 
visit_marks marks_ {}
 The pcs the closure being computed has entered (begin_visit).
 
std::size_t flushes_ {0}
 bumped by flush(); step()'s stale-state guard against a mid-call reset.
 
std::size_t byte_budget_ {lazy_dfa_default_byte_budget}
 Cached bytes tolerated before a flush.
 
std::size_t bytes_ {0}
 Bytes the cached states hold.
 
std::size_t byte_flushes_ {0}
 Flushes the byte budget called, the state budget not reached.
 
std::vector< std::int32_t > rev_eps_pool_
 transposed epsilon edges, CSR-packed.
 
std::vector< std::uint32_t > rev_eps_at_
 CSR offsets into rev_eps_pool_, size code+2.
 
std::vector< std::int32_t > rev_consume_pool_
 transposed consuming edges, CSR-packed.
 
std::vector< std::uint32_t > rev_consume_at_
 CSR offsets into rev_consume_pool_.
 
std::vector< std::int32_t > stack_
 The closures' work stack, a member to spare a heap block per call.
 
std::vector< std::vector< std::int32_t > > state_pcs_
 state id -> sorted pc-set.
 
std::vector< std::uint32_t > trans_
 flat [state*stride + class] -> next.
 
std::vector< char > state_has_start_
 state -> reaches the program start (an accept).
 
std::vector< std::uint8_t > state_pending_
 state -> holds a pending assertion (look programs).
 
std::vector< std::uint32_t > res_
 flat [state*(count+1) + key] -> resolved state (look programs).
 
pc_set_cache cache_
 pc-set -> state id, the memo behind intern.
 

Static Private Attributes

static constexpr std::uint8_t rctx_end {1}
 The position is the end of the text.
 
static constexpr std::uint8_t rctx_final_nl {8}
 The byte after it is a newline that ends the text.
 
static constexpr std::uint16_t key_unknown {0xFFFFU}
 Closing inside a step: the byte to the left is not read yet.
 
static constexpr std::int32_t pending_base {-17}
 An undecided assertion at pc pc is pending_base - pc.
 

Detailed Description

The start-finder companion to lazy_dfa. Given a match end, it finds the leftmost start (the design guide §7.6 contract). It runs the inverted program — the forward program's edges transposed, its consuming bytes kept — as a cached DFA over the text scanned right-to-left from the end, recording an accept each time it reaches the original start (reverse-kLongest: the furthest-back accept is the start). It needs no priority ordering — its states are plain unordered (sorted) PC sets and its rule is longest — so it is simpler than the forward pass. Dynamic only.

Constructor & Destructor Documentation

◆ reverse_dfa()

constexpr real::detail::reverse_dfa::reverse_dfa ( std::span< const instr >  code,
std::span< const char_class >  classes,
std::size_t  budget = state_budget,
const lazy_byte_alphabet *  shared_alpha = nullptr,
bool  ascii_word = false,
bool  word_quit = false,
std::size_t  byte_budget = lazy_dfa_default_byte_budget 
)
inlineexplicitconstexpr

Builds the (initially empty) reverse DFA, transposing the program's edges as it goes.

Parameters
[in]codeThe program's instruction stream (must outlive this object — held as a span).
[in]classesThe program's interned byte classes (likewise held as a span).
[in]budgetCached states before a flush; defaults to state_budget.
[in]shared_alphaA precomputed alphabet the caller shares per regex, or null to compute it here.
[in]ascii_wordWhether the program's word boundaries use ASCII word-ness: only then does one byte decide them. False, the default, declines any word boundary.
[in]word_quitWith Unicode word-ness, carry the word boundaries and quit next to a non-ASCII byte (see lazy_dfa's).
[in]byte_budgetBytes the cached states may hold before a flush; see lazy_dfa_byte_budget.

Member Function Documentation

◆ begin_visit()

constexpr visit_marks & real::detail::reverse_dfa::begin_visit ( )
inlineconstexprprivate

Starts a closure computation on this DFA's marks.

Returns
The marks, none entered.

◆ byte_flushes()

std::size_t real::detail::reverse_dfa::byte_flushes ( ) const
inline

Flushes over this object's lifetime that the byte budget called, the state budget not reached.

Returns
The count.

◆ bytes()

std::size_t real::detail::reverse_dfa::bytes ( ) const
inline

Bytes the cached states hold now, as the byte budget counts them.

Returns
The bytes.

◆ consumes()

bool real::detail::reverse_dfa::consumes ( std::int32_t  pc,
std::uint8_t  byte 
) const
inlineprivate

Whether the instruction at pc is a consuming edge that accepts byte.

Parameters
[in]pcProgram counter to test.
[in]byteThe byte offered to it.
Returns
True for a byte/klass op accepting it; false for any non-consuming op.

◆ eligible()

bool real::detail::reverse_dfa::eligible ( ) const
inline

Whether the program can be represented at all (see compute_eligibility).

Returns
False when the caller must find the start another way.

◆ holds_left()

bool real::detail::reverse_dfa::holds_left ( assert_kind  kind,
std::uint8_t  ctx,
std::uint16_t  key 
) const
inlineprivate

Whether an assertion that looks left holds, given the right context and the key to the left.

Parameters
[in]kindThe assertion.
[in]ctxThe position's right context.
[in]keyThe class of the byte before the position, or alpha_.count at the start of the text.
Returns
True when it holds.

◆ holds_right()

static constexpr bool real::detail::reverse_dfa::holds_right ( assert_kind  kind,
std::uint8_t  ctx 
)
inlinestaticconstexprprivate

Whether an assertion that looks only right holds with right context ctx.

Parameters
[in]kindThe assertion (\Z, $, (?m)$).
[in]ctxThe position's right context.
Returns
True when it holds.

◆ intern()

constexpr std::uint32_t real::detail::reverse_dfa::intern ( const std::vector< std::int32_t > &  pcs)
inlineconstexprprivate

Intern a sorted pc-set into a state id (cached), recording whether it reaches the program start.

Parameters
[in]pcsThe sorted pc-set.
Returns
Its state id, existing or freshly built; dead_state for an empty set.

◆ is_pending()

static constexpr bool real::detail::reverse_dfa::is_pending ( std::int32_t  entry)
inlinestaticconstexprprivate

Whether entry encodes an undecided assertion.

Parameters
[in]entryA set entry.
Returns
True for a pending assertion.

◆ looks_left()

static constexpr bool real::detail::reverse_dfa::looks_left ( assert_kind  kind)
inlinestaticconstexprprivate

Whether kind needs the text to the left of the position (so backward it waits for the next byte); an assertion that looks only right is decided by the context.

Parameters
[in]kindThe assertion.
Returns
True for \A, ^ and the word boundaries.

◆ mark_context()

static constexpr void real::detail::reverse_dfa::mark_context ( std::vector< std::int32_t > &  set,
std::uint8_t  ctx 
)
inlinestaticconstexprprivate

Appends ctx to set as a negative sentinel when set holds a pending assertion: the same pcs resolve differently in another context, so the context is part of the state.

Parameters
[in,out]setThe sorted pc-set.
[in]ctxIts position's right context.

◆ resolve()

std::uint32_t real::detail::reverse_dfa::resolve ( std::uint32_t  state,
std::uint16_t  key 
)
inlineprivate

state with its pending assertions decided by key, the byte to the left (or the start): each that holds lets the closure continue past it. A state with nothing pending is its own resolution. Cached per (state, key).

Parameters
[in]stateThe state.
[in]keyThe class of the byte before its position, or alpha_.count at the start.
Returns
The resolved state.

◆ rev_closure()

constexpr void real::detail::reverse_dfa::rev_closure ( std::vector< std::int32_t > &  set,
visit_marks &  seen 
) const
inlineconstexprprivate

Saturate set with its backward epsilon-closure, then sort it into a canonical key. Unordered by design: the reverse rule is longest, so priority carries no meaning here.

Parameters
[in,out]setThe pc-set to close over, in place.
[in,out]seenPer-pc visited marks, sized to the program.

◆ rev_closure_look()

constexpr void real::detail::reverse_dfa::rev_closure_look ( std::vector< std::int32_t > &  set,
visit_marks &  seen,
std::uint8_t  ctx,
std::uint16_t  key 
) const
inlineconstexprprivate

rev_closure for a program with position assertions: crossing back over an assertion needs it to hold at this position. One that looks only right is decided by ctx; one that looks left is decided by key when known, and otherwise stays in set as a pending pc that the closure does not cross until resolve reads the byte to the left.

Parameters
[in,out]setThe pc-set to close over, in place (sorted on return; unordered by design).
[in,out]seenPer-pc visited marks.
[in]ctxThe position's right context.
[in]keyThe byte to the left, or key_unknown.

◆ reverse_start()

std::size_t real::detail::reverse_dfa::reverse_start ( std::string_view  text,
std::size_t  e,
std::size_t  resume,
std::size_t *  read = nullptr 
)
inline

The leftmost start of the match ending at e, not before resume. Scans the text backward from e over the inverted program, keeping the furthest-back position that reaches the program start (reverse-kLongest). Precondition: a match ends at e; eligible programs only.

Parameters
[in]textSubject.
[in]eThe known match end.
[in]resumeLower bound the backward scan will not cross.
[out]readWhen not null, the bytes the scan read: it runs until its state dies or resume, past the start it returns.
Returns
The leftmost start at or after resume, or real::npos when none was reached.

◆ reverse_start_look()

std::size_t real::detail::reverse_dfa::reverse_start_look ( std::string_view  text,
std::size_t  e,
std::size_t  resume,
std::size_t *  read 
)
inlineprivate

reverse_start for a program with position assertions: each position's state is resolved by the byte to its left before the accept test and the step, and the scan begins with the right context the whole text gives the match end.

Parameters
[in]textSubject.
[in]eThe known match end.
[in]resumeLower bound the backward scan will not cross.
[out]readAs reverse_start's.
Returns
The leftmost start at or after resume, or real::npos.

◆ right_ctx_at()

std::uint8_t real::detail::reverse_dfa::right_ctx_at ( std::string_view  text,
std::size_t  pos 
) const
inlineprivate

The right context of position pos in the whole text.

Parameters
[in]textThe subject.
[in]posThe position.
Returns
Its context bits.

◆ start_for()

std::uint32_t real::detail::reverse_dfa::start_for ( std::uint8_t  ctx)
inlineprivate

The state that starts the backward scan at a match end with right context ctx: the backward closure of the forward match there.

Parameters
[in]ctxThe match end's right context.
Returns
Its state id.

◆ step()

std::uint32_t real::detail::reverse_dfa::step ( std::uint32_t  state,
std::uint8_t  byte 
)
inlineprivate

Transition state backward over byte, computing and caching the edge on first use.

Parameters
[in]stateThe current state id.
[in]byteThe byte consumed, read right-to-left.
Returns
The predecessor state, or dead_state when nothing reaches back through byte.

◆ step_with()

std::uint32_t real::detail::reverse_dfa::step_with ( std::uint32_t  state,
std::uint8_t  byte,
std::uint8_t  ctx 
)
inlineprivate

One backward step for a program with assertions, with the right context given rather than read from the byte's class: the step onto the text's last byte, where a newline is final.

Parameters
[in]stateThe current (resolved) state.
[in]byteThe byte consumed.
[in]ctxThe right context of the new position.
Returns
The predecessor state (not cached).

The documentation for this class was generated from the following file: