reda_lib/model/
ast.rs

1use std::{error::Error, fmt::Display, str::FromStr};
2use crate::error::{LibError, LibErrorContext};
3use super::LibExpr;
4
5#[derive(Debug, Clone, PartialEq)]
6pub enum LibAst {
7    LibGroup {
8        kind: String,
9        params: Vec<String>,
10        items: Vec<LibAst>,
11    },
12    Attr {
13        key: String,
14        value: LibValue,
15    },
16}
17
18#[derive(Debug, Clone, PartialEq)]
19pub enum LibValue {
20    Bool(bool),
21    Float(f64),
22    String(String),
23    Ident(String),
24    Vec(Vec<LibValue>),
25}
26
27impl LibAst {
28    pub fn group(kind: impl Into<String>, params: impl Into<Vec<String>>, items: impl Into<Vec<LibAst>>) -> Self {
29        Self::LibGroup {
30            kind: kind.into(),
31            params: params.into(),
32            items: items.into(),
33        }
34    }
35
36    pub fn group_single_param(kind: impl Into<String>, param: impl Into<String>, items: impl Into<Vec<LibAst>>) -> Self {
37        Self::LibGroup {
38            kind: kind.into(),
39            params: vec![param.into()],
40            items: items.into(),
41        }
42    }
43
44    pub fn attr(key: impl Into<String>, value: impl Into<LibValue>) -> Self {
45        Self::Attr { key: key.into(), value: value.into() }
46    }
47}
48
49impl LibValue {
50    pub fn kind_str(&self) -> &'static str {
51        match self {
52            Self::Bool(_) => "bool",
53            Self::Float(_) => "float",
54            Self::Ident(_) => "ident",
55            Self::String(_) => "string",
56            Self::Vec(_) => "vector",
57        }
58    }
59
60    pub fn bool(&self) -> Result<bool, LibError> {
61        if let Self::Bool(value) = self {
62            Ok(*value)
63        } else {
64            Err(LibError::ValueKindUnmatch("bool", self.kind_str()))
65        }
66    }
67
68    pub fn float(&self) -> Result<f64, LibError> {
69        if let Self::Float(value) = self {
70            Ok(*value)
71        } else {
72            Err(LibError::ValueKindUnmatch("float", self.kind_str()))
73        }
74    }
75
76    pub fn floats(&self) -> Result<Vec<f64>, LibError> {
77        if let Self::String(value) = self {
78            let values = value
79                .split(',')
80                .map(|token| token.trim().parse::<f64>().map_err(|e| LibError::ParseFloat(e)))
81                .collect::<Result<Vec<_>, _>>()
82                .context(|| "parse float from strings")?;
83            Ok(values)
84        } else {
85            Err(LibError::ValueKindUnmatch("floats", self.kind_str()))
86        }
87    }
88
89    pub fn expr(&self) -> Result<LibExpr, LibError> {
90        if let Self::String(value) = self {
91            let expr = LibExpr::from_str(value)?;
92            Ok(expr)
93        } else {
94            Err(LibError::ValueKindUnmatch("expr", self.kind_str()))
95        }
96    }
97
98    pub fn ident(&self) -> Result<&str, LibError> {
99        if let Self::Ident(value) = self {
100            Ok(value)
101        } else {
102            Err(LibError::ValueKindUnmatch("ident", self.kind_str()))
103        }
104    }
105
106    pub fn literal(&self) -> Result<&str, LibError> {
107        match self {
108            Self::Ident(value) => Ok(value),
109            Self::String(value) => Ok(value),
110            _ => Err(LibError::ValueKindUnmatch("literal", self.kind_str()))
111        }
112    }
113
114    pub fn string(&self) -> Result<&str, LibError> {
115        if let Self::String(value) = self {
116            Ok(value)
117        } else {
118            Err(LibError::ValueKindUnmatch("string", self.kind_str()))
119        }
120    }
121
122    pub fn vector(&self) -> Result<&[LibValue], LibError> {
123        if let Self::Vec(value) = self {
124            Ok(value)
125        } else {
126            Err(LibError::ValueKindUnmatch("vector", self.kind_str()))
127        }
128    }
129
130    pub fn parse<T>(&self) -> Result<T, LibError> 
131    where 
132        T: FromStr,
133        T::Err: Error,
134    {
135        let s = self.ident()?;
136        T::from_str(s).map_err(|e| LibError::Parse(e.to_string()))
137    }
138}
139
140impl LibValue {
141    pub fn into_bool(self) -> Result<bool, LibError> {
142        if let Self::Bool(value) = self {
143            Ok(value)
144        } else {
145            Err(LibError::ValueKindUnmatch("bool", self.kind_str()))
146        }
147    }
148
149    pub fn into_float(self) -> Result<f64, LibError> {
150        if let Self::Float(value) = self {
151            Ok(value)
152        } else {
153            Err(LibError::ValueKindUnmatch("float", self.kind_str()))
154        }
155    }
156
157    pub fn into_floats(self) -> Result<Vec<f64>, LibError> {
158        self.floats()
159    }
160
161    pub fn into_ident(self) -> Result<String, LibError> {
162        if let Self::Ident(value) = self {
163            Ok(value)
164        } else {
165            Err(LibError::ValueKindUnmatch("ident", self.kind_str()))
166        }
167    }
168
169    pub fn into_string(self) -> Result<String, LibError> {
170        if let Self::String(value) = self {
171            Ok(value)
172        } else {
173            Err(LibError::ValueKindUnmatch("string", self.kind_str()))
174        }
175    }
176
177    pub fn into_literal(self) -> Result<String, LibError> {
178        match self {
179            Self::Ident(value) => Ok(value),
180            Self::String(value) => Ok(value),
181            _ => Err(LibError::ValueKindUnmatch("literal", self.kind_str()))
182        }
183    }
184
185    pub fn into_vector(self) -> Result<Vec<LibValue>, LibError> {
186        if let Self::Vec(value) = self {
187            Ok(value)
188        } else {
189            Err(LibError::ValueKindUnmatch("vector", self.kind_str()))
190        }
191    }
192}
193
194impl LibValue {
195    pub fn is_complex(&self) -> bool {
196        if let Self::Vec(_) = self {
197            true
198        } else {
199            false
200        }
201    }
202}
203
204impl Display for LibValue {
205    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
206        match self {
207            Self::Bool(b) => if *b { write!(f, "ture") } else { write!(f, "false") },
208            Self::Float(v) => write!(f, "{}", *v),
209            Self::Ident(v) => write!(f, "{}", v),
210            Self::String(v) => write!(f, "{}", v),
211            Self::Vec(values) => {
212                write!(f, "(")?;
213                for (i, v) in values.iter().enumerate() {
214                    if i != 0 {
215                        write!(f, ", ")?;
216                    }
217                    write!(f, "{}", v)?;
218                }
219                write!(f, ")")
220            }
221        }
222    }
223}