182 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| mod build_fn;
 | |
| pub mod deserialize;
 | |
| mod pretty_print;
 | |
| mod spec;
 | |
| mod type_gen;
 | |
| mod util;
 | |
| 
 | |
| use crate::build_fn::enum_build_fn::make_enum_build_fn;
 | |
| use crate::build_fn::leaf_enum_build_fn::make_leaf_enum_build_fn;
 | |
| use crate::build_fn::leaf_struct_build_fn::make_leaf_struct_build_fn;
 | |
| use crate::build_fn::polymorphic_build_build_fn::make_polymorphic_build_build_fn;
 | |
| use crate::build_fn::polymorphic_build_fn::make_polymorphic_build_fn;
 | |
| use crate::build_fn::polymorphic_enum_build_fn::make_polymorphic_enum_build_fn;
 | |
| use crate::build_fn::production_build_fn::make_production_build_fn;
 | |
| use crate::build_fn::struct_build_fn::make_struct_build_fn;
 | |
| use crate::pretty_print::make_pretty_print_impl;
 | |
| 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());
 | |
|         }
 | |
|         BuildSpec::Polymorphic(polymorphic_build_spec) => {
 | |
|             println!(
 | |
|                 "Polymorphic Type Spec - name: {}",
 | |
|                 polymorphic_build_spec.name()
 | |
|             );
 | |
|         }
 | |
|         BuildSpec::PolymorphicBuild(polymorphic_build_build_spec) => {
 | |
|             println!(
 | |
|                 "Polymorphic Build Spec - name: {}",
 | |
|                 polymorphic_build_build_spec.name()
 | |
|             );
 | |
|         }
 | |
|         BuildSpec::PolymorphicEnum(polymorphic_enum_build_spec) => {
 | |
|             println!(
 | |
|                 "Polymorphic Enum Spec - name: {}",
 | |
|                 polymorphic_enum_build_spec.name()
 | |
|             );
 | |
|         }
 | |
|     }
 | |
|     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
 | |
|             }
 | |
|             BuildSpec::Polymorphic(polymorphic_build_spec) => {
 | |
|                 let stream = make_polymorphic_build_fn(polymorphic_build_spec);
 | |
|                 debug_built_spec(build_spec, &stream);
 | |
|                 stream
 | |
|             }
 | |
|             BuildSpec::PolymorphicBuild(polymorphic_build_build_spec) => {
 | |
|                 let stream = make_polymorphic_build_build_fn(polymorphic_build_build_spec);
 | |
|                 debug_built_spec(build_spec, &stream);
 | |
|                 stream
 | |
|             }
 | |
|             BuildSpec::PolymorphicEnum(polymorphic_enum_build_spec) => {
 | |
|                 let stream = make_polymorphic_enum_build_fn(polymorphic_enum_build_spec);
 | |
|                 debug_built_spec(build_spec, &stream);
 | |
|                 stream
 | |
|             }
 | |
|         })
 | |
|         .collect::<Vec<_>>();
 | |
|     let combined = quote! {
 | |
|         //noinspection RsUnusedImport
 | |
|         use crate::parser::Rule;
 | |
|         //noinspection RsUnusedImport
 | |
|         use pest::iterators::Pair;
 | |
|         //noinspection RsUnusedImport
 | |
|         use crate::ast::node::*;
 | |
| 
 | |
|         #(#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))
 | |
|         .filter(Option::is_some)
 | |
|         .collect::<Vec<_>>();
 | |
|     let combined = quote! {
 | |
|         #(#types)*
 | |
|     };
 | |
|     AstGeneratedFile {
 | |
|         name: String::from("node.rs"),
 | |
|         contents: token_stream_to_string(combined),
 | |
|     }
 | |
| }
 | |
| 
 | |
| fn generate_pretty_print_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
 | |
|     let impls = build_specs
 | |
|         .iter()
 | |
|         .map(|build_spec| {
 | |
|             let stream = make_pretty_print_impl(build_spec);
 | |
|             debug_built_spec(build_spec, &stream);
 | |
|             stream
 | |
|         })
 | |
|         .collect::<Vec<_>>();
 | |
| 
 | |
|     let combined = quote! {
 | |
|         use crate::ast::node::*;
 | |
|         #(#impls)*
 | |
|     };
 | |
|     AstGeneratedFile {
 | |
|         name: String::from("pretty_print.rs"),
 | |
|         contents: token_stream_to_string(combined),
 | |
|     }
 | |
| }
 | |
| 
 | |
| pub fn generate_files(build_specs: &[BuildSpec]) -> Vec<AstGeneratedFile> {
 | |
|     vec![
 | |
|         generate_build_file(build_specs),
 | |
|         generate_node_file(build_specs),
 | |
|         generate_pretty_print_file(build_specs),
 | |
|     ]
 | |
| }
 | 
