deimos-lang/ast-generator/src/production_build_fn.rs
2025-09-17 17:21:37 -05:00

96 lines
3.4 KiB
Rust

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::<i32>().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::<i64>().unwrap()
}
_ => panic!()
}
},
ProductionKind::Double => quote! {
#pair_ident.as_str().parse::<f64>().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::<bool>().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<Rule>) -> #return_type_ident {
#pair_mapper
}
}
}