udled_tokenizers/
numeric.rs1use alloc::string::ToString;
2use udled::{
3 tokenizers::{opt, Digit, Peek},
4 AsChar, AsSlice, AsStr, Buffer, Error, Item, Reader, Span, Tokenizer, TokenizerExt,
5};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
8pub struct Integer;
9
10impl<'input, B> Tokenizer<'input, B> for Integer
11where
12 B: Buffer<'input>,
13 B::Item: AsChar,
14{
15 type Token = Item<i128>;
16
17 fn to_token<'a>(&self, reader: &mut Reader<'_, 'input, B>) -> Result<Self::Token, Error> {
18 let start = reader.position();
19 let mut val: i128 = 0;
20 let base = 10;
21
22 let sign = if reader.eat('-').is_ok() { -1 } else { 1 };
23
24 loop {
25 let ch = reader.parse(Digit(base))?;
26
27 val = (base as i128) * val + (ch.value as i128);
28
29 if !reader.is(Digit(base)) {
30 break;
31 }
32 }
33
34 return Ok(Item::new(Span::new(start, reader.position()), val * sign));
35 }
36
37 fn peek(&self, reader: &mut Reader<'_, 'input, B>) -> bool {
38 reader.is(Peek((opt('-'), Digit(10))))
39 }
40}
41
42#[derive(Debug, Clone, Copy, Default)]
43pub struct Float;
44
45impl<'input, B> Tokenizer<'input, B> for Float
46where
47 B: Buffer<'input>,
48 B::Item: AsChar,
49 B::Source: AsSlice<'input>,
50 <B::Source as AsSlice<'input>>::Slice: AsStr<'input>,
51{
52 type Token = Item<f64>;
53
54 fn to_token<'a>(&self, reader: &mut Reader<'_, 'input, B>) -> Result<Self::Token, Error> {
55 let slice = reader.parse(
56 (
57 Integer,
58 '.',
59 Digit(10).many(),
60 ('e'.or('E'), opt('-'), Digit(10).many()).optional(),
61 )
62 .slice(),
63 )?;
64
65 let float: f64 = slice
66 .value
67 .as_str()
68 .parse()
69 .map_err(|err: core::num::ParseFloatError| reader.error(err.to_string()))?;
70
71 Ok(Item::new(slice.span, float))
72 }
73
74 fn peek(&self, reader: &mut Reader<'_, 'input, B>) -> bool {
75 reader.is(Peek((Integer, '.')))
76 }
77}
78
79#[cfg(test)]
80mod test {
81 use udled::Input;
82
83 use super::{Float, Integer};
84
85 #[test]
86 fn integer() {
87 let mut input = Input::new("10203 0 42");
88
89 let (a, _, b, _, c) = input.parse((Integer, ' ', Integer, ' ', Integer)).unwrap();
90
91 assert_eq!(a.value, 10203);
92 assert_eq!(b.value, 0);
93 assert_eq!(c.value, 42);
94 }
95
96 #[test]
108 fn float() {
109 let mut input = Input::new("1.0000033 2003.303 12.03e-20");
110
111 let (a, _, b, _, c) = input.parse((Float, ' ', Float, ' ', Float)).unwrap();
112
113 assert_eq!(a.value, 1.0000033);
114 assert_eq!(b.value, 2003.303);
115 assert_eq!(c.value, 12.03e-20);
116 }
117}