diff --git a/ast-generator/src/deserialize/polymorphic_enum_loop_spec.rs b/ast-generator/src/deserialize/polymorphic_enum_loop_spec.rs index a26c3c9..1768300 100644 --- a/ast-generator/src/deserialize/polymorphic_enum_loop_spec.rs +++ b/ast-generator/src/deserialize/polymorphic_enum_loop_spec.rs @@ -40,7 +40,10 @@ fn deserialize_build(name: &str, props: &Yaml) -> PolymorphicEnumLoopRuleBuild { fn deserialize_pass_through(name: &str, props: &Yaml) -> PolymorphicEnumLoopRulePassThrough { let kind = props["kind"].as_str().unwrap(); - let with = make_build_fn_name(props["with"].as_str().unwrap()); + let with = make_build_fn_name( + props["with"].as_str() + .unwrap_or(kind) + ); PolymorphicEnumLoopRulePassThrough::new(name, kind, &with) } diff --git a/ast-generator/src/lib.rs b/ast-generator/src/lib.rs index c04572a..863322e 100644 --- a/ast-generator/src/lib.rs +++ b/ast-generator/src/lib.rs @@ -6,7 +6,7 @@ mod type_gen; use crate::build_fn::make_build_fn; use crate::deserialize::deserialize_yaml_spec; -use crate::pretty_print::make_pretty_print_impl; +// use crate::pretty_print::make_pretty_print_impl; use crate::type_gen::make_type; use proc_macro2::TokenStream; use quote::quote; @@ -35,7 +35,10 @@ fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) { println!("Production Spec - name: {}", production_build_spec.name()); } BuildSpec::NodeProduction(node_production_build_spec) => { - println!("Node Production Spec - name: {}", node_production_build_spec.name()); + println!( + "Node Production Spec - name: {}", + node_production_build_spec.name() + ); } BuildSpec::PolymorphicType(polymorphic_build_spec) => { println!( @@ -80,7 +83,7 @@ fn generate_build_file(build_specs: &[BuildSpec]) -> AstGeneratedFile { build_fn }) .collect::>(); - + let combined = quote! { //noinspection RsUnusedImport use crate::parser::Rule; @@ -91,7 +94,7 @@ fn generate_build_file(build_specs: &[BuildSpec]) -> AstGeneratedFile { #(#build_fns)* }; - + AstGeneratedFile { name: String::from("build.rs"), contents: token_stream_to_string(combined), @@ -114,23 +117,24 @@ fn generate_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile { } 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::>(); - - let combined = quote! { - use crate::ast::node::*; - #(#impls)* - }; - AstGeneratedFile { - name: String::from("pretty_print.rs"), - contents: token_stream_to_string(combined), - } + // let impls = build_specs + // .iter() + // .map(|build_spec| { + // let stream = make_pretty_print_impl(build_spec); + // debug_built_spec(build_spec, &stream); + // stream + // }) + // .collect::>(); + // + // let combined = quote! { + // use crate::ast::node::*; + // #(#impls)* + // }; + // AstGeneratedFile { + // name: String::from("pretty_print.rs"), + // contents: token_stream_to_string(combined), + // } + todo!() } pub fn get_build_specs(yaml: &str) -> Vec { @@ -141,6 +145,6 @@ pub fn generate_files(build_specs: &[BuildSpec]) -> Vec { vec![ generate_build_file(build_specs), generate_node_file(build_specs), - generate_pretty_print_file(build_specs), + // generate_pretty_print_file(build_specs), ] } diff --git a/ast-generator/src/pretty_print.rs b/ast-generator/src/pretty_print.rs index 77f744b..8429283 100644 --- a/ast-generator/src/pretty_print.rs +++ b/ast-generator/src/pretty_print.rs @@ -1,256 +1,260 @@ -use crate::spec::{ - AlternativeChild, BuildSpec, EnumBuildSpec, EnumRuleChildKind, LeafEnumBuildSpec, - LeafStructBuildSpec, LeafStructMemberKind, MemberChildToBuild, PolymorphicBuildBuildSpec, - PolymorphicEnumBuildSpec, PolymorphicTypeBuildSpec, ProductionBuildSpec, StructBuildSpec, - StructChildSpec, VecChildToBuild, -}; -use convert_case::{Case, Casing}; -use proc_macro2::TokenStream; -use quote::{format_ident, quote}; - -fn make_production_p2_impl(_spec: &ProductionBuildSpec) -> TokenStream { - quote! {} -} - -fn make_polymorphic_enum_p2_impl(_spec: &PolymorphicEnumBuildSpec) -> TokenStream { - quote! {} -} - -fn make_polymorphic_build_p2_impl(spec: &PolymorphicBuildBuildSpec) -> TokenStream { - let (_, build) = spec.primary_alternative(); - let type_ident = format_ident!("{}", spec.name()); - let name_str = spec.name(); - - let child_statements = build - .children() - .map(|child| match child { - AlternativeChild::Skip => None, - AlternativeChild::Build(build) => { - let child_ident = format_ident!("{}", build.name()); - Some(quote! { - self.#child_ident().pretty_print(writer)? - }) - } - }) - .filter(Option::is_some) - .map(Option::unwrap) - .collect::>(); - - quote! { - impl PrettyPrint for #type_ident { - fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { - writer.writeln_indented(#name_str); - writer.increase_indent(); - #(#child_statements;)* - writer.decrease_indent(); - Ok(()) - } - } - } -} - -fn make_polymorphic_type_p2_impl(spec: &PolymorphicTypeBuildSpec) -> TokenStream { - let type_ident = format_ident!("{}", spec.name()); - let child_matchers = spec - .enum_members() - .map(|member| { - let enum_member_ident = format_ident!("{}", member.name()); - let inner_name = format_ident!("{}", member.inner_kind().to_case(Case::Snake)); - quote! { - #type_ident::#enum_member_ident(#inner_name) => #inner_name.pretty_print(writer) - } - }) - .collect::>(); - - quote! { - impl PrettyPrint for #type_ident { - fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { - match self { - #(#child_matchers,)* - } - } - } - } -} - -fn make_leaf_enum_p2_impl(spec: &LeafEnumBuildSpec) -> TokenStream { - let type_ident = format_ident!("{}", spec.build()); - let child_matchers = spec - .rules() - .map(|rule| { - let enum_variant_ident = format_ident!("{}", rule.rule()); - let name_str = rule.rule(); - quote! { - #type_ident::#enum_variant_ident => writer.writeln_indented(#name_str) - } - }) - .collect::>(); - - quote! { - impl PrettyPrint for #type_ident { - fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { - match self { - #(#child_matchers,)* - } - } - } - } -} - -fn make_enum_p2_impl(spec: &EnumBuildSpec) -> TokenStream { - let type_ident = format_ident!("{}", spec.build()); - let type_str = spec.build(); - - let child_matchers = spec - .rules() - .map(|rule| { - let enum_variant_ident = format_ident!("{}", rule.rule()); - if let Some(child) = rule.child() { - match child.kind() { - EnumRuleChildKind::Node(node_child) => { - let child_name_ident = - format_ident!("{}", node_child.build().to_case(Case::Snake)); - Some(quote! { - #type_ident::#enum_variant_ident(#child_name_ident) => { - #child_name_ident.pretty_print(writer)?; - } - }) - } - _ => None, - } - } else { - let variant_str = rule.rule(); - Some(quote! { - #type_ident::#enum_variant_ident => writer.writeln_indented(#variant_str)? - }) - } - }) - .filter(Option::is_some) - .map(Option::unwrap) - .collect::>(); - - quote! { - impl PrettyPrint for #type_ident { - fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { - writer.writeln_indented(#type_str)?; - writer.increase_indent(); - match self { - #(#child_matchers,)* - _ => {} - } - writer.decrease_indent(); - Ok(()) - } - } - } -} - -fn make_leaf_struct_p2_impl(leaf_struct_build_spec: &LeafStructBuildSpec) -> TokenStream { - let type_ident = format_ident!("{}", leaf_struct_build_spec.build()); - let member_formatters = leaf_struct_build_spec - .members() - .map(|member| match member.kind() { - LeafStructMemberKind::String => Some("{}"), - }) - .filter(Option::is_some) - .map(Option::unwrap) - .collect::>() - .join(", "); - - let format_string = format!("{}({})", leaf_struct_build_spec.build(), member_formatters); - - let members = leaf_struct_build_spec - .members() - .map(|member| { - let member_ident = format_ident!("{}", member.name()); - quote! { - self.#member_ident() - } - }) - .collect::>(); - - quote! { - impl PrettyPrint for #type_ident { - fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { - writer.writeln_indented(&format!(#format_string, #(#members),*)) - } - } - } -} - -fn make_struct_p2_impl(struct_build_spec: &StructBuildSpec) -> TokenStream { - let child_print_statements = struct_build_spec - .children() - .map(|child| match child { - StructChildSpec::SkipChild(_) => None, - StructChildSpec::VecChild(vec_child) => match vec_child.build() { - VecChildToBuild::Node(_) => { - let child_ident = format_ident!("{}", vec_child.name()); - Some(quote! { - for child in self.#child_ident() { - child.pretty_print(writer)?; - } - }) - } - VecChildToBuild::String => None, - }, - StructChildSpec::MemberChild(member_child) => match member_child.build() { - MemberChildToBuild::Node(node_member_child) => { - let child_ident = format_ident!("{}", member_child.name()); - if node_member_child.optional() { - Some(quote! { - if let Some(child) = self.#child_ident() { - child.pretty_print(writer)?; - } - }) - } else { - Some(quote! { - self.#child_ident().pretty_print(writer)?; - }) - } - } - MemberChildToBuild::Boolean(boolean_member_child) => { - let format_string = format!("{}({})", boolean_member_child.name(), "{}"); - let child_ident = format_ident!("{}", boolean_member_child.name()); - Some(quote! { - writer.writeln_indented(&format!(#format_string, self.#child_ident()))?; - }) - } - }, - }) - .filter(Option::is_some) - .map(Option::unwrap) - .collect::>(); - - let type_ident = format_ident!("{}", struct_build_spec.build()); - let type_string = struct_build_spec.build(); - - quote! { - impl PrettyPrint for #type_ident { - fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { - writer.writeln_indented(#type_string)?; - writer.increase_indent(); - #(#child_print_statements)* - writer.decrease_indent(); - Ok(()) - } - } - } -} - -pub fn make_pretty_print_impl(build_spec: &BuildSpec) -> TokenStream { - match build_spec { - BuildSpec::Struct(struct_spec) => make_struct_p2_impl(struct_spec), - BuildSpec::LeafStruct(leaf_struct) => make_leaf_struct_p2_impl(leaf_struct), - BuildSpec::Enum(enum_spec) => make_enum_p2_impl(enum_spec), - BuildSpec::LeafEnum(leaf_enum) => make_leaf_enum_p2_impl(leaf_enum), - BuildSpec::Polymorphic(polymorphic) => make_polymorphic_type_p2_impl(polymorphic), - BuildSpec::PolymorphicBuild(polymorphic_build) => { - make_polymorphic_build_p2_impl(polymorphic_build) - } - BuildSpec::PolymorphicEnum(polymorphic_enum) => { - make_polymorphic_enum_p2_impl(polymorphic_enum) - } - BuildSpec::Production(production) => make_production_p2_impl(production), - } -} +// use crate::spec::leaf_enum_spec::LeafEnumBuildSpec; +// use crate::spec::leaf_struct_spec::{LeafStructBuildSpec, LeafStructMemberKind}; +// use crate::spec::polymorphic_type_spec::PolymorphicTypeBuildSpec; +// use crate::spec::production_spec::ProductionBuildSpec; +// use crate::spec::struct_spec::StructSpec; +// use crate::spec::tree_enum_spec::{EnumRuleChildKind, TreeEnumBuildSpec}; +// use crate::spec::{ +// AlternativeChild, BuildSpec, MemberChildToBuild, PolymorphicBuildBuildSpec, +// PolymorphicEnumBuildSpec, StructChildSpec, VecChildToBuild, +// }; +// use convert_case::{Case, Casing}; +// use proc_macro2::TokenStream; +// use quote::{format_ident, quote}; +// +// fn make_production_p2_impl(_spec: &ProductionBuildSpec) -> TokenStream { +// quote! {} +// } +// +// fn make_polymorphic_enum_p2_impl(_spec: &PolymorphicEnumBuildSpec) -> TokenStream { +// quote! {} +// } +// +// fn make_polymorphic_build_p2_impl(spec: &PolymorphicBuildBuildSpec) -> TokenStream { +// let (_, build) = spec.primary_alternative(); +// let type_ident = format_ident!("{}", spec.name()); +// let name_str = spec.name(); +// +// let child_statements = build +// .children() +// .map(|child| match child { +// AlternativeChild::Skip => None, +// AlternativeChild::Build(build) => { +// let child_ident = format_ident!("{}", build.name()); +// Some(quote! { +// self.#child_ident().pretty_print(writer)? +// }) +// } +// }) +// .filter(Option::is_some) +// .map(Option::unwrap) +// .collect::>(); +// +// quote! { +// impl PrettyPrint for #type_ident { +// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { +// writer.writeln_indented(#name_str); +// writer.increase_indent(); +// #(#child_statements;)* +// writer.decrease_indent(); +// Ok(()) +// } +// } +// } +// } +// +// fn make_polymorphic_type_p2_impl(spec: &PolymorphicTypeBuildSpec) -> TokenStream { +// let type_ident = format_ident!("{}", spec.name()); +// let child_matchers = spec +// .variants() +// .map(|member| { +// let enum_member_ident = format_ident!("{}", member.name()); +// let inner_name = format_ident!("{}", member.inner_kind().to_case(Case::Snake)); +// quote! { +// #type_ident::#enum_member_ident(#inner_name) => #inner_name.pretty_print(writer) +// } +// }) +// .collect::>(); +// +// quote! { +// impl PrettyPrint for #type_ident { +// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { +// match self { +// #(#child_matchers,)* +// } +// } +// } +// } +// } +// +// fn make_leaf_enum_p2_impl(spec: &LeafEnumBuildSpec) -> TokenStream { +// let type_ident = format_ident!("{}", spec.build()); +// let child_matchers = spec +// .rules() +// .map(|rule| { +// let enum_variant_ident = format_ident!("{}", rule.rule()); +// let name_str = rule.rule(); +// quote! { +// #type_ident::#enum_variant_ident => writer.writeln_indented(#name_str) +// } +// }) +// .collect::>(); +// +// quote! { +// impl PrettyPrint for #type_ident { +// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { +// match self { +// #(#child_matchers,)* +// } +// } +// } +// } +// } +// +// fn make_enum_p2_impl(spec: &TreeEnumBuildSpec) -> TokenStream { +// let type_ident = format_ident!("{}", spec.build()); +// let type_str = spec.build(); +// +// let child_matchers = spec +// .rules() +// .map(|rule| { +// let enum_variant_ident = format_ident!("{}", rule.rule()); +// if let Some(child) = rule.child() { +// match child.kind() { +// EnumRuleChildKind::Node(node_child) => { +// let child_name_ident = +// format_ident!("{}", node_child.build().to_case(Case::Snake)); +// Some(quote! { +// #type_ident::#enum_variant_ident(#child_name_ident) => { +// #child_name_ident.pretty_print(writer)?; +// } +// }) +// } +// _ => None, +// } +// } else { +// let variant_str = rule.rule(); +// Some(quote! { +// #type_ident::#enum_variant_ident => writer.writeln_indented(#variant_str)? +// }) +// } +// }) +// .filter(Option::is_some) +// .map(Option::unwrap) +// .collect::>(); +// +// quote! { +// impl PrettyPrint for #type_ident { +// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { +// writer.writeln_indented(#type_str)?; +// writer.increase_indent(); +// match self { +// #(#child_matchers,)* +// _ => {} +// } +// writer.decrease_indent(); +// Ok(()) +// } +// } +// } +// } +// +// fn make_leaf_struct_p2_impl(leaf_struct_build_spec: &LeafStructBuildSpec) -> TokenStream { +// let type_ident = format_ident!("{}", leaf_struct_build_spec.build()); +// let member_formatters = leaf_struct_build_spec +// .members() +// .map(|member| match member.kind() { +// LeafStructMemberKind::String => Some("{}"), +// }) +// .filter(Option::is_some) +// .map(Option::unwrap) +// .collect::>() +// .join(", "); +// +// let format_string = format!("{}({})", leaf_struct_build_spec.build(), member_formatters); +// +// let members = leaf_struct_build_spec +// .members() +// .map(|member| { +// let member_ident = format_ident!("{}", member.name()); +// quote! { +// self.#member_ident() +// } +// }) +// .collect::>(); +// +// quote! { +// impl PrettyPrint for #type_ident { +// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { +// writer.writeln_indented(&format!(#format_string, #(#members),*)) +// } +// } +// } +// } +// +// fn make_struct_p2_impl(struct_build_spec: &StructSpec) -> TokenStream { +// let child_print_statements = struct_build_spec +// .children() +// .map(|child| match child { +// StructChildSpec::SkipChild(_) => None, +// StructChildSpec::VecChild(vec_child) => match vec_child.build() { +// VecChildToBuild::Node(_) => { +// let child_ident = format_ident!("{}", vec_child.name()); +// Some(quote! { +// for child in self.#child_ident() { +// child.pretty_print(writer)?; +// } +// }) +// } +// VecChildToBuild::String => None, +// }, +// StructChildSpec::MemberChild(member_child) => match member_child.build() { +// MemberChildToBuild::Node(node_member_child) => { +// let child_ident = format_ident!("{}", member_child.name()); +// if node_member_child.optional() { +// Some(quote! { +// if let Some(child) = self.#child_ident() { +// child.pretty_print(writer)?; +// } +// }) +// } else { +// Some(quote! { +// self.#child_ident().pretty_print(writer)?; +// }) +// } +// } +// MemberChildToBuild::Boolean(boolean_member_child) => { +// let format_string = format!("{}({})", boolean_member_child.name(), "{}"); +// let child_ident = format_ident!("{}", boolean_member_child.name()); +// Some(quote! { +// writer.writeln_indented(&format!(#format_string, self.#child_ident()))?; +// }) +// } +// }, +// }) +// .filter(Option::is_some) +// .map(Option::unwrap) +// .collect::>(); +// +// let type_ident = format_ident!("{}", struct_build_spec.build()); +// let type_string = struct_build_spec.build(); +// +// quote! { +// impl PrettyPrint for #type_ident { +// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { +// writer.writeln_indented(#type_string)?; +// writer.increase_indent(); +// #(#child_print_statements)* +// writer.decrease_indent(); +// Ok(()) +// } +// } +// } +// } +// +// pub fn make_pretty_print_impl(build_spec: &BuildSpec) -> TokenStream { +// match build_spec { +// BuildSpec::Struct(struct_spec) => make_struct_p2_impl(struct_spec), +// BuildSpec::LeafStruct(leaf_struct) => make_leaf_struct_p2_impl(leaf_struct), +// BuildSpec::Enum(enum_spec) => make_enum_p2_impl(enum_spec), +// BuildSpec::LeafEnum(leaf_enum) => make_leaf_enum_p2_impl(leaf_enum), +// BuildSpec::PolymorphicType(polymorphic) => make_polymorphic_type_p2_impl(polymorphic), +// BuildSpec::PolymorphicBuild(polymorphic_build) => { +// make_polymorphic_build_p2_impl(polymorphic_build) +// } +// BuildSpec::PolymorphicEnum(polymorphic_enum) => { +// make_polymorphic_enum_p2_impl(polymorphic_enum) +// } +// BuildSpec::Production(production) => make_production_p2_impl(production), +// } +// } diff --git a/build.rs b/build.rs index de92dc2..96f819c 100644 --- a/build.rs +++ b/build.rs @@ -1,4 +1,4 @@ -use ast_generator::{deserialize, generate_files}; +use ast_generator::{get_build_specs, generate_files}; use cst_test_generator::generate_test_files; use std::env; use std::fs; @@ -19,7 +19,7 @@ fn generate_ast_files(out_dir: &Path) -> io::Result<()> { fs::create_dir_all(&gen_ast_dir)?; let ast_yaml = include_str!("src/parser/ast.yaml"); - let build_specs = deserialize::deserialize_yaml_spec(ast_yaml); + let build_specs = get_build_specs(ast_yaml); let generated_files = generate_files(&build_specs); for generated_file in &generated_files { let path = gen_ast_dir.join(&generated_file.name);