Make polymorphic enum loop build fn.
This commit is contained in:
parent
d7b01377d7
commit
eb83d1202a
@ -1,8 +1,9 @@
|
||||
pub mod leaf_enum_build_fn;
|
||||
pub mod leaf_struct_build_fn;
|
||||
mod node_production_build_fn;
|
||||
pub mod node_production_build_fn;
|
||||
pub mod polymorphic_build_build_fn;
|
||||
pub mod polymorphic_enum_build_fn;
|
||||
pub mod polymorphic_enum_loop_build_fn;
|
||||
pub mod polymorphic_type_build_fn;
|
||||
pub mod production_build_fn;
|
||||
pub mod struct_build_fn;
|
||||
|
||||
100
ast-generator/src/build_fn/polymorphic_enum_loop_build_fn.rs
Normal file
100
ast-generator/src/build_fn/polymorphic_enum_loop_build_fn.rs
Normal file
@ -0,0 +1,100 @@
|
||||
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
||||
use crate::spec::polymorphic_enum_loop_spec::{
|
||||
PolymorphicEnumLoopBuildSpec, PolymorphicEnumLoopRule,
|
||||
PolymorphicEnumLoopRuleBuild, PolymorphicEnumLoopRuleBuildChild,
|
||||
PolymorphicEnumLoopRuleChildOnEach, PolymorphicEnumLoopRulePassThrough,
|
||||
};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
fn make_pass_through(pass_through: &PolymorphicEnumLoopRulePassThrough) -> TokenStream {
|
||||
let rule_ident = format_ident!("{}", pass_through.name());
|
||||
let inner_build_fn_ident = format_ident!("{}", pass_through.with());
|
||||
quote! {
|
||||
Rule::#rule_ident => {
|
||||
result = Some(#inner_build_fn_ident(inner_pair))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_on_each_child_build(child: &PolymorphicEnumLoopRuleChildOnEach) -> TokenStream {
|
||||
let child_build_fn_ident = format_ident!("{}", make_build_fn_name(child.rule()));
|
||||
quote! {
|
||||
#child_build_fn_ident(inner_pair)
|
||||
}
|
||||
}
|
||||
|
||||
fn make_build(
|
||||
spec: &PolymorphicEnumLoopBuildSpec,
|
||||
build: &PolymorphicEnumLoopRuleBuild,
|
||||
) -> TokenStream {
|
||||
let rule_ident = format_ident!("{}", build.name());
|
||||
let variant_type_ident = format_ident!("{}", build.name());
|
||||
let return_type_ident = format_ident!("{}", spec.kind());
|
||||
let variant_ident = format_ident!("{}", build.variant());
|
||||
|
||||
let on_each_child = build
|
||||
.children()
|
||||
.find(|child| match child {
|
||||
PolymorphicEnumLoopRuleBuildChild::OnEach(_) => true,
|
||||
_ => false,
|
||||
})
|
||||
.map(|child| {
|
||||
match child {
|
||||
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => on_each,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let build_on_each_child = make_on_each_child_build(on_each_child);
|
||||
|
||||
let child_args = build
|
||||
.children()
|
||||
.map(|child| match child {
|
||||
PolymorphicEnumLoopRuleBuildChild::UseCurrent(_) => {
|
||||
quote! { result.unwrap() }
|
||||
}
|
||||
PolymorphicEnumLoopRuleBuildChild::OnEach(_) => quote! { on_each_child },
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
Rule::#rule_ident => {
|
||||
let on_each_child = #build_on_each_child;
|
||||
let built = #variant_type_ident::new(#(#child_args),*);
|
||||
result = Some(#return_type_ident::#variant_ident(built))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_match_arm(spec: &PolymorphicEnumLoopBuildSpec, rule: &PolymorphicEnumLoopRule) -> TokenStream {
|
||||
match rule {
|
||||
PolymorphicEnumLoopRule::PassThrough(pass_through) => make_pass_through(pass_through),
|
||||
PolymorphicEnumLoopRule::Build(build) => make_build(spec, build),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_polymorphic_enum_loop_build_fn(spec: &PolymorphicEnumLoopBuildSpec) -> TokenStream {
|
||||
let build_fn_ident = format_ident!("{}", make_build_fn_name(spec.name()));
|
||||
let pair_ident = format_ident!("{}", make_build_pair(spec.name()));
|
||||
let return_type_ident = format_ident!("{}", spec.kind());
|
||||
|
||||
let match_arms = spec
|
||||
.rules()
|
||||
.map(|rule| make_match_arm(spec, rule))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||
let mut result: Option<#return_type_ident> = None;
|
||||
for inner_pair in #pair_ident.into_inner() {
|
||||
match inner_pair.as_rule() {
|
||||
#(#match_arms,)*,
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
result.unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user