1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//! ABNF grammars as a testing oracle.
//!
//! Parses ABNF grammars (RFC 5234 as amended by RFC 7405 and Errata 2968 and 3076), decides
//! whether an input string is in the language of a rule, and generates strings that are.
//!
//! The emphasis is on being *right*, not fast. Alternation is unordered, backtracking is full,
//! ambiguity is tolerated, and the recognizer computes the set of all end positions an element
//! can reach rather than committing to the first branch that matches. What this crate is
//! deliberately **not** is listed in `SCOPE.md` 3: no parse trees, no ambiguity detection, no
//! PEG or regex semantics, no byte-oriented matching, and no performance promises.
//!
//! # Shape of the API
//!
//! Three types, used in order:
//!
//! 1. [`Grammar`] — the syntactic layer. What the parser produces: definitions as written.
//! 2. `CheckedGrammar` — the semantic layer, produced by `Grammar::check`. Incremental
//! alternatives are merged, names are resolved, and the analyses the recognizer and
//! generator rely on have been run. It is the only route to either of them, so there is no
//! way to recognize against a grammar whose structure was never validated.
//! 3. `Recognizer` / `Generator` — bound to a checked grammar and a start rule.
//!
//! # Example
//!
//! ```
//! use abnf_oracle::{Generator, Grammar, Recognizer};
//!
//! // A grammar, as it would appear in an RFC.
//! let source = concat!(
//! "full-date = date-fullyear \"-\" date-month \"-\" date-mday\r\n",
//! "date-fullyear = 4DIGIT\r\n",
//! "date-month = 2DIGIT\r\n",
//! "date-mday = 2DIGIT\r\n",
//! );
//!
//! // Parse, then check. `check` merges incremental definitions, resolves every name and runs
//! // the analyses; it is the only way to reach a recognizer or a generator.
//! let grammar = Grammar::parse(source)
//! .expect("valid ABNF")
//! .check()
//! .expect("no structural errors");
//!
//! // Recognize.
//! assert!(Recognizer::new(&grammar, "2026-09-20").accepts("full-date").unwrap());
//! assert!(!Recognizer::new(&grammar, "20260920").accepts("full-date").unwrap());
//!
//! // Generate. The same seed always gives the same string.
//! let mut generator = Generator::new(&grammar, 42);
//! let produced = generator.generate("full-date").expect("generates");
//!
//! // What the generator produces, the recognizer accepts.
//! assert!(Recognizer::new(&grammar, &produced).accepts("full-date").unwrap());
//! ```
//!
//! # Errors are not rejections
//!
//! A limit, a prose value or an unrepresentable terminal makes a question *unanswerable*, which
//! is different from answering "no". Every such case is an `Err`, never `Ok(false)`, so a
//! caller can never mistake "could not decide" for "does not match".
pub use ;
pub use CheckedGrammar;
pub use ;
pub use ;
pub use ;