use crate::GenesysValue;
use std::io::Write;
use std::path::PathBuf;
pub fn write(ast: GenesysValue, to: PathBuf) -> Result<(), std::io::Error> {
let mut f = std::fs::File::create(to);
if let Ok(fd) = f {
let mut bufwriter = std::io::BufWriter::new(fd);
if let GenesysValue::File(tokens) = ast {
let s = parse_file_ast(tokens);
bufwriter.write(s.as_bytes())?;
}
}
Ok(())
}
pub fn parse_file_ast(ast: Vec<GenesysValue>) -> String {
let mut data = String::new();
let mut global_use = None;
let mut global_derive = None;
for token in ast.iter() {
match token {
GenesysValue::GlobUse(name, vec) => {
global_use = Some(parse_token(&None, &None, token, 0));
}
GenesysValue::GlobDerive(derive) => {
global_derive = Some(parse_token(&None, &None, token, 0));
}
_ => data += &parse_token(&global_use, &global_derive, token, 0),
}
}
data = global_use.unwrap_or(String::from("")) + &data;
data
}
pub fn parse_token(
global_use: &Option<String>,
global_derive: &Option<String>,
token: &GenesysValue,
level: u8,
) -> String {
let mut data = String::new();
match token {
GenesysValue::GlobUse(name, vec) => {
if level == 1 {
data += &format!("use {}{{\n", name);
} else if level > 1 {
data += &format!("{}{{\n", name);
}
for e in vec {
match e {
GenesysValue::String(s) => {
if level == 0 {
data += &format!("use {};\n", s);
} else {
data += &format!("{},\n", s)
}
}
_ => {
data += &parse_token(global_use, global_derive, e, level + 1);
}
}
}
if level > 0 {
data += &format!("}},\n");
} else {
}
}
GenesysValue::GlobDerive(v) => {
data += &format!(
"#[derive({})]\n",
v.iter()
.filter_map(|e| {
if let GenesysValue::String(s) = e {
return Some(*s);
}
None
})
.collect::<Vec<_>>()
.join(",")
);
}
GenesysValue::LocalUse(name, vec) => {
if level != 0 {
data += &format!("{}{{\n", name);
}
for e in vec {
match e {
GenesysValue::String(s) => {
if level == 0 {
data += &format!("use {};\n", s);
} else {
data += &format!("{},\n", s)
}
}
_ => {
data += &parse_token(global_use, global_derive, e, level + 1);
}
}
}
if level > 0 {
data += &format!("}},\n");
} else {
data += &format!("}}\n");
}
}
GenesysValue::LocalDerive(v) => {
data += &format!(
"#[derive({})]\n",
v.iter()
.filter_map(|e| {
if let GenesysValue::String(s) = e {
return Some(*s);
}
None
})
.collect::<Vec<_>>()
.join(",")
);
}
GenesysValue::SingleComponent(n) => {
if let Some(derive) = global_derive {
data += derive;
}
data += &format!("pub struct {};\n", n);
}
GenesysValue::TupleComponent(n, v) => {
if let Some(derive) = global_derive {
data += derive;
}
data += &format!("pub struct {}({});\n", n, v.iter().map(|e| format!("pub {}", e)).collect::<Vec<_>>().join(","));
}
GenesysValue::NamedComponent(n, hm) => {
if let Some(derive) = global_derive {
data += derive;
}
data += &format!(
"pub struct {} {{\n{}\n}}\n",
n,
hm.iter()
.map(|(k, v)| format!("pub {}: {}", k, v.replace("str", "String")))
.collect::<Vec<_>>()
.join(",\n")
);
}
GenesysValue::Module(name, children) => {
data += &format!("pub mod {} {{\n", name);
if let Some(guse) = global_use {
data += guse;
}
let mut derive = None;
for child in children.iter() {
if let GenesysValue::LocalDerive(local_derive) = &child {
derive = Some(parse_token(global_use, &None, child, level + 1));
} else if derive.is_some() {
data += &format!("{}", parse_token(global_use, &derive, child, level + 1));
} else {
data += &format!(
"{}",
parse_token(global_use, global_derive, child, level + 1)
);
}
}
data += "}\n";
}
GenesysValue::String(v) => {}
GenesysValue::File(v) => {}
GenesysValue::Empty => {}
}
data
}