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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//! The [`Pass`] trait: a single stage in a parse schedule.
use crateOutcome;
use crateSpan;
/// One stage of a parse schedule.
///
/// A pass is a pure function from a source region plus its context to an
/// [`Outcome`]: the region either expands into smaller child regions, is
/// accepted as parsed, or fails (later passes may retry it).
///
/// `increparse` is deliberately combinator-agnostic: a pass can wrap any
/// parsing technique — `nom`, `chumsky`, a PEG, regexes, or hand-rolled
/// scanning — behind this trait. The engine only cares about the outcome.
///
/// # Contract
///
/// * Passes must be pure: they must not mutate shared state and must produce
/// the same output for the same `(source, span, ctx)` input.
/// * Every child span returned from [`Outcome::Expand`] must be contained in
/// the input span and on the same source revision. By default a child may
/// cover its parent exactly; with
/// [`EngineConfig::enforce_shrink`](crate::EngineConfig::enforce_shrink)
/// it must be strictly smaller. The engine rejects outcomes that violate
/// this, marking the node [`Failed`](crate::Status::Failed).
/// * Passes must be `Send + Sync` so the engine can run batches on any
/// [`Executor`](crate::Executor).
///
/// # Examples
///
/// ```
/// use increparse::{Outcome, Pass, Span};
///
/// /// Accepts any region whose text starts with "ok".
/// struct AcceptOk;
///
/// impl Pass for AcceptOk {
/// type Ctx = ();
///
/// fn parse(&self, source: &str, span: Span, _ctx: &()) -> Outcome<()> {
/// let text = &source[span.to_range()];
/// if text.starts_with("ok") {
/// Outcome::Done
/// } else {
/// Outcome::Failed
/// }
/// }
/// }
/// ```
/// Creates a pass from a closure — no struct, no impl block.
///
/// The closure receives the same arguments as [`Pass::parse`] and returns
/// the same [`Outcome`]; captures are allowed, which makes stateful passes
/// (counters, lookup tables) trivial. Passes built this way are named
/// `"PassFn"` in diagnostics.
///
/// # Examples
///
/// ```
/// use increparse::{pass_fn, Outcome, Pass, Span};
///
/// let accept = pass_fn(|_source: &str, _span, _ctx: &()| Outcome::Done);
/// assert!(matches!(accept.parse("abc", Span::new(0, 3, 0), &()), Outcome::Done));
/// ```
/// A [`Pass`] built from a closure. See [`pass_fn`].