/rust/registry/src/index.crates.io-1949cf8c6b5b557f/nom-8.0.0/src/character/mod.rs
Line | Count | Source |
1 | | //! Character specific parsers and combinators |
2 | | //! |
3 | | //! Functions recognizing specific characters |
4 | | |
5 | | use core::marker::PhantomData; |
6 | | |
7 | | use crate::error::ErrorKind; |
8 | | use crate::FindToken; |
9 | | use crate::IsStreaming; |
10 | | use crate::Mode; |
11 | | use crate::{error::ParseError, AsChar, Err, IResult, Input, Needed, Parser}; |
12 | | |
13 | | #[cfg(test)] |
14 | | mod tests; |
15 | | |
16 | | pub mod complete; |
17 | | pub mod streaming; |
18 | | |
19 | | #[inline] |
20 | | #[doc(hidden)] |
21 | | #[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_alpha`")] |
22 | 0 | pub fn is_alphabetic(chr: u8) -> bool { |
23 | 0 | matches!(chr, 0x41..=0x5A | 0x61..=0x7A) |
24 | 0 | } |
25 | | |
26 | | #[inline] |
27 | | #[doc(hidden)] |
28 | | #[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_dec_digit`")] |
29 | 0 | pub fn is_digit(chr: u8) -> bool { |
30 | 0 | matches!(chr, 0x30..=0x39) |
31 | 0 | } |
32 | | |
33 | | #[inline] |
34 | | #[doc(hidden)] |
35 | | #[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_hex_digit`")] |
36 | 0 | pub fn is_hex_digit(chr: u8) -> bool { |
37 | 0 | matches!(chr, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66) |
38 | 0 | } |
39 | | |
40 | | #[inline] |
41 | | #[doc(hidden)] |
42 | | #[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_oct_digit`")] |
43 | 0 | pub fn is_oct_digit(chr: u8) -> bool { |
44 | 0 | matches!(chr, 0x30..=0x37) |
45 | 0 | } |
46 | | |
47 | | /// Tests if byte is ASCII binary digit: 0-1 |
48 | | /// |
49 | | /// # Example |
50 | | /// |
51 | | /// ``` |
52 | | /// # use nom::character::is_bin_digit; |
53 | | /// assert_eq!(is_bin_digit(b'a'), false); |
54 | | /// assert_eq!(is_bin_digit(b'2'), false); |
55 | | /// assert_eq!(is_bin_digit(b'0'), true); |
56 | | /// assert_eq!(is_bin_digit(b'1'), true); |
57 | | /// ``` |
58 | | #[inline] |
59 | 0 | pub fn is_bin_digit(chr: u8) -> bool { |
60 | 0 | matches!(chr, 0x30..=0x31) |
61 | 0 | } |
62 | | |
63 | | #[inline] |
64 | | #[doc(hidden)] |
65 | | #[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_alphanum`")] |
66 | 0 | pub fn is_alphanumeric(chr: u8) -> bool { |
67 | 0 | AsChar::is_alphanum(chr) |
68 | 0 | } |
69 | | |
70 | | #[inline] |
71 | | #[doc(hidden)] |
72 | | #[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_space`")] |
73 | 0 | pub fn is_space(chr: u8) -> bool { |
74 | 0 | chr == b' ' || chr == b'\t' |
75 | 0 | } |
76 | | |
77 | | #[inline] |
78 | | #[doc(hidden)] |
79 | | #[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_newline`")] |
80 | 0 | pub fn is_newline(chr: u8) -> bool { |
81 | 0 | chr == b'\n' |
82 | 0 | } |
83 | | |
84 | | /// Recognizes one character. |
85 | | /// |
86 | | /// # Example |
87 | | /// |
88 | | /// ``` |
89 | | /// # use nom::{Err, error::{ErrorKind, Error}, Needed, IResult}; |
90 | | /// # use nom::character::streaming::char; |
91 | | /// fn parser(i: &str) -> IResult<&str, char> { |
92 | | /// char('a')(i) |
93 | | /// } |
94 | | /// assert_eq!(parser("abc"), Ok(("bc", 'a'))); |
95 | | /// assert_eq!(parser("bc"), Err(Err::Error(Error::new("bc", ErrorKind::Char)))); |
96 | | /// assert_eq!(parser(""), Err(Err::Incomplete(Needed::new(1)))); |
97 | | /// ``` |
98 | 0 | pub fn char<I, Error: ParseError<I>>(c: char) -> impl Parser<I, Output = char, Error = Error> |
99 | 0 | where |
100 | 0 | I: Input, |
101 | 0 | <I as Input>::Item: AsChar, |
102 | | { |
103 | 0 | Char { c, e: PhantomData } |
104 | 0 | } Unexecuted instantiation: nom::character::char::<&str, nom::error::Error<&str>> Unexecuted instantiation: nom::character::char::<_, _> |
105 | | |
106 | | /// Parser implementation for [char()] |
107 | | pub struct Char<E> { |
108 | | c: char, |
109 | | e: PhantomData<E>, |
110 | | } |
111 | | |
112 | | impl<I, Error: ParseError<I>> Parser<I> for Char<Error> |
113 | | where |
114 | | I: Input, |
115 | | <I as Input>::Item: AsChar, |
116 | | { |
117 | | type Output = char; |
118 | | type Error = Error; |
119 | | #[inline(always)] |
120 | 0 | fn process<OM: crate::OutputMode>( |
121 | 0 | &mut self, |
122 | 0 | i: I, |
123 | 0 | ) -> crate::PResult<OM, I, Self::Output, Self::Error> { |
124 | 0 | match (i).iter_elements().next().map(|t| { |
125 | 0 | let b = t.as_char() == self.c; |
126 | 0 | (&self.c, b) |
127 | 0 | }) {Unexecuted instantiation: <nom::character::Char<nom::error::Error<&str>> as nom::internal::Parser<&str>>::process::<nom::internal::OutputM<nom::internal::Emit, nom::internal::Emit, nom::internal::Complete>>::{closure#0}Unexecuted instantiation: <nom::character::Char<_> as nom::internal::Parser<_>>::process::<_>::{closure#0} |
128 | | None => { |
129 | 0 | if OM::Incomplete::is_streaming() { |
130 | 0 | Err(Err::Incomplete(Needed::new(self.c.len() - i.input_len()))) |
131 | | } else { |
132 | 0 | Err(Err::Error(OM::Error::bind(|| Error::from_char(i, self.c)))) Unexecuted instantiation: <nom::character::Char<nom::error::Error<&str>> as nom::internal::Parser<&str>>::process::<nom::internal::OutputM<nom::internal::Emit, nom::internal::Emit, nom::internal::Complete>>::{closure#1}Unexecuted instantiation: <nom::character::Char<_> as nom::internal::Parser<_>>::process::<_>::{closure#1} |
133 | | } |
134 | | } |
135 | 0 | Some((_, false)) => Err(Err::Error(OM::Error::bind(|| Error::from_char(i, self.c)))), Unexecuted instantiation: <nom::character::Char<nom::error::Error<&str>> as nom::internal::Parser<&str>>::process::<nom::internal::OutputM<nom::internal::Emit, nom::internal::Emit, nom::internal::Complete>>::{closure#2}Unexecuted instantiation: <nom::character::Char<_> as nom::internal::Parser<_>>::process::<_>::{closure#2} |
136 | 0 | Some((c, true)) => Ok((i.take_from(c.len()), OM::Output::bind(|| c.as_char()))), Unexecuted instantiation: <nom::character::Char<nom::error::Error<&str>> as nom::internal::Parser<&str>>::process::<nom::internal::OutputM<nom::internal::Emit, nom::internal::Emit, nom::internal::Complete>>::{closure#3}Unexecuted instantiation: <nom::character::Char<_> as nom::internal::Parser<_>>::process::<_>::{closure#3} |
137 | | } |
138 | 0 | } Unexecuted instantiation: <nom::character::Char<nom::error::Error<&str>> as nom::internal::Parser<&str>>::process::<nom::internal::OutputM<nom::internal::Emit, nom::internal::Emit, nom::internal::Complete>> Unexecuted instantiation: <nom::character::Char<_> as nom::internal::Parser<_>>::process::<_> |
139 | | } |
140 | | |
141 | | /// Recognizes one character and checks that it satisfies a predicate |
142 | | /// |
143 | | /// # Example |
144 | | /// |
145 | | /// ``` |
146 | | /// # use nom::{Err, error::{ErrorKind, Error}, Needed, IResult}; |
147 | | /// # use nom::character::complete::satisfy; |
148 | | /// fn parser(i: &str) -> IResult<&str, char> { |
149 | | /// satisfy(|c| c == 'a' || c == 'b')(i) |
150 | | /// } |
151 | | /// assert_eq!(parser("abc"), Ok(("bc", 'a'))); |
152 | | /// assert_eq!(parser("cd"), Err(Err::Error(Error::new("cd", ErrorKind::Satisfy)))); |
153 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Satisfy)))); |
154 | | /// ``` |
155 | 0 | pub fn satisfy<F, I, Error: ParseError<I>>( |
156 | 0 | predicate: F, |
157 | 0 | ) -> impl Parser<I, Output = char, Error = Error> |
158 | 0 | where |
159 | 0 | I: Input, |
160 | 0 | <I as Input>::Item: AsChar, |
161 | 0 | F: Fn(char) -> bool, |
162 | | { |
163 | | Satisfy { |
164 | 0 | predicate, |
165 | 0 | make_error: |i: I| Error::from_error_kind(i, ErrorKind::Satisfy), |
166 | | } |
167 | 0 | } |
168 | | |
169 | | /// Parser implementation for [satisfy] |
170 | | pub struct Satisfy<F, MakeError> { |
171 | | predicate: F, |
172 | | make_error: MakeError, |
173 | | } |
174 | | |
175 | | impl<I, Error: ParseError<I>, F, MakeError> Parser<I> for Satisfy<F, MakeError> |
176 | | where |
177 | | I: Input, |
178 | | <I as Input>::Item: AsChar, |
179 | | F: Fn(char) -> bool, |
180 | | MakeError: Fn(I) -> Error, |
181 | | { |
182 | | type Output = char; |
183 | | type Error = Error; |
184 | | |
185 | | #[inline(always)] |
186 | 0 | fn process<OM: crate::OutputMode>( |
187 | 0 | &mut self, |
188 | 0 | i: I, |
189 | 0 | ) -> crate::PResult<OM, I, Self::Output, Self::Error> { |
190 | 0 | match (i).iter_elements().next().map(|t| { |
191 | 0 | let c = t.as_char(); |
192 | 0 | let b = (self.predicate)(c); |
193 | 0 | (c, b) |
194 | 0 | }) { |
195 | | None => { |
196 | 0 | if OM::Incomplete::is_streaming() { |
197 | 0 | Err(Err::Incomplete(Needed::Unknown)) |
198 | | } else { |
199 | 0 | Err(Err::Error(OM::Error::bind(|| (self.make_error)(i)))) |
200 | | } |
201 | | } |
202 | 0 | Some((_, false)) => Err(Err::Error(OM::Error::bind(|| (self.make_error)(i)))), |
203 | 0 | Some((c, true)) => Ok((i.take_from(c.len()), OM::Output::bind(|| c.as_char()))), |
204 | | } |
205 | 0 | } |
206 | | } |
207 | | |
208 | | /// Recognizes one of the provided characters. |
209 | | /// |
210 | | /// # Example |
211 | | /// |
212 | | /// ``` |
213 | | /// # use nom::{Err, error::ErrorKind}; |
214 | | /// # use nom::character::complete::one_of; |
215 | | /// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("abc")("b"), Ok(("", 'b'))); |
216 | | /// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("a")("bc"), Err(Err::Error(("bc", ErrorKind::OneOf)))); |
217 | | /// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("a")(""), Err(Err::Error(("", ErrorKind::OneOf)))); |
218 | | /// ``` |
219 | 0 | pub fn one_of<I, T, Error: ParseError<I>>(list: T) -> impl Parser<I, Output = char, Error = Error> |
220 | 0 | where |
221 | 0 | I: Input, |
222 | 0 | <I as Input>::Item: AsChar, |
223 | 0 | T: FindToken<char>, |
224 | | { |
225 | | Satisfy { |
226 | 0 | predicate: move |c: char| list.find_token(c), |
227 | 0 | make_error: move |i| Error::from_error_kind(i, ErrorKind::OneOf), |
228 | | } |
229 | 0 | } |
230 | | |
231 | | //. Recognizes a character that is not in the provided characters. |
232 | | /// |
233 | | /// # Example |
234 | | /// |
235 | | /// ``` |
236 | | /// # use nom::{Err, error::ErrorKind, Needed}; |
237 | | /// # use nom::character::streaming::none_of; |
238 | | /// assert_eq!(none_of::<_, _, (_, ErrorKind)>("abc")("z"), Ok(("", 'z'))); |
239 | | /// assert_eq!(none_of::<_, _, (_, ErrorKind)>("ab")("a"), Err(Err::Error(("a", ErrorKind::NoneOf)))); |
240 | | /// assert_eq!(none_of::<_, _, (_, ErrorKind)>("a")(""), Err(Err::Incomplete(Needed::Unknown))); |
241 | | /// ``` |
242 | 0 | pub fn none_of<I, T, Error: ParseError<I>>(list: T) -> impl Parser<I, Output = char, Error = Error> |
243 | 0 | where |
244 | 0 | I: Input, |
245 | 0 | <I as Input>::Item: AsChar, |
246 | 0 | T: FindToken<char>, |
247 | | { |
248 | | Satisfy { |
249 | 0 | predicate: move |c: char| !list.find_token(c), |
250 | 0 | make_error: move |i| Error::from_error_kind(i, ErrorKind::NoneOf), |
251 | | } |
252 | 0 | } |
253 | | |
254 | | // Matches one byte as a character. Note that the input type will |
255 | | /// accept a `str`, but not a `&[u8]`, unlike many other nom parsers. |
256 | | /// |
257 | | /// # Example |
258 | | /// |
259 | | /// ``` |
260 | | /// # use nom::{character::complete::anychar, Err, error::{Error, ErrorKind}, IResult}; |
261 | | /// fn parser(input: &str) -> IResult<&str, char> { |
262 | | /// anychar(input) |
263 | | /// } |
264 | | /// |
265 | | /// assert_eq!(parser("abc"), Ok(("bc",'a'))); |
266 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Eof)))); |
267 | | /// ``` |
268 | 0 | pub fn anychar<T, E: ParseError<T>>(input: T) -> IResult<T, char, E> |
269 | 0 | where |
270 | 0 | T: Input, |
271 | 0 | <T as Input>::Item: AsChar, |
272 | | { |
273 | 0 | let mut it = input.iter_elements(); |
274 | 0 | match it.next() { |
275 | 0 | None => Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof))), |
276 | 0 | Some(c) => Ok((input.take_from(c.len()), c.as_char())), |
277 | | } |
278 | 0 | } |
279 | | |
280 | | /// Parser implementation for char |
281 | | pub struct AnyChar<E> { |
282 | | e: PhantomData<E>, |
283 | | } |
284 | | |
285 | | impl<I, Error: ParseError<I>> Parser<I> for AnyChar<Error> |
286 | | where |
287 | | I: Input, |
288 | | <I as Input>::Item: AsChar, |
289 | | { |
290 | | type Output = char; |
291 | | type Error = Error; |
292 | | |
293 | 0 | fn process<OM: crate::OutputMode>( |
294 | 0 | &mut self, |
295 | 0 | i: I, |
296 | 0 | ) -> crate::PResult<OM, I, Self::Output, Self::Error> { |
297 | 0 | match (i).iter_elements().next() { |
298 | | None => { |
299 | 0 | if OM::Incomplete::is_streaming() { |
300 | 0 | Err(Err::Incomplete(Needed::new(1))) |
301 | | } else { |
302 | 0 | Err(Err::Error(OM::Error::bind(|| { |
303 | 0 | Error::from_error_kind(i, ErrorKind::Eof) |
304 | 0 | }))) |
305 | | } |
306 | | } |
307 | 0 | Some(c) => Ok((i.take_from(c.len()), OM::Output::bind(|| c.as_char()))), |
308 | | } |
309 | 0 | } |
310 | | } |
311 | | |
312 | | /// Recognizes one or more ASCII numerical characters: 0-9 |
313 | | /// |
314 | | /// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, |
315 | | /// or if no terminating token is found (a non digit character). |
316 | | /// # Example |
317 | | /// |
318 | | /// ``` |
319 | | /// # use nom::{Err, error::ErrorKind, IResult, Needed}; |
320 | | /// # use nom::character::streaming::digit1; |
321 | | /// assert_eq!(digit1::<_, (_, ErrorKind)>("21c"), Ok(("c", "21"))); |
322 | | /// assert_eq!(digit1::<_, (_, ErrorKind)>("c1"), Err(Err::Error(("c1", ErrorKind::Digit)))); |
323 | | /// assert_eq!(digit1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); |
324 | | /// ``` |
325 | 0 | pub fn digit1<T, E: ParseError<T>>() -> impl Parser<T, Output = T, Error = E> |
326 | 0 | where |
327 | 0 | T: Input, |
328 | 0 | <T as Input>::Item: AsChar, |
329 | | { |
330 | 0 | Digit1 { e: PhantomData } |
331 | 0 | } |
332 | | |
333 | | /// Parser implementation for [digit1] |
334 | | pub struct Digit1<E> { |
335 | | e: PhantomData<E>, |
336 | | } |
337 | | |
338 | | impl<I: Input, E: ParseError<I>> Parser<I> for Digit1<E> |
339 | | where |
340 | | <I as Input>::Item: AsChar, |
341 | | { |
342 | | type Output = I; |
343 | | |
344 | | type Error = E; |
345 | | |
346 | | #[inline] |
347 | 0 | fn process<OM: crate::OutputMode>( |
348 | 0 | &mut self, |
349 | 0 | input: I, |
350 | 0 | ) -> crate::PResult<OM, I, Self::Output, Self::Error> { |
351 | 0 | input.split_at_position_mode1::<OM, _, _>(|item| !item.is_dec_digit(), ErrorKind::Digit) |
352 | 0 | } |
353 | | } |
354 | | |
355 | | /// Recognizes zero or more spaces, tabs, carriage returns and line feeds. |
356 | | /// |
357 | | /// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, |
358 | | /// or if no terminating token is found (a non space character). |
359 | | /// # Example |
360 | | /// |
361 | | /// ``` |
362 | | /// # use nom::{Err, error::ErrorKind, IResult, Needed}; |
363 | | /// # use nom::character::streaming::multispace0; |
364 | | /// assert_eq!(multispace0::<_, (_, ErrorKind)>(" \t\n\r21c"), Ok(("21c", " \t\n\r"))); |
365 | | /// assert_eq!(multispace0::<_, (_, ErrorKind)>("Z21c"), Ok(("Z21c", ""))); |
366 | | /// assert_eq!(multispace0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); |
367 | | /// ``` |
368 | 0 | pub fn multispace0<T, E: ParseError<T>>() -> impl Parser<T, Output = T, Error = E> |
369 | 0 | where |
370 | 0 | T: Input, |
371 | 0 | <T as Input>::Item: AsChar, |
372 | | { |
373 | 0 | MultiSpace0 { e: PhantomData } |
374 | | /*input.split_at_position(|item| { |
375 | | let c = item.as_char(); |
376 | | !(c == ' ' || c == '\t' || c == '\r' || c == '\n') |
377 | | })*/ |
378 | 0 | } |
379 | | |
380 | | /// Parser implementation for [multispace0()] |
381 | | pub struct MultiSpace0<E> { |
382 | | e: PhantomData<E>, |
383 | | } |
384 | | |
385 | | impl<I, Error: ParseError<I>> Parser<I> for MultiSpace0<Error> |
386 | | where |
387 | | I: Input, |
388 | | <I as Input>::Item: AsChar, |
389 | | { |
390 | | type Output = I; |
391 | | type Error = Error; |
392 | | |
393 | 0 | fn process<OM: crate::OutputMode>( |
394 | 0 | &mut self, |
395 | 0 | i: I, |
396 | 0 | ) -> crate::PResult<OM, I, Self::Output, Self::Error> { |
397 | 0 | i.split_at_position_mode::<OM, _, _>(|item| { |
398 | 0 | let c = item.as_char(); |
399 | 0 | !(c == ' ' || c == '\t' || c == '\r' || c == '\n') |
400 | 0 | }) |
401 | 0 | } |
402 | | } |