49 lines
1.9 KiB
Rust
49 lines
1.9 KiB
Rust
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
|
use crate::spec::tree_enum_spec::{EnumRuleChildKind, TreeEnumBuildSpec};
|
|
use proc_macro2::TokenStream;
|
|
use quote::{format_ident, quote};
|
|
|
|
pub fn make_enum_build_fn(enum_build_spec: &TreeEnumBuildSpec) -> TokenStream {
|
|
let build_fn_ident = format_ident!("{}", make_build_fn_name(enum_build_spec.build()));
|
|
let pair_ident = format_ident!("{}", make_build_pair(enum_build_spec.build()));
|
|
let return_type_ident = format_ident!("{}", enum_build_spec.build());
|
|
|
|
let rule_branches = enum_build_spec
|
|
.rules()
|
|
.map(|enum_rule| {
|
|
let rule_ident = format_ident!("{}", enum_rule.rule());
|
|
if let Some(child) = enum_rule.child() {
|
|
let inner_builder = match child.kind() {
|
|
EnumRuleChildKind::Node(node_child) => {
|
|
let inner_build_fn_ident =
|
|
format_ident!("{}", make_build_fn_name(node_child.build()));
|
|
quote! { #inner_build_fn_ident(inner_pair) }
|
|
}
|
|
_ => {
|
|
let inner_build_fn_ident =
|
|
format_ident!("{}", make_build_fn_name(enum_rule.rule()));
|
|
quote! { #inner_build_fn_ident(inner_pair) }
|
|
}
|
|
};
|
|
quote! {
|
|
Rule::#rule_ident => #return_type_ident::#rule_ident(#inner_builder)
|
|
}
|
|
} else {
|
|
quote! {
|
|
Rule::#rule_ident => #return_type_ident::#rule_ident
|
|
}
|
|
}
|
|
})
|
|
.collect::<Vec<_>>();
|
|
|
|
quote! {
|
|
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
|
|
let inner_pair = #pair_ident.into_inner().next().unwrap();
|
|
match inner_pair.as_rule() {
|
|
#(#rule_branches,)*
|
|
_ => unreachable!()
|
|
}
|
|
}
|
|
}
|
|
}
|