diff --git a/ast-generator/src/ast_node/enum_ast_node.rs b/ast-generator/src/ast_node/enum_ast_node.rs index 66e579d..43a12fd 100644 --- a/ast-generator/src/ast_node/enum_ast_node.rs +++ b/ast-generator/src/ast_node/enum_ast_node.rs @@ -1,6 +1,50 @@ -use crate::spec::tree_enum_spec::TreeEnumBuildSpec; +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 { - todo!() + 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) + } + } + } } diff --git a/ast-generator/src/ast_node/leaf_enum_ast_node.rs b/ast-generator/src/ast_node/leaf_enum_ast_node.rs index 0e71db0..cdb0f02 100644 --- a/ast-generator/src/ast_node/leaf_enum_ast_node.rs +++ b/ast-generator/src/ast_node/leaf_enum_ast_node.rs @@ -1,6 +1,18 @@ use proc_macro2::TokenStream; +use quote::{format_ident, quote}; use crate::spec::leaf_enum_spec::LeafEnumBuildSpec; pub fn make_leaf_enum_ast_node_impl(spec: &LeafEnumBuildSpec) -> TokenStream { - todo!() + let type_ident = format_ident!("{}", spec.build()); + quote! { + impl AstNode for #type_ident { + fn children(&self) -> Vec { + vec![] + } + + fn as_node_ref(&self) -> AstNodeRef { + AstNodeRef::#type_ident(&self) + } + } + } } \ No newline at end of file diff --git a/ast-generator/src/ast_node/leaf_struct_ast_node.rs b/ast-generator/src/ast_node/leaf_struct_ast_node.rs index e449ed4..20440b4 100644 --- a/ast-generator/src/ast_node/leaf_struct_ast_node.rs +++ b/ast-generator/src/ast_node/leaf_struct_ast_node.rs @@ -1,6 +1,18 @@ -use proc_macro2::TokenStream; use crate::spec::leaf_struct_spec::LeafStructBuildSpec; +use proc_macro2::TokenStream; +use quote::{format_ident, quote}; pub fn make_leaf_struct_ast_node_impl(spec: &LeafStructBuildSpec) -> TokenStream { - todo!() -} \ No newline at end of file + let type_ident = format_ident!("{}", spec.build()); + quote! { + impl AstNode for #type_ident { + fn children(&self) -> Vec { + vec![] + } + + fn as_node_ref(&self) -> AstNodeRef { + AstNodeRef::#type_ident(&self) + } + } + } +} diff --git a/ast-generator/src/ast_node/polymorphic_enum_loop_ast_node.rs b/ast-generator/src/ast_node/polymorphic_enum_loop_ast_node.rs index 3f374eb..01e8fde 100644 --- a/ast-generator/src/ast_node/polymorphic_enum_loop_ast_node.rs +++ b/ast-generator/src/ast_node/polymorphic_enum_loop_ast_node.rs @@ -1,6 +1,49 @@ +use crate::spec::polymorphic_enum_loop_spec::{ + PolymorphicEnumLoopBuildSpec, PolymorphicEnumLoopRule, PolymorphicEnumLoopRuleBuildChild, +}; use proc_macro2::TokenStream; -use crate::spec::polymorphic_enum_loop_spec::PolymorphicEnumLoopBuildSpec; +use quote::{format_ident, quote}; -pub fn make_polymorphic_enum_loop_ast_node_impl(spec: &PolymorphicEnumLoopBuildSpec) -> TokenStream { - todo!() -} \ No newline at end of file +pub fn make_polymorphic_enum_loop_ast_node_impl( + spec: &PolymorphicEnumLoopBuildSpec, +) -> TokenStream { + let type_ident = format_ident!("{}", spec.name()); + let build_rule = spec + .rules() + .filter_map(|rule| match rule { + PolymorphicEnumLoopRule::PassThrough(_) => None, + PolymorphicEnumLoopRule::Build(build_rule) => Some(build_rule), + }) + .next() + .unwrap(); + let child_adders = build_rule + .children() + .map(|child| { + let child_ident = match child { + PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => { + format_ident!("{}", use_current.name()) + } + PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => { + format_ident!("{}", on_each.name()) + } + }; + quote! { + children.push(self.#child_ident().as_node_ref()) + } + }) + .collect::>(); + + quote! { + impl AstNode for #type_ident { + fn children(&self) -> Vec { + let mut children: Vec = vec![]; + #(#child_adders;)* + children + } + + fn as_node_ref(&self) -> AstNodeRef { + AstNodeRef::#type_ident(&self) + } + } + } +} diff --git a/ast-generator/src/ast_node/polymorphic_type_ast_node.rs b/ast-generator/src/ast_node/polymorphic_type_ast_node.rs index 250359f..2df90ee 100644 --- a/ast-generator/src/ast_node/polymorphic_type_ast_node.rs +++ b/ast-generator/src/ast_node/polymorphic_type_ast_node.rs @@ -1,6 +1,32 @@ -use proc_macro2::TokenStream; use crate::spec::polymorphic_type_spec::PolymorphicTypeBuildSpec; +use convert_case::{Case, Casing}; +use proc_macro2::TokenStream; +use quote::{format_ident, quote}; pub fn make_polymorphic_type_ast_node_impl(spec: &PolymorphicTypeBuildSpec) -> TokenStream { - todo!() -} \ No newline at end of file + let type_ident = format_ident!("{}", spec.name()); + let match_arms = spec + .variants() + .map(|variant| { + let variant_ident = format_ident!("{}", variant.name()); + let child_ident = format_ident!("{}", variant.inner_kind().to_case(Case::Snake)); + quote! { + #type_ident::#variant_ident(#child_ident) => vec![#child_ident] + } + }) + .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) + } + } + } +}