Add walk impl.
This commit is contained in:
parent
dd0bee1c91
commit
5b772443f8
@ -4,6 +4,7 @@ mod deserialize;
|
|||||||
mod pretty_print;
|
mod pretty_print;
|
||||||
mod spec;
|
mod spec;
|
||||||
mod type_gen;
|
mod type_gen;
|
||||||
|
mod walk;
|
||||||
|
|
||||||
use crate::ast_node::{make_ast_enum_member, make_ast_node_impl};
|
use crate::ast_node::{make_ast_enum_member, make_ast_node_impl};
|
||||||
use crate::build_fn::make_build_fn;
|
use crate::build_fn::make_build_fn;
|
||||||
@ -14,6 +15,7 @@ use proc_macro2::TokenStream;
|
|||||||
use quote::quote;
|
use quote::quote;
|
||||||
use spec::BuildSpec;
|
use spec::BuildSpec;
|
||||||
use syn::File;
|
use syn::File;
|
||||||
|
use crate::walk::make_walk_fn;
|
||||||
|
|
||||||
fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
|
fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
|
||||||
println!("*** BuildSpec ***");
|
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> {
|
pub fn get_build_specs(yaml: &str) -> Vec<BuildSpec> {
|
||||||
deserialize_yaml_spec(yaml)
|
deserialize_yaml_spec(yaml)
|
||||||
}
|
}
|
||||||
@ -194,5 +204,6 @@ pub fn generate_files(build_specs: &[BuildSpec]) -> Vec<AstGeneratedFile> {
|
|||||||
generate_node_file(build_specs),
|
generate_node_file(build_specs),
|
||||||
generate_pretty_print_file(build_specs),
|
generate_pretty_print_file(build_specs),
|
||||||
generate_ast_node_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