use crate::spec::{ProductionBuildSpec, ProductionKind, ProductionStringFrom}; use crate::util::{make_build_fn_name, make_build_pair}; use proc_macro2::TokenStream; use quote::{format_ident, quote}; pub fn make_production_build_fn(production_build_spec: &ProductionBuildSpec) -> TokenStream { let build_fn_ident = format_ident!("{}", make_build_fn_name(production_build_spec.rule())); let return_type_ident = match production_build_spec.kind() { ProductionKind::Int => format_ident!("i32"), ProductionKind::Long => format_ident!("i64"), ProductionKind::Double => format_ident!("f64"), ProductionKind::String(_) => format_ident!("String"), ProductionKind::Boolean => format_ident!("bool"), ProductionKind::Node(node_type) => format_ident!("{}", node_type), }; let pair_ident = format_ident!("{}", make_build_pair(production_build_spec.rule())); let pair_mapper = match production_build_spec.kind() { ProductionKind::Int => quote! { let number_base_pair = #pair_ident.into_inner() .next() .unwrap(); let inner_number_base_pair = number_base_pair.into_inner() .next() .unwrap(); match inner_number_base_pair.as_rule() { Rule::BinaryBase => { todo!() } Rule::HexadecimalBase => { todo!() } Rule::DecimalBase => { inner_number_base_pair.as_str().parse::().unwrap() } _ => panic!() } }, ProductionKind::Long => quote! { let number_base_pair = #pair_ident.into_inner() .next() .unwrap(); let inner_number_base_pair = number_base_pair.into_inner() .next() .unwrap(); match inner_number_base_pair.as_rule() { Rule::BinaryBase => { todo!() } Rule::HexadecimalBase => { todo!() } Rule::DecimalBase => { inner_number_base_pair.as_str().parse::().unwrap() } _ => panic!() } }, ProductionKind::Double => quote! { #pair_ident.as_str().parse::().unwrap() }, ProductionKind::String(from) => match from { ProductionStringFrom::StringInner => { quote! { #pair_ident.into_inner() .next() .unwrap() .as_str() .to_string() } } ProductionStringFrom::WholePair => { quote! { #pair_ident.as_str().to_string() } } }, ProductionKind::Boolean => quote! { #pair_ident.as_str().parse::().unwrap() }, ProductionKind::Node(node_type) => { let build_fn_ident = format_ident!("{}", make_build_fn_name(node_type)); quote! { let inner_pair = #pair_ident.into_inner().next().unwrap(); #build_fn_ident(inner_pair) } } }; quote! { fn #build_fn_ident(#pair_ident: Pair) -> #return_type_ident { #pair_mapper } } }