openpql_pql_parser/ast/
num.rs

1use super::{Display, Error, LalrError, Loc, NumValueFloat, NumValueInt, str};
2
3#[derive(Clone, PartialEq, derive_more::From, derive_more::Debug)]
4#[debug("{}", self.inner)]
5pub struct Num {
6    pub inner: NumValue,
7    pub loc: (Loc, Loc),
8}
9
10impl From<(NumValueFloat, (Loc, Loc))> for Num {
11    fn from((val, loc): (NumValueFloat, (Loc, Loc))) -> Self {
12        Self {
13            inner: val.into(),
14            loc,
15        }
16    }
17}
18
19impl From<(NumValueInt, (Loc, Loc))> for Num {
20    fn from((val, loc): (NumValueInt, (Loc, Loc))) -> Self {
21        Self {
22            inner: val.into(),
23            loc,
24        }
25    }
26}
27
28/// # Panics
29/// float parse won't fail /-?(\d+)?\.\d+/
30/// <https://doc.rust-lang.org/std/primitive.f64.html#method.from_str>
31impl<'input> TryFrom<(&'input str, (Loc, Loc), bool)> for Num {
32    type Error = LalrError<'input>;
33
34    fn try_from(
35        (src, loc, is_float): (&'input str, (Loc, Loc), bool),
36    ) -> Result<Self, Self::Error> {
37        if is_float {
38            Ok((src.parse::<NumValueFloat>().unwrap(), loc).into())
39        } else {
40            src.parse::<NumValueInt>().map_or_else(
41                |_| Err(Error::InvalidNumericValue(loc).into()),
42                |v| Ok((v, loc).into()),
43            )
44        }
45    }
46}
47
48#[derive(Clone, Copy, Debug, PartialEq, derive_more::From, Display)]
49pub enum NumValue {
50    #[display("{_0}")]
51    Int(NumValueInt),
52    #[display("{_0}")]
53    Float(NumValueFloat),
54}
55
56#[cfg(test)]
57mod tests {
58
59    use super::*;
60    use crate::*;
61
62    fn assert_num<T>(src: &str, expected: T)
63    where
64        NumValue: From<T>,
65    {
66        let loc_start = 0;
67        let loc_end = src.len();
68        assert_eq!(
69            parse_num(src),
70            Ok((NumValue::from(expected), (loc_start, loc_end)).into())
71        );
72    }
73
74    #[test]
75    fn test_num() {
76        assert_num("0", 0);
77        assert_num("-1", -1);
78        assert_num("-1.5", -1.5);
79        assert_num("-.5", -0.5);
80        assert_num(".5", 0.5);
81    }
82
83    #[test]
84    fn test_err() {
85        let toobig = format!("{}0", NumValueInt::MAX);
86        assert_eq!(
87            parse_num(&toobig),
88            Err(Error::InvalidNumericValue((0, toobig.len())))
89        );
90    }
91
92    #[test]
93    fn test_dbg() {
94        assert_eq!(format!("{:?}", Num::from((-123, (0, 1)))), "-123");
95    }
96}