pub mod deserialize; mod enum_build_fn; mod leaf_enum_build_fn; mod leaf_struct_build_fn; mod production_build_fn; mod spec; mod struct_build_fn; mod type_gen; mod util; use crate::enum_build_fn::make_enum_build_fn; use crate::leaf_enum_build_fn::make_leaf_enum_build_fn; use crate::leaf_struct_build_fn::make_leaf_struct_build_fn; use crate::production_build_fn::make_production_build_fn; use crate::struct_build_fn::make_struct_build_fn; use crate::type_gen::make_type; use proc_macro2::TokenStream; use quote::quote; use spec::BuildSpec; use syn::File; fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) { println!("*** BuildSpec ***"); match build_spec { BuildSpec::Enum(enum_build_spec) => { println!("Enum Spec - build: {}", enum_build_spec.build()); } BuildSpec::LeafEnum(leaf_enum_build_spec) => { println!("Leaf Enum Spec - build: {}", leaf_enum_build_spec.build()); } BuildSpec::Struct(struct_build_spec) => { println!("Struct Spec - build: {}", struct_build_spec.build()); } BuildSpec::LeafStruct(leaf_struct_build_spec) => { println!( "Leaf Struct Spec - build: {}", leaf_struct_build_spec.build() ); } BuildSpec::Production(production_build_spec) => { println!("Production Spec - rule: {}", production_build_spec.rule()) } } println!("{:#?}", token_stream); let parsed: File = syn::parse2(token_stream.clone()).unwrap(); println!("{}", prettyplease::unparse(&parsed)); } pub struct AstGeneratedFile { pub name: String, pub contents: String, } fn token_stream_to_string(token_stream: TokenStream) -> String { let file: File = syn::parse2(token_stream).unwrap(); prettyplease::unparse(&file) } fn generate_build_file(build_specs: &[BuildSpec]) -> AstGeneratedFile { let build_fns = build_specs .iter() .map(|build_spec| match build_spec { BuildSpec::Enum(enum_build_spec) => { let stream = make_enum_build_fn(enum_build_spec); debug_built_spec(build_spec, &stream); stream } BuildSpec::LeafEnum(leaf_enum_build_spec) => { let stream = make_leaf_enum_build_fn(leaf_enum_build_spec); debug_built_spec(build_spec, &stream); stream } BuildSpec::Struct(struct_build_spec) => { let stream = make_struct_build_fn(struct_build_spec); debug_built_spec(build_spec, &stream); stream } BuildSpec::LeafStruct(leaf_struct_build_spec) => { let stream = make_leaf_struct_build_fn(leaf_struct_build_spec); debug_built_spec(build_spec, &stream); stream } BuildSpec::Production(production_build_spec) => { let stream = make_production_build_fn(production_build_spec); debug_built_spec(build_spec, &stream); stream } }) .collect::>(); let combined = quote! { #(#build_fns)* }; AstGeneratedFile { name: String::from("build.rs"), contents: token_stream_to_string(combined), } } fn generate_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile { let types = build_specs .iter() .map(|build_spec| make_type(build_spec)) .collect::>(); let combined = quote! { #(#types)* }; AstGeneratedFile { name: String::from("node.rs"), contents: token_stream_to_string(combined), } } pub fn generate_files(build_specs: &[BuildSpec]) -> Vec { vec![ generate_build_file(build_specs), generate_node_file(build_specs), ] }