1use std::{fmt, result};
6
7use crate::error::Error;
8use crate::liberty::Liberty;
9use crate::parser::parse_libs;
10
11use gpoint::GPoint;
12use itertools::Itertools;
13use nom::error::VerboseError;
14
15pub type ParseResult<'a, T> = result::Result<T, Error<'a>>;
17
18#[derive(Debug, Clone)]
23pub struct LibertyAst(pub Vec<GroupItem>);
24
25impl LibertyAst {
26 pub fn new(libs: Vec<GroupItem>) -> Self {
28 Self(libs)
29 }
30
31 pub fn from_string(input: &str) -> ParseResult<'_, Self> {
33 parse_libs::<VerboseError<&str>>(input)
34 .map_err(|e| Error::new(input, e))
35 .map(|(_, libs)| LibertyAst::new(libs))
36 }
37
38 pub fn into_liberty(self) -> Liberty {
40 Liberty::from_ast(self)
41 }
42
43 pub fn from_liberty(lib: Liberty) -> Self {
45 lib.to_ast()
46 }
47}
48
49impl fmt::Display for LibertyAst {
50 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51 write!(f, "{}", items_to_string(&self.0, 0))
52 }
53}
54
55impl From<Liberty> for LibertyAst {
56 fn from(liberty: Liberty) -> Self {
57 LibertyAst::from_liberty(liberty)
58 }
59}
60
61fn items_to_string(items: &[GroupItem], level: usize) -> String {
63 let indent = " ".repeat(level);
64 items
65 .iter()
66 .map(|item| match item {
67 GroupItem::SimpleAttr(name, value) => {
68 format!("{}{} : {};", indent, name, value)
69 }
70 GroupItem::ComplexAttr(name, values) => format!(
71 "{}{} ({});",
72 indent,
73 name,
74 values.iter().map(|v| v.to_string()).join(", ")
75 ),
76 GroupItem::Comment(v) => format!("/*\n{}\n*/", v),
77 GroupItem::Group(type_, name, group_items) => format!(
78 "{}{} ({}) {{\n{}\n{}}}",
79 indent,
80 type_,
81 name,
82 items_to_string(group_items, level + 1),
83 indent
84 ),
85 })
86 .join("\n")
87}
88
89#[derive(Debug, PartialEq, Clone)]
91pub enum GroupItem {
92 Group(String, String, Vec<GroupItem>),
94 SimpleAttr(String, Value),
96 ComplexAttr(String, Vec<Value>),
97 Comment(String),
99}
100
101impl GroupItem {
102 pub fn group(&self) -> (String, String, Vec<GroupItem>) {
104 if let GroupItem::Group(type_, name, items) = self {
105 (String::from(type_), String::from(name), items.clone())
106 } else {
107 panic!("Not variant GroupItem::Group");
108 }
109 }
110}
111
112#[derive(Debug, PartialEq, Clone)]
118pub enum Value {
119 Bool(bool),
121 Float(f64),
126 FloatGroup(Vec<f64>),
139 String(String),
141 Expression(String),
146}
147
148impl fmt::Display for Value {
149 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
150 match self {
151 Value::Expression(v) => v.fmt(f),
152 Value::String(v) => write!(f, "\"{}\"", v),
153 Value::Bool(v) => {
154 if *v {
155 write!(f, "true")
156 } else {
157 write!(f, "false")
158 }
159 }
160 Value::Float(v) => write!(f, "{}", GPoint(*v)),
161 Value::FloatGroup(v) => write!(f, "\"{}\"", v.iter().map(|x| GPoint(*x)).format(", ")),
162 }
163 }
164}
165
166impl Value {
167 pub fn float(&self) -> f64 {
169 if let Value::Float(v) = self {
170 *v
171 } else {
172 panic!("Not a float")
173 }
174 }
175
176 pub fn string(&self) -> String {
178 if let Value::String(v) = self {
179 v.clone()
180 } else {
181 panic!("Not a string")
182 }
183 }
184
185 pub fn expr(&self) -> String {
187 if let Value::Expression(v) = self {
188 v.clone()
189 } else {
190 panic!("Not a string")
191 }
192 }
193
194 pub fn bool(&self) -> bool {
196 if let Value::Bool(v) = self {
197 *v
198 } else {
199 panic!("Not a bool")
200 }
201 }
202
203 pub fn float_group(&self) -> Vec<f64> {
205 if let Value::FloatGroup(v) = self {
206 v.clone()
207 } else {
208 panic!("Not a float group")
209 }
210 }
211}
212
213#[cfg(test)]
214mod test {
215 use super::{LibertyAst, Value};
216
217 macro_rules! parse_file {
218 ($fname:ident) => {{
219 let data = include_str!(concat!("../data/", stringify!($fname), ".lib"));
220 LibertyAst::from_string(data).unwrap()
221 }};
222 }
223
224 #[test]
225 fn test_files() {
226 parse_file!(small);
227 parse_file!(cells);
228 parse_file!(cells_timing);
229 }
230
231 #[test]
232 fn test_values() {
233 assert_eq!(Value::Bool(false).bool(), false);
234 assert_eq!(Value::Float(-3.45).float(), -3.45f64);
235 assert_eq!(Value::Expression("A & B".to_string()).expr(), "A & B");
236 assert_eq!(
237 Value::FloatGroup(vec![1.2, 3.4]).float_group(),
238 vec![1.2, 3.4]
239 );
240 assert_eq!(Value::String("abc def".to_string()).string(), "abc def");
241 }
242}