Compare commits

..

8 Commits

Author SHA1 Message Date
Jesse Brault
41673a68f8 Make all tests passing. 2025-09-25 12:16:55 -05:00
Jesse Brault
86331ee9b0 Resolve all compile errors. 2025-09-25 11:57:55 -05:00
Jesse Brault
4eb48cc1a2 Fixing polymorphic enum loop build fn bug. 2025-09-24 20:40:17 -05:00
Jesse Brault
3159f119bc Add pretty print for polymorphic enum loop. 2025-09-24 20:35:19 -05:00
Jesse Brault
5a3403cc28 Add polymorphic enum loop type gen. 2025-09-24 20:29:17 -05:00
Jesse Brault
39e9c2ddd5 Squishing bugs. 2025-09-24 14:23:14 -05:00
Jesse Brault
12c565d0e1 Fix missing box. 2025-09-24 14:18:49 -05:00
Jesse Brault
8a6e4277a7 Refactor PrettyPrint. 2025-09-24 14:17:17 -05:00
12 changed files with 491 additions and 354 deletions

View File

@ -1,10 +1,10 @@
use crate::deserialize::util::make_build_pair; use crate::deserialize::util::{make_build_fn_name, make_build_pair};
use crate::spec::node_production_spec::NodeProductionBuildSpec; use crate::spec::node_production_spec::NodeProductionBuildSpec;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::{format_ident, quote}; use quote::{format_ident, quote};
pub fn make_node_production_build_fn(spec: &NodeProductionBuildSpec) -> TokenStream { pub fn make_node_production_build_fn(spec: &NodeProductionBuildSpec) -> TokenStream {
let build_fn_ident = format_ident!("{}", spec.with()); let build_fn_ident = format_ident!("{}", make_build_fn_name(spec.name()));
let pair_ident = format_ident!("{}", make_build_pair(spec.name())); let pair_ident = format_ident!("{}", make_build_pair(spec.name()));
let return_type_ident = format_ident!("{}", spec.kind()); let return_type_ident = format_ident!("{}", spec.kind());
let inner_build_fn_ident = format_ident!("{}", spec.with()); let inner_build_fn_ident = format_ident!("{}", spec.with());

View File

@ -1,8 +1,8 @@
use crate::deserialize::util::{make_build_fn_name, make_build_pair}; use crate::deserialize::util::{make_build_fn_name, make_build_pair};
use crate::spec::polymorphic_enum_loop_spec::{ use crate::spec::polymorphic_enum_loop_spec::{
PolymorphicEnumLoopBuildSpec, PolymorphicEnumLoopRule, PolymorphicEnumLoopBuildSpec, PolymorphicEnumLoopRule, PolymorphicEnumLoopRuleBuild,
PolymorphicEnumLoopRuleBuild, PolymorphicEnumLoopRuleBuildChild, PolymorphicEnumLoopRuleBuildChild, PolymorphicEnumLoopRuleChildOnEach,
PolymorphicEnumLoopRuleChildOnEach, PolymorphicEnumLoopRulePassThrough, PolymorphicEnumLoopRulePassThrough,
}; };
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::{format_ident, quote}; use quote::{format_ident, quote};
@ -20,7 +20,7 @@ fn make_pass_through(pass_through: &PolymorphicEnumLoopRulePassThrough) -> Token
fn make_on_each_child_build(child: &PolymorphicEnumLoopRuleChildOnEach) -> TokenStream { fn make_on_each_child_build(child: &PolymorphicEnumLoopRuleChildOnEach) -> TokenStream {
let child_build_fn_ident = format_ident!("{}", make_build_fn_name(child.rule())); let child_build_fn_ident = format_ident!("{}", make_build_fn_name(child.rule()));
quote! { quote! {
#child_build_fn_ident(inner_pair) Box::new(#child_build_fn_ident(inner_pair))
} }
} }
@ -29,7 +29,7 @@ fn make_build(
build: &PolymorphicEnumLoopRuleBuild, build: &PolymorphicEnumLoopRuleBuild,
) -> TokenStream { ) -> TokenStream {
let rule_ident = format_ident!("{}", build.name()); let rule_ident = format_ident!("{}", build.name());
let variant_type_ident = format_ident!("{}", build.name()); let variant_type_ident = format_ident!("{}", spec.name());
let return_type_ident = format_ident!("{}", spec.kind()); let return_type_ident = format_ident!("{}", spec.kind());
let variant_ident = format_ident!("{}", build.variant()); let variant_ident = format_ident!("{}", build.variant());
@ -39,21 +39,19 @@ fn make_build(
PolymorphicEnumLoopRuleBuildChild::OnEach(_) => true, PolymorphicEnumLoopRuleBuildChild::OnEach(_) => true,
_ => false, _ => false,
}) })
.map(|child| { .map(|child| match child {
match child { PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => on_each,
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => on_each, _ => unreachable!(),
_ => unreachable!(),
}
}) })
.unwrap(); .unwrap();
let build_on_each_child = make_on_each_child_build(on_each_child); let build_on_each_child = make_on_each_child_build(on_each_child);
let child_args = build let child_args = build
.children() .children()
.map(|child| match child { .map(|child| match child {
PolymorphicEnumLoopRuleBuildChild::UseCurrent(_) => { PolymorphicEnumLoopRuleBuildChild::UseCurrent(_) => {
quote! { result.unwrap() } quote! { Box::new(result.unwrap()) }
} }
PolymorphicEnumLoopRuleBuildChild::OnEach(_) => quote! { on_each_child }, PolymorphicEnumLoopRuleBuildChild::OnEach(_) => quote! { on_each_child },
}) })
@ -68,7 +66,10 @@ fn make_build(
} }
} }
fn make_match_arm(spec: &PolymorphicEnumLoopBuildSpec, rule: &PolymorphicEnumLoopRule) -> TokenStream { fn make_match_arm(
spec: &PolymorphicEnumLoopBuildSpec,
rule: &PolymorphicEnumLoopRule,
) -> TokenStream {
match rule { match rule {
PolymorphicEnumLoopRule::PassThrough(pass_through) => make_pass_through(pass_through), PolymorphicEnumLoopRule::PassThrough(pass_through) => make_pass_through(pass_through),
PolymorphicEnumLoopRule::Build(build) => make_build(spec, build), PolymorphicEnumLoopRule::Build(build) => make_build(spec, build),
@ -80,6 +81,12 @@ pub fn make_polymorphic_enum_loop_build_fn(spec: &PolymorphicEnumLoopBuildSpec)
let pair_ident = format_ident!("{}", make_build_pair(spec.name())); let pair_ident = format_ident!("{}", make_build_pair(spec.name()));
let return_type_ident = format_ident!("{}", spec.kind()); let return_type_ident = format_ident!("{}", spec.kind());
let iter_expr = if spec.reverse() {
quote! { #pair_ident.into_inner().rev() }
} else {
quote! { #pair_ident.into_inner() }
};
let match_arms = spec let match_arms = spec
.rules() .rules()
.map(|rule| make_match_arm(spec, rule)) .map(|rule| make_match_arm(spec, rule))
@ -88,10 +95,10 @@ pub fn make_polymorphic_enum_loop_build_fn(spec: &PolymorphicEnumLoopBuildSpec)
quote! { quote! {
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident { fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
let mut result: Option<#return_type_ident> = None; let mut result: Option<#return_type_ident> = None;
for inner_pair in #pair_ident.into_inner() { for inner_pair in #iter_expr {
match inner_pair.as_rule() { match inner_pair.as_rule() {
#(#match_arms,)* #(#match_arms,)*
_ => unreachable!() _ => unreachable!("Unexpected parse rule: {:?} (inner pair: {:#?}", inner_pair.as_rule(), inner_pair),
} }
} }
result.unwrap() result.unwrap()

View File

@ -1,4 +1,4 @@
use crate::deserialize::util::{make_build_fn_name, unwrap_single_member_hash}; use crate::deserialize::util::{get_as_bool, make_build_fn_name, unwrap_single_member_hash};
use crate::spec::polymorphic_enum_loop_spec::{ use crate::spec::polymorphic_enum_loop_spec::{
PolymorphicEnumLoopBuildSpec, PolymorphicEnumLoopChildUseCurrent, PolymorphicEnumLoopRule, PolymorphicEnumLoopBuildSpec, PolymorphicEnumLoopChildUseCurrent, PolymorphicEnumLoopRule,
PolymorphicEnumLoopRuleBuild, PolymorphicEnumLoopRuleBuildChild, PolymorphicEnumLoopRuleBuild, PolymorphicEnumLoopRuleBuildChild,
@ -62,6 +62,8 @@ fn deserialize_rule(rule_name: &str, props: &Yaml) -> PolymorphicEnumLoopRule {
pub fn deserialize_polymorphic_enum_loop(name: &str, props: &Yaml) -> PolymorphicEnumLoopBuildSpec { pub fn deserialize_polymorphic_enum_loop(name: &str, props: &Yaml) -> PolymorphicEnumLoopBuildSpec {
let kind = props["kind"].as_str().unwrap(); let kind = props["kind"].as_str().unwrap();
let reverse = get_as_bool(&props["reverse"]);
let rules = props["rules"] let rules = props["rules"]
.as_vec() .as_vec()
.unwrap() .unwrap()
@ -73,5 +75,5 @@ pub fn deserialize_polymorphic_enum_loop(name: &str, props: &Yaml) -> Polymorphi
.map(Box::new) .map(Box::new)
.collect(); .collect();
PolymorphicEnumLoopBuildSpec::new(name, kind, rules) PolymorphicEnumLoopBuildSpec::new(name, kind, reverse, rules)
} }

View File

@ -38,7 +38,7 @@ fn deserialize_member_build(child_name: &str, rule: &str, props: &Yaml) -> Membe
let kind = node_props["kind"].as_str().unwrap_or(rule); let kind = node_props["kind"].as_str().unwrap_or(rule);
let with = node_props["with"] let with = node_props["with"]
.as_str() .as_str()
.map(ToString::to_string) .map(|with| make_build_fn_name(with))
.unwrap_or_else(|| make_build_fn_name(kind)); .unwrap_or_else(|| make_build_fn_name(kind));
let or_else = if get_as_bool(&node_props["or_else_default"]) { let or_else = if get_as_bool(&node_props["or_else_default"]) {

View File

@ -6,7 +6,7 @@ mod type_gen;
use crate::build_fn::make_build_fn; use crate::build_fn::make_build_fn;
use crate::deserialize::deserialize_yaml_spec; 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 crate::type_gen::make_type;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::quote; use quote::quote;
@ -117,24 +117,27 @@ fn generate_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
} }
fn generate_pretty_print_file(build_specs: &[BuildSpec]) -> AstGeneratedFile { fn generate_pretty_print_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
// let impls = build_specs let impls = build_specs
// .iter() .iter()
// .map(|build_spec| { .map(|build_spec| {
// let stream = make_pretty_print_impl(build_spec); let maybe_stream = make_pretty_print_impl(build_spec);
// debug_built_spec(build_spec, &stream); if let Some(stream) = &maybe_stream {
// stream debug_built_spec(build_spec, &stream);
// }) }
// .collect::<Vec<_>>(); maybe_stream
// })
// let combined = quote! { .filter(Option::is_some)
// use crate::ast::node::*; .map(Option::unwrap)
// #(#impls)* .collect::<Vec<_>>();
// };
// AstGeneratedFile { let combined = quote! {
// name: String::from("pretty_print.rs"), use crate::ast::node::*;
// contents: token_stream_to_string(combined), #(#impls)*
// } };
todo!() AstGeneratedFile {
name: String::from("pretty_print.rs"),
contents: token_stream_to_string(combined),
}
} }
pub fn get_build_specs(yaml: &str) -> Vec<BuildSpec> { pub fn get_build_specs(yaml: &str) -> Vec<BuildSpec> {
@ -145,6 +148,6 @@ pub fn generate_files(build_specs: &[BuildSpec]) -> Vec<AstGeneratedFile> {
vec![ vec![
generate_build_file(build_specs), generate_build_file(build_specs),
generate_node_file(build_specs), generate_node_file(build_specs),
// generate_pretty_print_file(build_specs), generate_pretty_print_file(build_specs),
] ]
} }

View File

@ -1,260 +1,265 @@
// use crate::spec::leaf_enum_spec::LeafEnumBuildSpec; use crate::spec::leaf_enum_spec::LeafEnumBuildSpec;
// use crate::spec::leaf_struct_spec::{LeafStructBuildSpec, LeafStructMemberKind}; use crate::spec::leaf_struct_spec::{LeafStructBuildSpec, LeafStructMemberKind};
// use crate::spec::polymorphic_type_spec::PolymorphicTypeBuildSpec; use crate::spec::polymorphic_type_spec::PolymorphicTypeBuildSpec;
// use crate::spec::production_spec::ProductionBuildSpec; use crate::spec::struct_spec::{MemberChildBuild, StructChild, StructSpec, VecChildBuild};
// use crate::spec::struct_spec::StructSpec; use crate::spec::tree_enum_spec::{EnumRuleChildKind, TreeEnumBuildSpec};
// use crate::spec::tree_enum_spec::{EnumRuleChildKind, TreeEnumBuildSpec}; use crate::spec::BuildSpec;
// use crate::spec::{ use convert_case::{Case, Casing};
// AlternativeChild, BuildSpec, MemberChildToBuild, PolymorphicBuildBuildSpec, use proc_macro2::TokenStream;
// PolymorphicEnumBuildSpec, StructChildSpec, VecChildToBuild, use quote::{format_ident, quote};
// }; use crate::spec::polymorphic_enum_loop_spec::{PolymorphicEnumLoopBuildSpec, PolymorphicEnumLoopRule, PolymorphicEnumLoopRuleBuildChild};
// use convert_case::{Case, Casing};
// use proc_macro2::TokenStream; fn make_polymorphic_enum_loop_p2_impl(spec: &PolymorphicEnumLoopBuildSpec) -> TokenStream {
// use quote::{format_ident, quote}; let type_ident = format_ident!("{}", spec.name());
// let type_string = spec.name();
// fn make_production_p2_impl(_spec: &ProductionBuildSpec) -> TokenStream {
// quote! {} let build = spec.rules()
// } .find(|rule| {
// match rule {
// fn make_polymorphic_enum_p2_impl(_spec: &PolymorphicEnumBuildSpec) -> TokenStream { PolymorphicEnumLoopRule::Build(_) => true,
// quote! {} _ => false
// } }
// })
// fn make_polymorphic_build_p2_impl(spec: &PolymorphicBuildBuildSpec) -> TokenStream { .map(|rule| {
// let (_, build) = spec.primary_alternative(); match rule {
// let type_ident = format_ident!("{}", spec.name()); PolymorphicEnumLoopRule::Build(build) => build,
// let name_str = spec.name(); _ => unreachable!()
// }
// let child_statements = build })
// .children() .unwrap();
// .map(|child| match child {
// AlternativeChild::Skip => None, let child_print_statements = build.children()
// AlternativeChild::Build(build) => { .map(|child| {
// let child_ident = format_ident!("{}", build.name()); let child_ident = match child {
// Some(quote! { PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
// self.#child_ident().pretty_print(writer)? format_ident!("{}", use_current.name())
// }) }
// } PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
// }) format_ident!("{}", on_each.name())
// .filter(Option::is_some) }
// .map(Option::unwrap) };
// .collect::<Vec<TokenStream>>(); quote! {
// self.#child_ident().pretty_print(writer)?;
// quote! { }
// impl PrettyPrint for #type_ident { })
// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { .collect::<Vec<_>>();
// writer.writeln_indented(#name_str);
// writer.increase_indent(); quote! {
// #(#child_statements;)* impl PrettyPrint for #type_ident {
// writer.decrease_indent(); fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
// Ok(()) writer.writeln_indented(#type_string)?;
// } writer.increase_indent();
// } #(#child_print_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| { fn make_polymorphic_type_p2_impl(spec: &PolymorphicTypeBuildSpec) -> TokenStream {
// let enum_member_ident = format_ident!("{}", member.name()); let type_ident = format_ident!("{}", spec.name());
// let inner_name = format_ident!("{}", member.inner_kind().to_case(Case::Snake)); let child_matchers = spec
// quote! { .variants()
// #type_ident::#enum_member_ident(#inner_name) => #inner_name.pretty_print(writer) .map(|member| {
// } let enum_member_ident = format_ident!("{}", member.name());
// }) let inner_name = format_ident!("{}", member.inner_kind().to_case(Case::Snake));
// .collect::<Vec<_>>(); quote! {
// #type_ident::#enum_member_ident(#inner_name) => #inner_name.pretty_print(writer)
// quote! { }
// impl PrettyPrint for #type_ident { })
// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { .collect::<Vec<_>>();
// match self {
// #(#child_matchers,)* 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| { fn make_leaf_enum_p2_impl(spec: &LeafEnumBuildSpec) -> TokenStream {
// let enum_variant_ident = format_ident!("{}", rule.rule()); let type_ident = format_ident!("{}", spec.build());
// let name_str = rule.rule(); let child_matchers = spec
// quote! { .rules()
// #type_ident::#enum_variant_ident => writer.writeln_indented(#name_str) .map(|rule| {
// } let enum_variant_ident = format_ident!("{}", rule);
// }) let name_str = rule;
// .collect::<Vec<_>>(); quote! {
// #type_ident::#enum_variant_ident => writer.writeln_indented(#name_str)
// quote! { }
// impl PrettyPrint for #type_ident { })
// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { .collect::<Vec<_>>();
// match self {
// #(#child_matchers,)* 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 fn make_tree_enum_p2_impl(spec: &TreeEnumBuildSpec) -> TokenStream {
// .rules() let type_ident = format_ident!("{}", spec.build());
// .map(|rule| { let type_str = spec.build();
// let enum_variant_ident = format_ident!("{}", rule.rule());
// if let Some(child) = rule.child() { let child_matchers = spec
// match child.kind() { .rules()
// EnumRuleChildKind::Node(node_child) => { .map(|rule| {
// let child_name_ident = let enum_variant_ident = format_ident!("{}", rule.rule());
// format_ident!("{}", node_child.build().to_case(Case::Snake)); if let Some(child) = rule.child() {
// Some(quote! { match child.kind() {
// #type_ident::#enum_variant_ident(#child_name_ident) => { EnumRuleChildKind::Node(node_child) => {
// #child_name_ident.pretty_print(writer)?; let child_name_ident =
// } format_ident!("{}", node_child.node_kind().to_case(Case::Snake));
// }) Some(quote! {
// } #type_ident::#enum_variant_ident(#child_name_ident) => {
// _ => None, #child_name_ident.pretty_print(writer)?;
// } }
// } else { })
// let variant_str = rule.rule(); }
// Some(quote! { _ => None,
// #type_ident::#enum_variant_ident => writer.writeln_indented(#variant_str)? }
// }) } else {
// } let variant_str = rule.rule();
// }) Some(quote! {
// .filter(Option::is_some) #type_ident::#enum_variant_ident => writer.writeln_indented(#variant_str)?
// .map(Option::unwrap) })
// .collect::<Vec<_>>(); }
// })
// quote! { .filter(Option::is_some)
// impl PrettyPrint for #type_ident { .map(Option::unwrap)
// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { .collect::<Vec<_>>();
// writer.writeln_indented(#type_str)?;
// writer.increase_indent(); quote! {
// match self { impl PrettyPrint for #type_ident {
// #(#child_matchers,)* fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
// _ => {} writer.writeln_indented(#type_str)?;
// } writer.increase_indent();
// writer.decrease_indent(); match self {
// Ok(()) #(#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() { fn make_leaf_struct_p2_impl(leaf_struct_build_spec: &LeafStructBuildSpec) -> TokenStream {
// LeafStructMemberKind::String => Some("{}"), let type_ident = format_ident!("{}", leaf_struct_build_spec.build());
// }) let member_formatters = leaf_struct_build_spec
// .filter(Option::is_some) .members()
// .map(Option::unwrap) .map(|member| match member.kind() {
// .collect::<Vec<_>>() LeafStructMemberKind::String => Some("{}"),
// .join(", "); })
// .filter(Option::is_some)
// let format_string = format!("{}({})", leaf_struct_build_spec.build(), member_formatters); .map(Option::unwrap)
// .collect::<Vec<_>>()
// let members = leaf_struct_build_spec .join(", ");
// .members()
// .map(|member| { let format_string = format!("{}({})", leaf_struct_build_spec.build(), member_formatters);
// let member_ident = format_ident!("{}", member.name());
// quote! { let members = leaf_struct_build_spec
// self.#member_ident() .members()
// } .map(|member| {
// }) let member_ident = format_ident!("{}", member.name());
// .collect::<Vec<_>>(); quote! {
// self.#member_ident()
// quote! { }
// impl PrettyPrint for #type_ident { })
// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { .collect::<Vec<_>>();
// writer.writeln_indented(&format!(#format_string, #(#members),*))
// } 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, fn make_struct_p2_impl(struct_build_spec: &StructSpec) -> TokenStream {
// StructChildSpec::VecChild(vec_child) => match vec_child.build() { let child_print_statements = struct_build_spec
// VecChildToBuild::Node(_) => { .children()
// let child_ident = format_ident!("{}", vec_child.name()); .map(|child| match child {
// Some(quote! { StructChild::SkipChild(_) => None,
// for child in self.#child_ident() { StructChild::VecChild(vec_child) => match vec_child.build() {
// child.pretty_print(writer)?; VecChildBuild::Node(_) => {
// } let child_ident = format_ident!("{}", vec_child.name());
// }) Some(quote! {
// } for child in self.#child_ident() {
// VecChildToBuild::String => None, child.pretty_print(writer)?;
// }, }
// StructChildSpec::MemberChild(member_child) => match member_child.build() { })
// MemberChildToBuild::Node(node_member_child) => { }
// let child_ident = format_ident!("{}", member_child.name()); VecChildBuild::String(_) => None,
// if node_member_child.optional() { },
// Some(quote! { StructChild::MemberChild(member_child) => match member_child.build() {
// if let Some(child) = self.#child_ident() { MemberChildBuild::Node(_) => {
// child.pretty_print(writer)?; let child_ident = format_ident!("{}", member_child.name());
// } if member_child.optional() {
// }) Some(quote! {
// } else { if let Some(child) = self.#child_ident() {
// Some(quote! { child.pretty_print(writer)?;
// self.#child_ident().pretty_print(writer)?; }
// }) })
// } } else {
// } Some(quote! {
// MemberChildToBuild::Boolean(boolean_member_child) => { self.#child_ident().pretty_print(writer)?;
// 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()))?; MemberChildBuild::Boolean(_) => {
// }) let format_string = format!("{}({})", member_child.name(), "{}");
// } let child_ident = format_ident!("{}", member_child.name());
// }, Some(quote! {
// }) writer.writeln_indented(&format!(#format_string, self.#child_ident()))?;
// .filter(Option::is_some) })
// .map(Option::unwrap) }
// .collect::<Vec<_>>(); },
// })
// let type_ident = format_ident!("{}", struct_build_spec.build()); .filter(Option::is_some)
// let type_string = struct_build_spec.build(); .map(Option::unwrap)
// .collect::<Vec<_>>();
// quote! {
// impl PrettyPrint for #type_ident { let type_ident = format_ident!("{}", struct_build_spec.build());
// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { let type_string = struct_build_spec.build();
// writer.writeln_indented(#type_string)?;
// writer.increase_indent(); quote! {
// #(#child_print_statements)* impl PrettyPrint for #type_ident {
// writer.decrease_indent(); fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
// Ok(()) 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), pub fn make_pretty_print_impl(build_spec: &BuildSpec) -> Option<TokenStream> {
// BuildSpec::LeafEnum(leaf_enum) => make_leaf_enum_p2_impl(leaf_enum), match build_spec {
// BuildSpec::PolymorphicType(polymorphic) => make_polymorphic_type_p2_impl(polymorphic), BuildSpec::Struct(struct_spec) => Some(make_struct_p2_impl(struct_spec)),
// BuildSpec::PolymorphicBuild(polymorphic_build) => { BuildSpec::LeafStruct(leaf_struct) => Some(make_leaf_struct_p2_impl(leaf_struct)),
// make_polymorphic_build_p2_impl(polymorphic_build) BuildSpec::Enum(enum_spec) => Some(make_tree_enum_p2_impl(enum_spec)),
// } BuildSpec::LeafEnum(leaf_enum) => Some(make_leaf_enum_p2_impl(leaf_enum)),
// BuildSpec::PolymorphicEnum(polymorphic_enum) => { BuildSpec::Production(_) => None,
// make_polymorphic_enum_p2_impl(polymorphic_enum) BuildSpec::NodeProduction(_) => None,
// } BuildSpec::PolymorphicType(polymorphic_type) => {
// BuildSpec::Production(production) => make_production_p2_impl(production), Some(make_polymorphic_type_p2_impl(polymorphic_type))
// } }
// } BuildSpec::PolymorphicPassThrough(_) => None,
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
Some(make_polymorphic_enum_loop_p2_impl(polymorphic_enum_loop))
},
}
}

View File

@ -1,14 +1,16 @@
pub struct PolymorphicEnumLoopBuildSpec { pub struct PolymorphicEnumLoopBuildSpec {
name: String, name: String,
kind: String, kind: String,
reverse: bool,
rules: Vec<Box<PolymorphicEnumLoopRule>>, rules: Vec<Box<PolymorphicEnumLoopRule>>,
} }
impl PolymorphicEnumLoopBuildSpec { impl PolymorphicEnumLoopBuildSpec {
pub fn new(name: &str, kind: &str, rules: Vec<Box<PolymorphicEnumLoopRule>>) -> Self { pub fn new(name: &str, kind: &str, reverse: bool, rules: Vec<Box<PolymorphicEnumLoopRule>>) -> Self {
Self { Self {
name: name.to_string(), name: name.to_string(),
kind: kind.to_string(), kind: kind.to_string(),
reverse,
rules, rules,
} }
} }
@ -20,6 +22,10 @@ impl PolymorphicEnumLoopBuildSpec {
pub fn kind(&self) -> &str { pub fn kind(&self) -> &str {
&self.kind &self.kind
} }
pub fn reverse(&self) -> bool {
self.reverse
}
pub fn rules(&self) -> impl Iterator<Item = &PolymorphicEnumLoopRule> { pub fn rules(&self) -> impl Iterator<Item = &PolymorphicEnumLoopRule> {
self.rules.iter().map(Box::as_ref) self.rules.iter().map(Box::as_ref)

View File

@ -1,6 +1,7 @@
mod enum_type; mod enum_type;
mod leaf_enum_type; mod leaf_enum_type;
mod leaf_struct_type; mod leaf_struct_type;
mod polymorphic_enum_loop_type;
mod polymorphic_type_type; mod polymorphic_type_type;
mod struct_type; mod struct_type;
@ -11,6 +12,7 @@ use crate::type_gen::leaf_struct_type::make_leaf_struct_type;
use crate::type_gen::polymorphic_type_type::make_polymorphic_type_type; use crate::type_gen::polymorphic_type_type::make_polymorphic_type_type;
use crate::type_gen::struct_type::make_struct_type; use crate::type_gen::struct_type::make_struct_type;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use crate::type_gen::polymorphic_enum_loop_type::make_polymorphic_enum_loop_type;
pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> { pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> {
match build_spec { match build_spec {
@ -27,7 +29,9 @@ pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> {
BuildSpec::PolymorphicType(polymorphic_build_spec) => { BuildSpec::PolymorphicType(polymorphic_build_spec) => {
Some(make_polymorphic_type_type(polymorphic_build_spec)) Some(make_polymorphic_type_type(polymorphic_build_spec))
} }
BuildSpec::PolymorphicEnumLoop(_) => None, BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop_spec) => {
Some(make_polymorphic_enum_loop_type(polymorphic_enum_loop_spec))
},
BuildSpec::PolymorphicPassThrough(_) => None, BuildSpec::PolymorphicPassThrough(_) => None,
} }
} }

View File

@ -0,0 +1,96 @@
use crate::spec::polymorphic_enum_loop_spec::{PolymorphicEnumLoopBuildSpec, PolymorphicEnumLoopRule, PolymorphicEnumLoopRuleBuildChild};
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
pub fn make_polymorphic_enum_loop_type(spec: &PolymorphicEnumLoopBuildSpec) -> TokenStream {
let type_ident = format_ident!("{}", spec.name());
let build = spec.rules()
.find(|rule| {
match rule {
PolymorphicEnumLoopRule::Build(_) => true,
_ => false
}
})
.map(|rule| {
match rule {
PolymorphicEnumLoopRule::Build(build) => build,
_ => unreachable!()
}
})
.unwrap();
let annotated_members = build.children()
.map(|child| {
match child {
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
let child_ident = format_ident!("{}", use_current.name());
let child_type_ident = format_ident!("{}", use_current.kind());
quote! {
#child_ident: Box<#child_type_ident>
}
}
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
let child_ident = format_ident!("{}", on_each.name());
let child_type_ident = format_ident!("{}", on_each.rule());
quote! {
#child_ident: Box<#child_type_ident>
}
}
}
})
.collect::<Vec<_>>();
let member_names = build.children()
.map(|child| {
match child {
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
format_ident!("{}", use_current.name())
}
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
format_ident!("{}", on_each.name())
}
}
})
.collect::<Vec<_>>();
let accessors = build.children()
.map(|child| {
let (child_ident, child_type_ident) = match child {
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
(format_ident!("{}", use_current.name()), format_ident!("{}", use_current.kind()))
}
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
(format_ident!("{}", on_each.name()), format_ident!("{}", on_each.rule()))
}
};
let child_mut_ident = format_ident!("{}_mut", child_ident);
quote! {
pub fn #child_ident(&self) -> &#child_type_ident {
self.#child_ident.as_ref()
}
pub fn #child_mut_ident(&mut self) -> &mut #child_type_ident {
self.#child_ident.as_mut()
}
}
})
.collect::<Vec<_>>();
quote! {
pub struct #type_ident {
#(#annotated_members),*
}
impl #type_ident {
pub fn new(#(#annotated_members),*) -> Self {
Self {
#(#member_names),*
}
}
#(#accessors)*
}
}
}

View File

@ -1,4 +1,6 @@
use crate::spec::struct_spec::{MemberChild, MemberChildBuild, StructChild, StructSpec, VecChild, VecChildBuild}; use crate::spec::struct_spec::{
MemberChild, MemberChildBuild, StructChild, StructSpec, VecChild, VecChildBuild,
};
use proc_macro2::{Ident, TokenStream}; use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote}; use quote::{format_ident, quote};
@ -11,18 +13,18 @@ fn make_vec_child_accessors(vec_child: &VecChild) -> TokenStream {
self.#child_ident.iter().map(String::as_str) self.#child_ident.iter().map(String::as_str)
} }
} }
}, }
VecChildBuild::Node(vec_child_node_build) => { VecChildBuild::Node(vec_child_node_build) => {
let child_type_ident = format_ident!("{}", vec_child_node_build.kind()); let child_type_ident = format_ident!("{}", vec_child_node_build.kind());
let child_ident_mut = format_ident!("{}_mut", vec_child.name()); let child_ident_mut = format_ident!("{}_mut", vec_child.name());
quote! { quote! {
pub fn #child_ident(&self) -> impl Iterator<Item = &#child_type_ident> { pub fn #child_ident(&self) -> impl Iterator<Item = &#child_type_ident> {
self.#child_ident.iter().map(Box::as_ref) self.#child_ident.iter().map(Box::as_ref)
} }
pub fn #child_ident_mut(&mut self) -> impl Iterator<Item = &mut child_type_ident> { pub fn #child_ident_mut(&mut self) -> impl Iterator<Item = &mut #child_type_ident> {
self.#child_ident.iter().map(Box::as_mut) self.#child_ident.iter_mut().map(Box::as_mut)
} }
} }
} }
@ -35,7 +37,7 @@ fn make_member_child_accessors(member_child: &MemberChild) -> TokenStream {
MemberChildBuild::Node(node_member_build) => { MemberChildBuild::Node(node_member_build) => {
let return_type_ident = format_ident!("{}", node_member_build.kind()); let return_type_ident = format_ident!("{}", node_member_build.kind());
let child_ident_mut = format_ident!("{}_mut", member_child.name()); let child_ident_mut = format_ident!("{}_mut", member_child.name());
if member_child.optional() { if member_child.optional() {
quote! { quote! {
pub fn #child_ident(&self) -> Option<&#return_type_ident> { pub fn #child_ident(&self) -> Option<&#return_type_ident> {
@ -45,7 +47,7 @@ fn make_member_child_accessors(member_child: &MemberChild) -> TokenStream {
None None
} }
} }
pub fn #child_ident_mut(&mut self) -> Option<&mut #return_type_ident> { pub fn #child_ident_mut(&mut self) -> Option<&mut #return_type_ident> {
if let Some(#child_ident) = &mut self.#child_ident { if let Some(#child_ident) = &mut self.#child_ident {
Some(#child_ident.as_mut()) Some(#child_ident.as_mut())
@ -59,7 +61,7 @@ fn make_member_child_accessors(member_child: &MemberChild) -> TokenStream {
pub fn #child_ident(&self) -> &#return_type_ident { pub fn #child_ident(&self) -> &#return_type_ident {
self.#child_ident.as_ref() self.#child_ident.as_ref()
} }
pub fn #child_ident_mut(&mut self) -> &mut #return_type_ident { pub fn #child_ident_mut(&mut self) -> &mut #return_type_ident {
self.#child_ident.as_mut() self.#child_ident.as_mut()
} }
@ -79,24 +81,16 @@ fn make_member_child_accessors(member_child: &MemberChild) -> TokenStream {
fn make_accessors(child: &StructChild) -> Option<TokenStream> { fn make_accessors(child: &StructChild) -> Option<TokenStream> {
match child { match child {
StructChild::SkipChild(_) => None, StructChild::SkipChild(_) => None,
StructChild::VecChild(vec_child) => { StructChild::VecChild(vec_child) => Some(make_vec_child_accessors(vec_child)),
Some(make_vec_child_accessors(vec_child)) StructChild::MemberChild(member_child) => Some(make_member_child_accessors(member_child)),
}
StructChild::MemberChild(member_child) => {
Some(make_member_child_accessors(member_child))
}
} }
} }
fn make_member_ident(child: &StructChild) -> Option<Ident> { fn make_member_ident(child: &StructChild) -> Option<Ident> {
match child { match child {
StructChild::SkipChild(_) => None, StructChild::SkipChild(_) => None,
StructChild::VecChild(vec_child) => { StructChild::VecChild(vec_child) => Some(format_ident!("{}", vec_child.name())),
Some(format_ident!("{}", vec_child.name())) StructChild::MemberChild(member_child) => Some(format_ident!("{}", member_child.name())),
},
StructChild::MemberChild(member_child) => {
Some(format_ident!("{}", member_child.name()))
}
} }
} }
@ -107,9 +101,9 @@ fn make_vec_child_annotated_member(vec_child: &VecChild) -> TokenStream {
VecChildBuild::Node(vec_child_node_build) => { VecChildBuild::Node(vec_child_node_build) => {
let type_ident = format_ident!("{}", vec_child_node_build.kind()); let type_ident = format_ident!("{}", vec_child_node_build.kind());
quote! { Box<#type_ident> } quote! { Box<#type_ident> }
}, }
}; };
quote! { quote! {
#child_ident: Vec<#type_stream> #child_ident: Vec<#type_stream>
} }
@ -119,8 +113,8 @@ fn make_member_child_type_ident(member_child: &MemberChild) -> TokenStream {
match member_child.build() { match member_child.build() {
MemberChildBuild::Node(node_member_build) => { MemberChildBuild::Node(node_member_build) => {
let type_ident = format_ident!("{}", node_member_build.kind()); let type_ident = format_ident!("{}", node_member_build.kind());
quote! { #type_ident } quote! { Box<#type_ident> }
}, }
MemberChildBuild::Boolean(_) => { MemberChildBuild::Boolean(_) => {
quote! { bool } quote! { bool }
} }
@ -133,9 +127,9 @@ fn make_member_child_annotated_member(member_child: &MemberChild) -> TokenStream
let type_stream = if member_child.optional() { let type_stream = if member_child.optional() {
quote! { Option<#type_ident> } quote! { Option<#type_ident> }
} else { } else {
type_ident quote! { #type_ident }
}; };
quote! { quote! {
#child_name_ident: #type_stream #child_name_ident: #type_stream
} }
@ -145,36 +139,35 @@ fn make_annotated_member(child: &StructChild) -> Option<TokenStream> {
match child { match child {
StructChild::SkipChild(_) => None, StructChild::SkipChild(_) => None,
StructChild::VecChild(vec_child) => Some(make_vec_child_annotated_member(vec_child)), StructChild::VecChild(vec_child) => Some(make_vec_child_annotated_member(vec_child)),
StructChild::MemberChild(member_child) => Some(make_member_child_annotated_member(member_child)), StructChild::MemberChild(member_child) => {
Some(make_member_child_annotated_member(member_child))
}
} }
} }
pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream { pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream {
let type_ident = format_ident!("{}", build_spec.build()); let type_ident = format_ident!("{}", build_spec.build());
let annotated_members = build_spec.children() let annotated_members = build_spec
.map(|child| { .children()
make_annotated_member(child) .map(|child| make_annotated_member(child))
})
.filter(Option::is_some) .filter(Option::is_some)
.map(Option::unwrap) .map(Option::unwrap)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let member_names = build_spec.children() let member_names = build_spec
.map(|child| { .children()
make_member_ident(child) .map(|child| make_member_ident(child))
})
.filter(Option::is_some) .filter(Option::is_some)
.map(Option::unwrap) .map(Option::unwrap)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let accessors = build_spec.children() let accessors = build_spec
.map(|child| { .children()
make_accessors(child) .map(|child| make_accessors(child))
})
.filter(Option::is_some) .filter(Option::is_some)
.map(Option::unwrap) .map(Option::unwrap)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
quote! { quote! {
pub struct #type_ident { pub struct #type_ident {
#(#annotated_members),* #(#annotated_members),*

View File

@ -342,6 +342,8 @@ $defs:
properties: properties:
kind: kind:
type: string type: string
reverse:
type: boolean
rules: rules:
type: array type: array
items: items:

View File

@ -863,6 +863,10 @@ ComparisonRhs:
- expression: - expression:
member: member:
rule: ShiftExpression rule: ShiftExpression
build:
node:
kind: Expression
with: ShiftExpression
ComparisonOperator: ComparisonOperator:
leaf_enum: leaf_enum:
rules: rules:
@ -899,6 +903,10 @@ ShiftRhs:
- expression: - expression:
member: member:
rule: AdditiveExpression rule: AdditiveExpression
build:
node:
kind: Expression
with: AdditiveExpression
ShiftOperator: ShiftOperator:
leaf_enum: leaf_enum:
rules: rules:
@ -911,6 +919,7 @@ AdditiveExpression:
- MultiplicativeExpression: - MultiplicativeExpression:
pass_through: pass_through:
kind: Expression kind: Expression
with: MultiplicativeExpression
- AdditiveRhs: - AdditiveRhs:
build: build:
variant: Additive variant: Additive
@ -930,6 +939,10 @@ AdditiveRhs:
- expression: - expression:
member: member:
rule: MultiplicativeExpression rule: MultiplicativeExpression
build:
node:
kind: Expression
with: MultiplicativeExpression
AdditiveOperator: AdditiveOperator:
leaf_enum: leaf_enum:
rules: rules:
@ -942,6 +955,7 @@ MultiplicativeExpression:
- PrefixExpression: - PrefixExpression:
pass_through: pass_through:
kind: Expression kind: Expression
with: PrefixExpression
- MultiplicativeRhs: - MultiplicativeRhs:
build: build:
variant: Multiplicative variant: Multiplicative
@ -961,6 +975,10 @@ MultiplicativeRhs:
- expression: - expression:
member: member:
rule: PrefixExpression rule: PrefixExpression
build:
node:
kind: Expression
with: PrefixExpression
MultiplicativeOperator: MultiplicativeOperator:
leaf_enum: leaf_enum:
rules: rules:
@ -970,17 +988,18 @@ MultiplicativeOperator:
PrefixExpression: PrefixExpression:
polymorphic_enum_loop_build: polymorphic_enum_loop_build:
kind: Expression kind: Expression
reverse: true
rules: rules:
- PrefixOperator: - PrefixOperator:
build: build:
variant: Prefix variant: Prefix
children: children:
- operator: - operator:
use_current: on_each:
kind: Expression rule: PrefixOperator
- expression: - expression:
on_each: use_current:
rule: SuffixExpression kind: Expression
- SuffixExpression: - SuffixExpression:
pass_through: pass_through:
kind: Expression kind: Expression
@ -1008,7 +1027,7 @@ SuffixExpression:
kind: Expression kind: Expression
- operator: - operator:
on_each: on_each:
rule: SuffixExpression rule: SuffixOperator
SuffixOperator: SuffixOperator:
tree_enum: tree_enum:
rules: rules:
@ -1041,7 +1060,7 @@ PrimaryExpression:
- Closure: - Closure:
inner: inner:
kind: Closure kind: Closure
- ListExpression: - List:
inner: inner:
kind: ListExpression kind: ListExpression
- ParenthesizedExpression: - ParenthesizedExpression:
@ -1052,9 +1071,9 @@ ListExpression:
children: children:
- expression_list - expression_list
ParenthesizedExpression: ParenthesizedExpression:
struct: node_production:
children: kind: Expression
- expression with: Expression
# Calls # Calls
Call: Call: