pratt_gen_core/
primitive.rs

1use once_cell::sync::Lazy;
2use crate::*;
3
4macro_rules! impl_i {($($int: ty)*) => {$(
5    impl<'a> ParserImpl<'a> for $int {
6        fn parser_impl(
7            source: Source<'a>, 
8            out_arena: &'a Arena,
9            err_arena: &'a Arena,
10            precedence: u16,
11        ) -> Result<(Self, Source<'a>), Error<'a>> {
12            let _ = out_arena;
13            let _ = precedence;
14            let mut by = 0;
15            if source[..].starts_with("-") { by += 1; }
16            for c in source[by..].chars() {
17                if !c.is_ascii_digit() { break }
18                by += c.len_utf8();
19            }
20            match source[..by].parse::<$int>() {
21                Ok(out) => Ok((out, source.proceed(by))),
22                Err(_) => Err(Error::Mismatch {
23                    range: (source.split, source.split + by), 
24                    token: stringify!($int), 
25                    piece: unsafe { err_arena.alloc_str(&source[..source[..].chars().next().map(|x| x.len_utf8()).unwrap_or(0)]) }
26                })
27            }
28        }
29    })*
30};}
31
32impl_i!{i8 i16 i32 i64 i128}
33
34macro_rules! impl_u {($($int: ty)*) => {$(
35    impl<'a> ParserImpl<'a> for $int {
36        fn parser_impl(
37            source: Source<'a>, 
38            out_arena: &'a Arena,
39            err_arena: &'a Arena,
40            precedence: u16,
41        ) -> Result<(Self, Source<'a>), Error<'a>> {
42            let _ = out_arena;
43            let _ = precedence;
44            let mut by = 0;
45            for c in source[by..].chars() {
46                if !c.is_ascii_digit() { break }
47                by += c.len_utf8();
48            }
49            match source[..by].parse::<$int>() {
50                Ok(out) => Ok((out, source.proceed(by))),
51                Err(_) => Err(Error::Mismatch {
52                    range: (source.split, source.split + by), 
53                    token: stringify!($int), 
54                    piece: unsafe { err_arena.alloc_str(&source[..source[..].chars().next().map(|x| x.len_utf8()).unwrap_or(0)]) }
55                })
56            }
57        }
58    })*
59};}
60
61impl_u!{u8 u16 u32 u64 u128}
62
63macro_rules! impl_f {($($flt: ty)*) => {$(
64    impl<'a> ParserImpl<'a> for $flt {
65        fn parser_impl(
66            source: Source<'a>, 
67            out_arena: &'a Arena,
68            err_arena: &'a Arena,
69            precedence: u16,
70        ) -> Result<(Self, Source<'a>), Error<'a>> {
71            let _ = out_arena;
72            let _ = precedence;
73            let mut by  = 0;
74            let mut dot = false;
75            if source[..].starts_with("-") { by += 1; }
76            for c in source[by..].chars() {
77                if c == '.' && !dot {
78                    dot = true;
79                    by += c.len_utf8();
80                    continue; 
81                }
82                if !c.is_ascii_digit() { break }
83                by += c.len_utf8();
84            }
85            match source[..by].parse::<$flt>() {
86                Ok(out) => Ok((out, source.proceed(by))),
87                Err(_) => Err(Error::Mismatch {
88                    range: (source.split, source.split + by), 
89                    token: stringify!($flt), 
90                    piece: unsafe { err_arena.alloc_str(&source[..source[..].chars().next().map(|x| x.len_utf8()).unwrap_or(0)]) }
91                })
92            }
93        }
94    })*
95};}
96
97impl_f!{f32 f64}
98
99#[derive(Debug, Clone, Copy)]
100pub struct Ident<'a>(pub &'a str);
101
102impl<'a> Ident<'a> { pub fn to_str(&self) -> &'a str { self.0 } }
103
104impl<'a> ParserImpl<'a> for Ident<'a> {
105    fn parser_impl(
106        source: Source<'a>, 
107        out_arena: &'a Arena,
108        err_arena: &'a Arena,
109        _: u16,
110    ) -> Result<(Self, Source<'a>), Error<'a>> {
111        let mut len = 0;
112        let mut char_len = 0;
113        for c in source[..].chars() {
114            if c.is_ascii_alphanumeric() {
115                len += c.len_utf8();
116            } else {
117                char_len = c.len_utf8();
118                break;
119            }
120        }
121        unsafe {if len == 0 {
122            Err(Error::Mismatch {
123                range: (source.split, source.split + len), 
124                token: "", 
125                piece: err_arena.alloc_str(&source[..char_len])
126            })
127        } else {
128            let ident = out_arena.alloc_str(&source[..len]);
129            Ok((Ident(ident), source.proceed(len)))
130        } }
131    }
132}
133
134impl<'a> ParserImpl<'a> for &'a str {
135    fn parser_impl(
136        source: Source<'a>, 
137        out_arena: &'a Arena,
138        err_arena: &'a Arena,
139        _: u16,
140    ) -> Result<(Self, Source<'a>), Error<'a>> {
141        use regex::Regex;
142        static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(
143            r#"^"([^"\\]|\\\\|\\")*""#
144        ).unwrap());
145        let Some(by) = REGEX.shortest_match(&source[..]) else {
146            Err(Error::Mismatch {
147                range: (source.split, source.split+2), 
148                token: "<str>", 
149                piece: unsafe{err_arena.alloc_str(&source[..source[..].chars().next().map(|x| x.len_utf8()).unwrap_or(0)])}
150            })?
151        };
152        let s = unsafe{ out_arena.alloc_str(&source[1..by-1]) };
153        Ok((s, source.proceed(by)))
154    }
155}