deimos-lang/ast-generator/src/lib.rs
2025-09-21 11:19:27 -05:00

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),
]
}