Add support for polymorphic enum builds (used for suffix operators).
This commit is contained in:
parent
7439ca554c
commit
f21128fd68
@ -1,6 +1,7 @@
|
||||
mod enum_ast_node;
|
||||
mod leaf_enum_ast_node;
|
||||
mod leaf_struct_ast_node;
|
||||
mod polymorphic_enum_inner_build_ast_node;
|
||||
mod polymorphic_enum_loop_ast_node;
|
||||
mod polymorphic_type_ast_node;
|
||||
mod struct_ast_node;
|
||||
@ -8,6 +9,7 @@ mod struct_ast_node;
|
||||
use crate::ast_node::enum_ast_node::make_enum_ast_node_impl;
|
||||
use crate::ast_node::leaf_enum_ast_node::make_leaf_enum_ast_node_impl;
|
||||
use crate::ast_node::leaf_struct_ast_node::make_leaf_struct_ast_node_impl;
|
||||
use crate::ast_node::polymorphic_enum_inner_build_ast_node::make_polymorphic_enum_inner_build_ast_node_impl;
|
||||
use crate::ast_node::polymorphic_enum_loop_ast_node::make_polymorphic_enum_loop_ast_node_impl;
|
||||
use crate::ast_node::polymorphic_type_ast_node::make_polymorphic_type_ast_node_impl;
|
||||
use crate::ast_node::struct_ast_node::make_struct_ast_node_impl;
|
||||
@ -30,6 +32,11 @@ pub fn make_ast_node_impl(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||
make_polymorphic_enum_loop_ast_node_impl(polymorphic_enum_loop),
|
||||
),
|
||||
BuildSpec::PolymorphicPassThrough(_) => None,
|
||||
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build) => Some(
|
||||
make_polymorphic_enum_inner_build_ast_node_impl(polymorphic_enum_inner_build),
|
||||
),
|
||||
BuildSpec::PolymorphicLeafEnum(_) => None,
|
||||
BuildSpec::PolymorphicTreeEnum(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,6 +55,11 @@ fn make_type_ident(build_spec: &BuildSpec) -> Option<Ident> {
|
||||
BuildSpec::PolymorphicPassThrough(_) => None,
|
||||
BuildSpec::Production(_) => None,
|
||||
BuildSpec::NodeProduction(_) => None,
|
||||
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build) => {
|
||||
Some(format_ident!("{}", polymorphic_enum_inner_build.name()))
|
||||
}
|
||||
BuildSpec::PolymorphicLeafEnum(_) => None,
|
||||
BuildSpec::PolymorphicTreeEnum(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,4 +93,4 @@ pub fn make_ast_node_ref_mut_unwrapper(build_spec: &BuildSpec) -> Option<TokenSt
|
||||
AstNodeRefMut::#type_ident(inner) => *inner
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
use convert_case::{Case, Casing};
|
||||
use crate::spec::polymorphic_enum_inner_build::{PolymorphicEnumInnerBuild, PolymorphicEnumInnerBuildMemberKind};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
pub fn make_polymorphic_enum_inner_build_ast_node_impl(
|
||||
spec: &PolymorphicEnumInnerBuild,
|
||||
) -> TokenStream {
|
||||
let type_ident = format_ident!("{}", spec.name());
|
||||
|
||||
let match_arms = spec.members()
|
||||
.map(|member| {
|
||||
let member_ident = format_ident!("{}", member.name());
|
||||
match member.kind() {
|
||||
PolymorphicEnumInnerBuildMemberKind::Leaf => {
|
||||
quote! {
|
||||
#type_ident::#member_ident => vec![]
|
||||
}
|
||||
}
|
||||
PolymorphicEnumInnerBuildMemberKind::Struct => {
|
||||
let child_ident = format_ident!("{}", member.name().to_case(Case::Snake));
|
||||
quote! {
|
||||
#type_ident::#member_ident(#child_ident) => vec![
|
||||
#child_ident
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut_match_arms = spec.members()
|
||||
.map(|member| {
|
||||
let member_ident = format_ident!("{}", member.name());
|
||||
match member.kind() {
|
||||
PolymorphicEnumInnerBuildMemberKind::Leaf => {
|
||||
quote! {
|
||||
#type_ident::#member_ident => {}
|
||||
}
|
||||
}
|
||||
PolymorphicEnumInnerBuildMemberKind::Struct => {
|
||||
let child_ident = format_ident!("{}", member.name().to_case(Case::Snake));
|
||||
quote! {
|
||||
#type_ident::#member_ident(#child_ident) => {
|
||||
f(#child_ident as &'a mut dyn AstNode<'a>)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
impl<'a> AstNode<'a> for #type_ident {
|
||||
fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> {
|
||||
match self {
|
||||
#(#match_arms,)*
|
||||
}
|
||||
}
|
||||
|
||||
fn for_each_child_mut(&'a mut self, mut f: &mut dyn FnMut(&'a mut dyn AstNode<'a>)) {
|
||||
match self {
|
||||
#(#mut_match_arms,)*
|
||||
}
|
||||
}
|
||||
|
||||
fn as_node_ref(&'a self) -> AstNodeRef<'a> {
|
||||
AstNodeRef::#type_ident(&self)
|
||||
}
|
||||
|
||||
fn as_node_ref_mut(&'a mut self) -> AstNodeRefMut<'a> {
|
||||
AstNodeRefMut::#type_ident(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,20 +1,26 @@
|
||||
use crate::build_fn::leaf_enum_build_fn::make_leaf_enum_build_fn;
|
||||
use crate::build_fn::leaf_struct_build_fn::make_leaf_struct_build_fn;
|
||||
use crate::build_fn::node_production_build_fn::make_node_production_build_fn;
|
||||
use crate::build_fn::polymorphic_enum_loop_build_fn::make_polymorphic_enum_loop_build_fn;
|
||||
use crate::build_fn::polymorphic_pass_through_build_fn::make_polymorphic_pass_through_build_fn;
|
||||
use crate::build_fn::polymorphic_type_build_fn::make_polymorphic_type_build_fn;
|
||||
use crate::build_fn::production_build_fn::make_production_build_fn;
|
||||
use crate::build_fn::struct_build_fn::make_struct_build_fn;
|
||||
use crate::build_fn::tree_enum_build_fn::make_enum_build_fn;
|
||||
use crate::spec::BuildSpec;
|
||||
use leaf_enum_build_fn::make_leaf_enum_build_fn;
|
||||
use leaf_struct_build_fn::make_leaf_struct_build_fn;
|
||||
use node_production_build_fn::make_node_production_build_fn;
|
||||
use polymorphic_enum_inner_build_build_fn::make_polymorphic_enum_inner_build_build_fn;
|
||||
use polymorphic_enum_loop_build_fn::make_polymorphic_enum_loop_build_fn;
|
||||
use polymorphic_leaf_enum_build_fn::make_polymorphic_leaf_enum_build_fn;
|
||||
use polymorphic_pass_through_build_fn::make_polymorphic_pass_through_build_fn;
|
||||
use polymorphic_tree_enum_build_fn::make_polymorphic_tree_enum_build_fn;
|
||||
use polymorphic_type_build_fn::make_polymorphic_type_build_fn;
|
||||
use proc_macro2::TokenStream;
|
||||
use production_build_fn::make_production_build_fn;
|
||||
use struct_build_fn::make_struct_build_fn;
|
||||
use tree_enum_build_fn::make_enum_build_fn;
|
||||
|
||||
mod leaf_enum_build_fn;
|
||||
mod leaf_struct_build_fn;
|
||||
mod node_production_build_fn;
|
||||
mod polymorphic_enum_inner_build_build_fn;
|
||||
mod polymorphic_enum_loop_build_fn;
|
||||
mod polymorphic_leaf_enum_build_fn;
|
||||
mod polymorphic_pass_through_build_fn;
|
||||
mod polymorphic_tree_enum_build_fn;
|
||||
mod polymorphic_type_build_fn;
|
||||
mod production_build_fn;
|
||||
mod struct_build_fn;
|
||||
@ -39,5 +45,14 @@ pub fn make_build_fn(build_spec: &BuildSpec) -> TokenStream {
|
||||
BuildSpec::PolymorphicPassThrough(polymorphic_pass_through_spec) => {
|
||||
make_polymorphic_pass_through_build_fn(polymorphic_pass_through_spec)
|
||||
}
|
||||
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build_spec) => {
|
||||
make_polymorphic_enum_inner_build_build_fn(polymorphic_enum_inner_build_spec)
|
||||
}
|
||||
BuildSpec::PolymorphicLeafEnum(polymorphic_leaf_enum_spec) => {
|
||||
make_polymorphic_leaf_enum_build_fn(polymorphic_leaf_enum_spec)
|
||||
}
|
||||
BuildSpec::PolymorphicTreeEnum(polymorphic_tree_enum_spec) => {
|
||||
make_polymorphic_tree_enum_build_fn(polymorphic_tree_enum_spec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
use crate::spec::polymorphic_enum_inner_build::PolymorphicEnumInnerBuild;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
||||
|
||||
pub fn make_polymorphic_enum_inner_build_build_fn(spec: &PolymorphicEnumInnerBuild) -> TokenStream {
|
||||
let build_fn_ident = format_ident!("{}", make_build_fn_name(spec.name()));
|
||||
let pair_ident = format_ident!("{}", make_build_pair(spec.name()));
|
||||
let return_type_ident = format_ident!("{}", spec.name());
|
||||
|
||||
let rule_branches = spec.rules()
|
||||
.map(|rule| {
|
||||
let rule_ident = format_ident!("{}", rule.name());
|
||||
let rule_build_fn_ident = format_ident!("{}", rule.with());
|
||||
quote! {
|
||||
Rule::#rule_ident => #rule_build_fn_ident(file_id, inner_pair)
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||
let inner_pair = #pair_ident.into_inner().next().unwrap();
|
||||
match inner_pair.as_rule() {
|
||||
#(#rule_branches,)*
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
ast-generator/src/build_fn/polymorphic_leaf_enum_build_fn.rs
Normal file
29
ast-generator/src/build_fn/polymorphic_leaf_enum_build_fn.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use crate::spec::polymorphic_leaf_enum::PolymorphicLeafEnum;
|
||||
use convert_case::{Case, Casing};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
pub fn make_polymorphic_leaf_enum_build_fn(spec: &PolymorphicLeafEnum) -> TokenStream {
|
||||
let build_fn_ident = format_ident!("build_{}", spec.name().to_case(Case::Snake));
|
||||
let pair_ident = format_ident!("{}_pair", spec.name().to_case(Case::Snake));
|
||||
let return_type_ident = format_ident!("{}", spec.kind());
|
||||
|
||||
let child_matchers = spec.rules()
|
||||
.map(|rule| {
|
||||
let rule_ident = format_ident!("{}", rule);
|
||||
quote! {
|
||||
Rule::#rule_ident => #return_type_ident::#rule_ident
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||
let inner_pair = #pair_ident.into_inner().next().unwrap();
|
||||
match inner_pair.as_rule() {
|
||||
#(#child_matchers,)*
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
33
ast-generator/src/build_fn/polymorphic_tree_enum_build_fn.rs
Normal file
33
ast-generator/src/build_fn/polymorphic_tree_enum_build_fn.rs
Normal file
@ -0,0 +1,33 @@
|
||||
use crate::spec::polymorphic_tree_enum_spec::PolymorphicTreeEnumSpec;
|
||||
use convert_case::{Case, Casing};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
pub fn make_polymorphic_tree_enum_build_fn(spec: &PolymorphicTreeEnumSpec) -> TokenStream {
|
||||
let build_fn_ident = format_ident!("build_{}", spec.name().to_case(Case::Snake));
|
||||
let pair_ident = format_ident!("{}_pair", spec.name().to_case(Case::Snake));
|
||||
let return_type_ident = format_ident!("{}", spec.kind());
|
||||
|
||||
let rule_matchers = spec
|
||||
.rules()
|
||||
.map(|rule| {
|
||||
let rule_ident = format_ident!("{}", rule);
|
||||
let inner_build_fn_ident = format_ident!("build_{}", rule.to_case(Case::Snake));
|
||||
quote! {
|
||||
Rule::#rule_ident => #return_type_ident::#rule_ident(
|
||||
#inner_build_fn_ident(file_id, inner_pair)
|
||||
)
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||
let inner_pair = #pair_ident.into_inner().next().unwrap();
|
||||
match inner_pair.as_rule() {
|
||||
#(#rule_matchers,)*
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,11 @@
|
||||
mod leaf_enum_spec;
|
||||
mod leaf_struct_spec;
|
||||
mod node_production_spec;
|
||||
mod polymorphic_enum_build_inner;
|
||||
mod polymorphic_enum_loop_spec;
|
||||
mod polymorphic_leaf_enum;
|
||||
mod polymorphic_pass_through_spec;
|
||||
mod polymorphic_tree_enum;
|
||||
mod polymorphic_type_spec;
|
||||
mod production_spec;
|
||||
mod struct_spec;
|
||||
@ -12,14 +15,17 @@ pub(crate) mod util;
|
||||
use crate::deserialize::leaf_enum_spec::deserialize_leaf_enum;
|
||||
use crate::deserialize::leaf_struct_spec::deserialize_leaf_struct;
|
||||
use crate::deserialize::node_production_spec::deserialize_node_production;
|
||||
use crate::deserialize::polymorphic_enum_build_inner::deserialize_polymorphic_enum_inner_build;
|
||||
use crate::deserialize::polymorphic_enum_loop_spec::deserialize_polymorphic_enum_loop;
|
||||
use crate::deserialize::polymorphic_leaf_enum::deserialize_polymorphic_leaf_enum;
|
||||
use crate::deserialize::polymorphic_pass_through_spec::deserialize_polymorphic_pass_through;
|
||||
use crate::deserialize::polymorphic_type_spec::deserialize_polymorphic_type;
|
||||
use crate::deserialize::production_spec::deserialize_production;
|
||||
use crate::deserialize::struct_spec::deserialize_struct_spec;
|
||||
use crate::deserialize::tree_enum_spec::deserialize_tree_enum;
|
||||
use crate::spec::BuildSpec;
|
||||
use yaml_rust2::{Yaml, YamlLoader};
|
||||
use crate::deserialize::polymorphic_pass_through_spec::deserialize_polymorphic_pass_through;
|
||||
use crate::deserialize::polymorphic_tree_enum::deserialize_polymorphic_tree_enum;
|
||||
|
||||
fn deserialize_build_spec(build_spec_name: &str, build_spec: &Yaml) -> BuildSpec {
|
||||
if build_spec["struct"].is_hash() {
|
||||
@ -67,6 +73,21 @@ fn deserialize_build_spec(build_spec_name: &str, build_spec: &Yaml) -> BuildSpec
|
||||
build_spec_name,
|
||||
&build_spec["polymorphic_pass_through"],
|
||||
))
|
||||
} else if build_spec["polymorphic_enum_inner_build"].is_hash() {
|
||||
BuildSpec::PolymorphicEnumInnerBuild(deserialize_polymorphic_enum_inner_build(
|
||||
build_spec_name,
|
||||
&build_spec["polymorphic_enum_inner_build"],
|
||||
))
|
||||
} else if build_spec["polymorphic_leaf_enum"].is_hash() {
|
||||
BuildSpec::PolymorphicLeafEnum(deserialize_polymorphic_leaf_enum(
|
||||
build_spec_name,
|
||||
&build_spec["polymorphic_leaf_enum"],
|
||||
))
|
||||
} else if build_spec["polymorphic_tree_enum"].is_hash() {
|
||||
BuildSpec::PolymorphicTreeEnum(deserialize_polymorphic_tree_enum(
|
||||
build_spec_name,
|
||||
&build_spec["polymorphic_tree_enum"],
|
||||
))
|
||||
} else {
|
||||
panic!("Missing or incorrect build type for {}", build_spec_name);
|
||||
}
|
||||
|
||||
@ -0,0 +1,59 @@
|
||||
use crate::deserialize::util::{make_build_fn_name, unwrap_single_member_hash};
|
||||
use crate::spec::polymorphic_enum_inner_build::{
|
||||
PolymorphicEnumInnerBuild, PolymorphicEnumInnerBuildMember,
|
||||
PolymorphicEnumInnerBuildMemberKind, PolymorphicEnumInnerBuildRule,
|
||||
};
|
||||
use yaml_rust2::Yaml;
|
||||
|
||||
pub fn deserialize_polymorphic_enum_inner_build(
|
||||
name: &str,
|
||||
props: &Yaml,
|
||||
) -> PolymorphicEnumInnerBuild {
|
||||
let members = props["members"]
|
||||
.as_vec()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|member| {
|
||||
if let Some(name) = member.as_str() {
|
||||
PolymorphicEnumInnerBuildMember::new(
|
||||
name,
|
||||
PolymorphicEnumInnerBuildMemberKind::Struct,
|
||||
)
|
||||
} else if member.is_hash() {
|
||||
let (name, props) = unwrap_single_member_hash(member);
|
||||
if let Some(kind) = props["kind"].as_str() {
|
||||
match kind {
|
||||
"leaf" => PolymorphicEnumInnerBuildMember::new(
|
||||
&name,
|
||||
PolymorphicEnumInnerBuildMemberKind::Leaf,
|
||||
),
|
||||
"struct" => PolymorphicEnumInnerBuildMember::new(
|
||||
&name,
|
||||
PolymorphicEnumInnerBuildMemberKind::Struct,
|
||||
),
|
||||
_ => panic!(),
|
||||
}
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let rules = props["rules"]
|
||||
.as_vec()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|rule| {
|
||||
let rule_as_string = rule.as_str().unwrap().to_string();
|
||||
PolymorphicEnumInnerBuildRule::new(
|
||||
&rule_as_string,
|
||||
&make_build_fn_name(&rule_as_string),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
PolymorphicEnumInnerBuild::new(name, members, rules)
|
||||
}
|
||||
13
ast-generator/src/deserialize/polymorphic_leaf_enum.rs
Normal file
13
ast-generator/src/deserialize/polymorphic_leaf_enum.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use yaml_rust2::Yaml;
|
||||
use crate::spec::polymorphic_leaf_enum::PolymorphicLeafEnum;
|
||||
|
||||
pub fn deserialize_polymorphic_leaf_enum(name: &str, props: &Yaml) -> PolymorphicLeafEnum {
|
||||
let kind = props["kind"].as_str().unwrap();
|
||||
let rules = props["rules"].as_vec().unwrap()
|
||||
.iter()
|
||||
.map(|rule| {
|
||||
rule.as_str().unwrap().to_string()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
PolymorphicLeafEnum::new(name, kind, rules)
|
||||
}
|
||||
12
ast-generator/src/deserialize/polymorphic_tree_enum.rs
Normal file
12
ast-generator/src/deserialize/polymorphic_tree_enum.rs
Normal file
@ -0,0 +1,12 @@
|
||||
use yaml_rust2::Yaml;
|
||||
use crate::spec::polymorphic_tree_enum_spec::PolymorphicTreeEnumSpec;
|
||||
|
||||
pub fn deserialize_polymorphic_tree_enum(name: &str, props: &Yaml) -> PolymorphicTreeEnumSpec {
|
||||
let kind = props["kind"].as_str().unwrap();
|
||||
let rules = props["rules"].as_vec().unwrap()
|
||||
.iter()
|
||||
.map(|rule| rule.as_str().unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
PolymorphicTreeEnumSpec::new(name, kind, &rules)
|
||||
}
|
||||
@ -65,6 +65,24 @@ fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
|
||||
pass_through_build_spec.name()
|
||||
);
|
||||
}
|
||||
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build_spec) => {
|
||||
println!(
|
||||
"Polymorphic Enum Inner Build Spec - name: {}",
|
||||
polymorphic_enum_inner_build_spec.name()
|
||||
);
|
||||
}
|
||||
BuildSpec::PolymorphicLeafEnum(polymorphic_leaf_enum) => {
|
||||
println!(
|
||||
"Polymorphic Leaf Enum Build Spec - name: {}",
|
||||
polymorphic_leaf_enum.name()
|
||||
);
|
||||
}
|
||||
BuildSpec::PolymorphicTreeEnum(polymorphic_tree_enum) => {
|
||||
println!(
|
||||
"Polymorphic Tree Enum Build Spec - name: {}",
|
||||
polymorphic_tree_enum.name()
|
||||
);
|
||||
}
|
||||
}
|
||||
println!("{:#?}", token_stream);
|
||||
let parsed: File = syn::parse2(token_stream.clone()).unwrap();
|
||||
|
||||
@ -10,11 +10,56 @@ use crate::spec::BuildSpec;
|
||||
use convert_case::{Case, Casing};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use crate::spec::polymorphic_enum_inner_build::{PolymorphicEnumInnerBuild, PolymorphicEnumInnerBuildMember, PolymorphicEnumInnerBuildMemberKind};
|
||||
|
||||
fn make_result() -> TokenStream {
|
||||
quote! { std::fmt::Result }
|
||||
}
|
||||
|
||||
fn make_polymorphic_enum_inner_build_p2_impl(spec: &PolymorphicEnumInnerBuild) -> TokenStream {
|
||||
let type_ident = format_ident!("{}", spec.name());
|
||||
let result = make_result();
|
||||
|
||||
let type_string = spec.name();
|
||||
|
||||
let child_matchers = spec.members()
|
||||
.map(|member| {
|
||||
let variant_ident = format_ident!("{}", member.name());
|
||||
match member.kind() {
|
||||
PolymorphicEnumInnerBuildMemberKind::Leaf => {
|
||||
let variant_string = member.name();
|
||||
quote! {
|
||||
#type_ident::#variant_ident => writer.writeln_indented(#variant_string)?
|
||||
}
|
||||
}
|
||||
PolymorphicEnumInnerBuildMemberKind::Struct => {
|
||||
let child_ident = format_ident!("{}", member.name().to_case(Case::Snake));
|
||||
quote! {
|
||||
#type_ident::#variant_ident(#child_ident) => {
|
||||
#child_ident.pretty_print(writer)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
impl PrettyPrint for #type_ident {
|
||||
fn pretty_print(&self, writer: &mut IndentWriter) -> #result {
|
||||
writer.writeln_indented(#type_string)?;
|
||||
writer.increase_indent();
|
||||
match self {
|
||||
#(#child_matchers,)*
|
||||
_ => {}
|
||||
}
|
||||
writer.decrease_indent();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_polymorphic_enum_loop_p2_impl(spec: &PolymorphicEnumLoopBuildSpec) -> TokenStream {
|
||||
let type_ident = format_ident!("{}", spec.name());
|
||||
let type_string = spec.name();
|
||||
@ -285,5 +330,10 @@ pub fn make_pretty_print_impl(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
|
||||
Some(make_polymorphic_enum_loop_p2_impl(polymorphic_enum_loop))
|
||||
}
|
||||
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build) => {
|
||||
Some(make_polymorphic_enum_inner_build_p2_impl(polymorphic_enum_inner_build))
|
||||
}
|
||||
BuildSpec::PolymorphicLeafEnum(_) => None,
|
||||
BuildSpec::PolymorphicTreeEnum(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,18 +1,24 @@
|
||||
use crate::spec::node_production_spec::NodeProductionBuildSpec;
|
||||
use crate::spec::polymorphic_enum_loop_spec::PolymorphicEnumLoopBuildSpec;
|
||||
use polymorphic_leaf_enum::PolymorphicLeafEnum;
|
||||
use leaf_enum_spec::LeafEnumBuildSpec;
|
||||
use leaf_struct_spec::LeafStructBuildSpec;
|
||||
use node_production_spec::NodeProductionBuildSpec;
|
||||
use polymorphic_enum_inner_build::PolymorphicEnumInnerBuild;
|
||||
use polymorphic_enum_loop_spec::PolymorphicEnumLoopBuildSpec;
|
||||
use polymorphic_pass_through_spec::PolymorphicPassThroughBuildSpec;
|
||||
use polymorphic_type_spec::PolymorphicTypeBuildSpec;
|
||||
use production_spec::ProductionBuildSpec;
|
||||
use struct_spec::StructSpec;
|
||||
use tree_enum_spec::TreeEnumBuildSpec;
|
||||
use crate::spec::polymorphic_pass_through_spec::PolymorphicPassThroughBuildSpec;
|
||||
use polymorphic_tree_enum_spec::PolymorphicTreeEnumSpec;
|
||||
|
||||
pub(crate) mod leaf_enum_spec;
|
||||
pub(crate) mod leaf_struct_spec;
|
||||
pub(crate) mod node_production_spec;
|
||||
pub(crate) mod polymorphic_enum_inner_build;
|
||||
pub(crate) mod polymorphic_enum_loop_spec;
|
||||
pub(crate) mod polymorphic_leaf_enum;
|
||||
pub(crate) mod polymorphic_pass_through_spec;
|
||||
pub(crate) mod polymorphic_tree_enum_spec;
|
||||
pub(crate) mod polymorphic_type_spec;
|
||||
pub(crate) mod production_spec;
|
||||
pub(crate) mod struct_spec;
|
||||
@ -27,5 +33,8 @@ pub enum BuildSpec {
|
||||
NodeProduction(NodeProductionBuildSpec),
|
||||
PolymorphicType(PolymorphicTypeBuildSpec),
|
||||
PolymorphicEnumLoop(PolymorphicEnumLoopBuildSpec),
|
||||
PolymorphicPassThrough(PolymorphicPassThroughBuildSpec)
|
||||
PolymorphicPassThrough(PolymorphicPassThroughBuildSpec),
|
||||
PolymorphicEnumInnerBuild(PolymorphicEnumInnerBuild),
|
||||
PolymorphicLeafEnum(PolymorphicLeafEnum),
|
||||
PolymorphicTreeEnum(PolymorphicTreeEnumSpec),
|
||||
}
|
||||
|
||||
76
ast-generator/src/spec/polymorphic_enum_inner_build.rs
Normal file
76
ast-generator/src/spec/polymorphic_enum_inner_build.rs
Normal file
@ -0,0 +1,76 @@
|
||||
pub struct PolymorphicEnumInnerBuild {
|
||||
name: String,
|
||||
members: Vec<PolymorphicEnumInnerBuildMember>,
|
||||
rules: Vec<PolymorphicEnumInnerBuildRule>,
|
||||
}
|
||||
|
||||
impl PolymorphicEnumInnerBuild {
|
||||
pub fn new(name: &str, members: Vec<PolymorphicEnumInnerBuildMember>, rules: Vec<PolymorphicEnumInnerBuildRule>) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
members,
|
||||
rules,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn members(&self) -> impl Iterator<Item = &PolymorphicEnumInnerBuildMember> {
|
||||
self.members.iter()
|
||||
}
|
||||
|
||||
pub fn rules(&self) -> impl Iterator<Item = &PolymorphicEnumInnerBuildRule> {
|
||||
self.rules.iter()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PolymorphicEnumInnerBuildMember {
|
||||
name: String,
|
||||
kind: PolymorphicEnumInnerBuildMemberKind
|
||||
}
|
||||
|
||||
impl PolymorphicEnumInnerBuildMember {
|
||||
pub fn new(name: &str, kind: PolymorphicEnumInnerBuildMemberKind) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
kind
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> &PolymorphicEnumInnerBuildMemberKind {
|
||||
&self.kind
|
||||
}
|
||||
}
|
||||
|
||||
pub enum PolymorphicEnumInnerBuildMemberKind {
|
||||
Leaf,
|
||||
Struct
|
||||
}
|
||||
|
||||
pub struct PolymorphicEnumInnerBuildRule {
|
||||
name: String,
|
||||
with: String,
|
||||
}
|
||||
|
||||
impl PolymorphicEnumInnerBuildRule {
|
||||
pub fn new(name: &str, with: &str) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
with: with.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn with(&self) -> &str {
|
||||
&self.with
|
||||
}
|
||||
}
|
||||
27
ast-generator/src/spec/polymorphic_leaf_enum.rs
Normal file
27
ast-generator/src/spec/polymorphic_leaf_enum.rs
Normal file
@ -0,0 +1,27 @@
|
||||
pub struct PolymorphicLeafEnum {
|
||||
name: String,
|
||||
kind: String,
|
||||
rules: Vec<String>,
|
||||
}
|
||||
|
||||
impl PolymorphicLeafEnum {
|
||||
pub fn new(name: &str, kind: &str, rules: Vec<String>) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
kind: kind.to_string(),
|
||||
rules,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> &str {
|
||||
&self.kind
|
||||
}
|
||||
|
||||
pub fn rules(&self) -> impl Iterator<Item = &str> {
|
||||
self.rules.iter().map(AsRef::as_ref)
|
||||
}
|
||||
}
|
||||
27
ast-generator/src/spec/polymorphic_tree_enum_spec.rs
Normal file
27
ast-generator/src/spec/polymorphic_tree_enum_spec.rs
Normal file
@ -0,0 +1,27 @@
|
||||
pub struct PolymorphicTreeEnumSpec {
|
||||
name: String,
|
||||
kind: String,
|
||||
rules: Vec<String>,
|
||||
}
|
||||
|
||||
impl PolymorphicTreeEnumSpec {
|
||||
pub fn new(name: &str, kind: &str, rules: &[&str]) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
kind: kind.to_string(),
|
||||
rules: rules.iter().map(ToString::to_string).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> &str {
|
||||
&self.kind
|
||||
}
|
||||
|
||||
pub fn rules(&self) -> impl Iterator<Item = &str> {
|
||||
self.rules.iter().map(AsRef::as_ref)
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
mod enum_type;
|
||||
mod leaf_enum_type;
|
||||
mod leaf_struct_type;
|
||||
mod polymorphic_enum_inner_build_type;
|
||||
mod polymorphic_enum_loop_type;
|
||||
mod polymorphic_type_type;
|
||||
mod struct_type;
|
||||
@ -9,10 +10,11 @@ use crate::spec::BuildSpec;
|
||||
use crate::type_gen::enum_type::make_enum_type;
|
||||
use crate::type_gen::leaf_enum_type::make_leaf_enum_type;
|
||||
use crate::type_gen::leaf_struct_type::make_leaf_struct_type;
|
||||
use crate::type_gen::polymorphic_enum_inner_build_type::make_polymorphic_enum_inner_build_type;
|
||||
use crate::type_gen::polymorphic_enum_loop_type::make_polymorphic_enum_loop_type;
|
||||
use crate::type_gen::polymorphic_type_type::make_polymorphic_type_type;
|
||||
use crate::type_gen::struct_type::make_struct_type;
|
||||
use proc_macro2::TokenStream;
|
||||
use crate::type_gen::polymorphic_enum_loop_type::make_polymorphic_enum_loop_type;
|
||||
|
||||
pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||
match build_spec {
|
||||
@ -31,7 +33,12 @@ pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||
}
|
||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop_spec) => {
|
||||
Some(make_polymorphic_enum_loop_type(polymorphic_enum_loop_spec))
|
||||
},
|
||||
}
|
||||
BuildSpec::PolymorphicPassThrough(_) => None,
|
||||
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build_spec) => Some(
|
||||
make_polymorphic_enum_inner_build_type(polymorphic_enum_inner_build_spec),
|
||||
),
|
||||
BuildSpec::PolymorphicLeafEnum(_) => None,
|
||||
BuildSpec::PolymorphicTreeEnum(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use crate::spec::polymorphic_enum_inner_build::{PolymorphicEnumInnerBuild, PolymorphicEnumInnerBuildMemberKind};
|
||||
|
||||
pub fn make_polymorphic_enum_inner_build_type(spec: &PolymorphicEnumInnerBuild) -> TokenStream {
|
||||
let members = spec.members()
|
||||
.map(|member| {
|
||||
let name_ident = format_ident!("{}", member.name());
|
||||
match member.kind() {
|
||||
PolymorphicEnumInnerBuildMemberKind::Leaf => {
|
||||
quote! { #name_ident }
|
||||
}
|
||||
PolymorphicEnumInnerBuildMemberKind::Struct => {
|
||||
quote! { #name_ident(#name_ident) }
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let type_name_ident = format_ident!("{}", spec.name());
|
||||
quote! {
|
||||
pub enum #type_name_ident {
|
||||
#(#members,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,13 @@
|
||||
use crate::ast::node::{AnySpaceSuffixOperator, AssignmentStatement, BacktickString, BoundSuffixOperator, Call, Closure, ClosureParameters, CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, DString, Expression, ExpressionList, ExpressionStatement, Function, FunctionAliasBody, FunctionBlockBody, FunctionBody, FunctionEqualsBody, GenericParameters, Identifier, IdentifierExpression, IdentifierOrFqn, LValue, LValueSuffix, Literal, ModuleLevelDeclaration, NoNewlineSuffixOperator, ObjectIndex, Parameter, Parameters, PlatformFunction, PrimitiveType, ReturnType, StarUseStatement, Statement, SuffixExpression, SuffixOperator, TypeUse, TypedArray, UseStatement, UseStatementIdentifier, UseStatementPrefix, VariableDeclaration};
|
||||
use crate::ast::node::{
|
||||
AssignmentStatement, BacktickString, Call, Closure, ClosureParameters,
|
||||
CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, DString, Expression,
|
||||
ExpressionList, ExpressionStatement, Function, FunctionAliasBody, FunctionBlockBody,
|
||||
FunctionBody, FunctionEqualsBody, GenericParameters, Identifier, IdentifierExpression,
|
||||
IdentifierOrFqn, LValue, LValueSuffix, Literal, ModuleLevelDeclaration
|
||||
, ObjectIndex, Parameter, Parameters, PlatformFunction, PrimitiveType,
|
||||
ReturnType, StarUseStatement, Statement, SuffixExpression, SuffixOperator, TypeUse, TypedArray,
|
||||
UseStatement, UseStatementIdentifier, UseStatementPrefix, VariableDeclaration,
|
||||
};
|
||||
use crate::diagnostic::DmDiagnostic;
|
||||
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
|
||||
@ -668,30 +677,16 @@ fn na_p2_suffix_operator(
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
match suffix_operator {
|
||||
SuffixOperator::BoundSuffixOperator(bound_suffix) => {
|
||||
match bound_suffix {
|
||||
BoundSuffixOperator::PlusPlus => {
|
||||
// no-op
|
||||
}
|
||||
BoundSuffixOperator::MinusMinus => {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
SuffixOperator::PlusPlus => {}
|
||||
SuffixOperator::MinusMinus => {}
|
||||
SuffixOperator::ObjectIndex(object_index) => {
|
||||
na_p2_object_index(object_index, symbol_table, diagnostics);
|
||||
}
|
||||
SuffixOperator::NoNewlineSuffixOperator(no_newline_suffix) => match no_newline_suffix {
|
||||
NoNewlineSuffixOperator::ObjectIndex(object_index) => {
|
||||
na_p2_object_index(object_index, symbol_table, diagnostics);
|
||||
}
|
||||
NoNewlineSuffixOperator::Call(call) => {
|
||||
na_p2_call(call, symbol_table, diagnostics);
|
||||
}
|
||||
},
|
||||
SuffixOperator::AnySpaceSuffixOperator(any_space_suffix) => {
|
||||
match any_space_suffix {
|
||||
AnySpaceSuffixOperator::ObjectProperty(_) => {
|
||||
// no-op; this is checked during type checking
|
||||
}
|
||||
}
|
||||
SuffixOperator::Call(call) => {
|
||||
na_p2_call(call, symbol_table, diagnostics);
|
||||
}
|
||||
SuffixOperator::ObjectProperty(object_property) => {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1158,23 +1158,34 @@ SuffixExpression:
|
||||
on_each:
|
||||
rule: SuffixOperator
|
||||
SuffixOperator:
|
||||
tree_enum:
|
||||
polymorphic_enum_inner_build:
|
||||
members:
|
||||
- PlusPlus:
|
||||
kind: leaf
|
||||
- MinusMinus:
|
||||
kind: leaf
|
||||
- ObjectIndex
|
||||
- Call
|
||||
- ObjectProperty
|
||||
rules:
|
||||
- BoundSuffixOperator
|
||||
- NoNewlineSuffixOperator
|
||||
- AnySpaceSuffixOperator
|
||||
BoundSuffixOperator:
|
||||
leaf_enum:
|
||||
polymorphic_leaf_enum:
|
||||
kind: SuffixOperator
|
||||
rules:
|
||||
- PlusPlus
|
||||
- MinusMinus
|
||||
NoNewlineSuffixOperator:
|
||||
tree_enum:
|
||||
polymorphic_tree_enum:
|
||||
kind: SuffixOperator
|
||||
rules:
|
||||
- ObjectIndex
|
||||
- Call
|
||||
AnySpaceSuffixOperator:
|
||||
tree_enum:
|
||||
polymorphic_tree_enum:
|
||||
kind: SuffixOperator
|
||||
rules:
|
||||
- ObjectProperty
|
||||
ObjectProperty:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user