use convert_case::{Case, Casing}; use crate::spec::tree_enum_spec::{EnumRuleChildKind, TreeEnumBuildSpec}; use proc_macro2::TokenStream; use quote::{format_ident, quote}; pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream { let type_ident = format_ident!("{}", enum_spec.build()); let match_arms = enum_spec .rules() .map(|rule| { let rule_ident = format_ident!("{}", rule.rule()); match rule.child() { Some(child) => { match child.kind() { EnumRuleChildKind::Node(node_child) => { let child_ident = format_ident!("{}", node_child.node_kind().to_case(Case::Snake)); quote! { #type_ident::#rule_ident(#child_ident) => vec![ #child_ident.as_node_ref() ] } } _ => quote! { #type_ident::#rule_ident(_) => vec![] } } }, None => { quote! { #type_ident::#rule_ident => vec![] } } } }) .collect::>(); quote! { impl AstNode for #type_ident { fn children(&self) -> Vec { match self { #(#match_arms,)* } } fn as_node_ref(&self) -> AstNodeRef { AstNodeRef::#type_ident(&self) } } } }