Add walk impl.
This commit is contained in:
parent
dd0bee1c91
commit
5b772443f8
@ -4,6 +4,7 @@ mod deserialize;
|
||||
mod pretty_print;
|
||||
mod spec;
|
||||
mod type_gen;
|
||||
mod walk;
|
||||
|
||||
use crate::ast_node::{make_ast_enum_member, make_ast_node_impl};
|
||||
use crate::build_fn::make_build_fn;
|
||||
@ -14,6 +15,7 @@ use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use spec::BuildSpec;
|
||||
use syn::File;
|
||||
use crate::walk::make_walk_fn;
|
||||
|
||||
fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
|
||||
println!("*** BuildSpec ***");
|
||||
@ -184,6 +186,14 @@ fn generate_ast_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_walk_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
||||
let stream = make_walk_fn(build_specs);
|
||||
AstGeneratedFile {
|
||||
name: String::from("walk.rs"),
|
||||
contents: token_stream_to_string(stream),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_build_specs(yaml: &str) -> Vec<BuildSpec> {
|
||||
deserialize_yaml_spec(yaml)
|
||||
}
|
||||
@ -194,5 +204,6 @@ pub fn generate_files(build_specs: &[BuildSpec]) -> Vec<AstGeneratedFile> {
|
||||
generate_node_file(build_specs),
|
||||
generate_pretty_print_file(build_specs),
|
||||
generate_ast_node_file(build_specs),
|
||||
generate_walk_file(build_specs),
|
||||
]
|
||||
}
|
||||
|
||||
60
ast-generator/src/walk.rs
Normal file
60
ast-generator/src/walk.rs
Normal file
@ -0,0 +1,60 @@
|
||||
use crate::spec::BuildSpec;
|
||||
use convert_case::{Case, Casing};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
pub fn make_walk_fn(specs: &[BuildSpec]) -> TokenStream {
|
||||
let child_match_arms = specs
|
||||
.iter()
|
||||
.map(|spec| match spec {
|
||||
BuildSpec::Enum(enum_spec) => Some((
|
||||
format_ident!("{}", enum_spec.build()),
|
||||
format_ident!("{}", enum_spec.build().to_case(Case::Snake)),
|
||||
)),
|
||||
BuildSpec::LeafEnum(leaf_enum) => Some((
|
||||
format_ident!("{}", leaf_enum.build()),
|
||||
format_ident!("{}", leaf_enum.build().to_case(Case::Snake)),
|
||||
)),
|
||||
BuildSpec::Struct(struct_spec) => Some((
|
||||
format_ident!("{}", struct_spec.build()),
|
||||
format_ident!("{}", struct_spec.build().to_case(Case::Snake)),
|
||||
)),
|
||||
BuildSpec::LeafStruct(leaf_struct) => Some((
|
||||
format_ident!("{}", leaf_struct.build()),
|
||||
format_ident!("{}", leaf_struct.build().to_case(Case::Snake)),
|
||||
)),
|
||||
BuildSpec::Production(_) => None,
|
||||
BuildSpec::NodeProduction(_) => None,
|
||||
BuildSpec::PolymorphicType(polymorphic_type) => Some((
|
||||
format_ident!("{}", polymorphic_type.name()),
|
||||
format_ident!("{}", polymorphic_type.name().to_case(Case::Snake)),
|
||||
)),
|
||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => Some((
|
||||
format_ident!("{}", polymorphic_enum_loop.name()),
|
||||
format_ident!("{}", polymorphic_enum_loop.name().to_case(Case::Snake)),
|
||||
)),
|
||||
BuildSpec::PolymorphicPassThrough(_) => None,
|
||||
})
|
||||
.filter(Option::is_some)
|
||||
.map(Option::unwrap)
|
||||
.map(|(type_ident, inner_ident)| {
|
||||
quote! {
|
||||
#type_ident(#inner_ident) => walk_depth_first(#inner_ident, f)
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
use crate::ast::node::*;
|
||||
use crate::ast::ast_node::*;
|
||||
|
||||
pub fn walk_depth_first(node: &impl AstNode, f: &mut impl FnMut(AstNodeRef)) {
|
||||
use AstNodeRef::*;
|
||||
for child in node.children() {
|
||||
match child {
|
||||
#(#child_match_arms,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -161,3 +161,7 @@ pub mod ast_node {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod walk {
|
||||
include!(concat!(env!("OUT_DIR"), "/src/ast/walk.rs"));
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user