Builds and holds the one-pass classification (and table, when eligible) of a byte-program.
More...
|
| constexpr | onepass (const byte_program &bp, std::size_t max_bytes=max_table_bytes) |
| |
| bool | eligible () const |
| |
| const std::string & | bail_reason () const |
| |
| std::size_t | node_count () const |
| |
| std::uint16_t | num_classes () const |
| |
| const std::vector< onepass_node > & | nodes () const |
| |
| std::uint8_t | class_of (std::uint8_t byte) const |
| | The byte-class of byte, for a runtime that walks this table.
|
| |
| std::size_t | slot_count () const |
| | The number of capture slots (group 0 start/end plus each group's).
|
| |
| template<typename OutSlots > |
| bool | extract (std::string_view text, std::size_t s, std::size_t e, OutSlots &out) const |
| | Fills out with the capture slots of the one-pass match on text[s, e) — the single left-to- right pass the whole arc is for, no thread lists. text is the full subject (never a substring: assertions look at s - 1 and e). Anchored at s; this is fullmatch-on-span (the span the router located): it consumes to e and requires the run to accept exactly there. \ref real::npos marks a slot no edge wrote. Returns false (leaving out unspecified) if the pattern is ineligible or the span does not in fact match — which the caller has already ruled out for a router-supplied span.
|
| |
| bool | asserts_hold (std::uint32_t mask, std::string_view text, std::size_t pos) const |
| | Whether every assertion in mask (a set of assert_kind bits) holds at pos in text.
|
| |
|
| static constexpr std::uint32_t | no_node {0xFFFFFFFFU} |
| | "No node yet" sentinel in the pc->node map.
|
| |
| static constexpr std::size_t | max_nodes {65000} |
| | Node cap (RE2's), a memory/DoS bound.
|
| |
| static constexpr std::size_t | max_slots {10} |
| | Slot-pointer cap: group 0 + four user groups.
|
| |
| static constexpr std::size_t | minimize_buckets {4096} |
| | Hash buckets for the Moore-refinement dedup.
|
| |
| static constexpr std::size_t | max_table_bytes {8U << 20} |
| | Table-memory cap (~8 MB): larger declines to the VM.
|
| |
|
| constexpr void | bail (const char *reason, std::int32_t node=-1, std::int32_t klass=-1, std::int32_t pc=-1) |
| | Reject as not one-pass, recording a category and the offending node / byte-class / pc (kept as integers rather than formatted into the string so the whole builder stays constexpr — a constexpr real::regex embeds an (empty) one-pass table in its literal state).
|
| |
| constexpr std::uint32_t | node_of (std::int32_t pc, std::vector< std::int32_t > &queue) |
| | Get-or-create the node whose entry pc is pc, enqueueing a fresh one for the flood.
|
| |
| constexpr void | build (const byte_program &bp) |
| |
| constexpr void | minimize () |
| | Moore partition refinement of the one-pass automaton: merge nodes that are behaviourally identical (same accept + match captures, and for every byte-class the same edge — target partition AND capture mask). The one-pass graph has cycles (\w+ loops), so bottom-up hash-consing is not enough; refinement to a fixpoint is. Merged nodes have identical capture masks by construction, so captures are unchanged. The dense per-node edge table is preserved, so extract's O(1) lookup is unchanged — the whole point of not going sparse.
|
| |
| constexpr void | build_edges (std::int32_t pc, std::uint64_t cap_mask, std::uint32_t assert_mask, std::vector< char > &on_path, std::uint32_t node_id, std::vector< std::int32_t > &queue) |
| | Walk the epsilon-closure from pc, writing this node's edges. on_path detects epsilon cycles (a nullable loop => not one-pass). cap_mask accumulates the slots crossed so far.
|
| |
Builds and holds the one-pass classification (and table, when eligible) of a byte-program.
Construction floods the program from the start: for each node it walks the epsilon-closure (split, jump, save) accumulating the capture mask, and every consuming instruction (byte, klass) writes the edge for its byte-class(es). A byte-class written twice with a different edge, a second reachable match with different captures, or an epsilon cycle (a nullable loop) each means not one-pass and the build bails with a human-readable reason. Node and slot counts are capped, so a pathological program is rejected rather than explored without bound.
Definition at line 74 of file onepass.hpp.
template<typename OutSlots >
| bool real::detail::onepass::extract |
( |
std::string_view |
text, |
|
|
std::size_t |
s, |
|
|
std::size_t |
e, |
|
|
OutSlots & |
out |
|
) |
| const |
|
inline |
Fills out with the capture slots of the one-pass match on text[s, e) — the single left-to- right pass the whole arc is for, no thread lists. text is the full subject (never a substring: assertions look at s - 1 and e). Anchored at s; this is fullmatch-on-span (the span the router located): it consumes to e and requires the run to accept exactly there. \ref real::npos marks a slot no edge wrote. Returns false (leaving out unspecified) if the pattern is ineligible or the span does not in fact match — which the caller has already ruled out for a router-supplied span.
- Parameters
-
| [in] | text | The full subject. |
| [in] | s | Match start (anchor). |
| [in] | e | Match end (the run must accept here). |
| [out] | out | Capture slots, sized to slot_count. |
Definition at line 151 of file onepass.hpp.
| constexpr void real::detail::onepass::minimize |
( |
| ) |
|
|
inlineconstexprprivate |
Moore partition refinement of the one-pass automaton: merge nodes that are behaviourally identical (same accept + match captures, and for every byte-class the same edge — target partition AND capture mask). The one-pass graph has cycles (\w+ loops), so bottom-up hash-consing is not enough; refinement to a fixpoint is. Merged nodes have identical capture masks by construction, so captures are unchanged. The dense per-node edge table is preserved, so extract's O(1) lookup is unchanged — the whole point of not going sparse.
Definition at line 299 of file onepass.hpp.