reda_lib/model/
ast.rs

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