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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//! Types and traits that let you write extensions for chumsky.
//!
//! Chumsky is a complicated crate that performs many internal optimizations to keep your parsers fast. These
//! optimizations mean that chumsky's core is rapidly changing, difficult to work with, and reveals a lot of
//! often-superfluous implementation details that are necessary to account for.
//!
//! In short: it's not a good basis for a stable public API upon which to build a parser ecosystem.
//!
//! To get around this problem, chumsky provides an extension interface (the contents of this module). This is a set of
//! types, traits, and functions that we've decided that we're comfortable providing long-term support for even if
//! the core of chumsky changes in an otherwise breaking manner in the future.
//!
//! The extension API is versioned. See the [`v1`] module for the current implementation of the API.
//!
//! # Example
//!
//! ```
//! use chumsky::{
//! prelude::*,
//! error::LabelError,
//! input::InputRef,
//! extension::v1::{ExtParser, Ext},
//! DefaultExpected,
//! };
//!
//! // An example extension parser that expects a null byte.
//! pub struct Null_;
//!
//! // We implement `ExtParser` for our null byte parser, plugging us into the chumsky ecosystem
//! impl<'src, I, E> ExtParser<'src, I, (), E> for Null_
//! where
//! I: Input<'src, Token = u8>,
//! E: extra::ParserExtra<'src, I>,
//! {
//! fn parse(&self, inp: &mut InputRef<'src, '_, I, E>) -> Result<(), E::Error> {
//! let before = inp.cursor();
//! match inp.next_maybe().as_deref() {
//! // The next token was a null byte, meaning that parsing was successful
//! Some(b'\0') => Ok(()),
//! // The next token was something that wasn't a null byte, generate an error instead
//! found => Err(LabelError::<I, _>::expected_found(
//! // Expected a null byte
//! [DefaultExpected::Token(b'\0'.into())],
//! // Found whatever the token was instead
//! found.copied().map(Into::into),
//! // The span of the error is the span of the token that was found instead
//! inp.span_since(&before),
//! )),
//! }
//! }
//! }
//!
//! // Finally, we create an easy way to name the parser type for users
//! pub type Null = Ext<Null_>;
//!
//! // It's also conventional to create a function to conveniently use the parser primitive
//! pub fn null() -> Null {
//! Ext(Null_)
//! }
//!
//! // Let's give our parser a test!
//! fn make_parser<'src>() -> impl Parser<'src, &'src [u8], ()> {
//! null()
//! }
//!
//! assert_eq!(make_parser().parse(b"\0").into_result(), Ok(()));
//! assert!(make_parser().parse(b"!").has_errors());
//! assert!(make_parser().parse(b"").has_errors());
//! ```
use *;
/// Version 1 of the extension API.
///
/// Versioning the extension API allows us to make significant changes to it in the future without breaking crates that
/// depend on it.