Compare commits
No commits in common. "2a2936ef02d813355a8375ea2269a4bbb8f993d1" and "fe2fff5882ed15d4f19b60f0b7b75a35cf2ccafa" have entirely different histories.
2a2936ef02
...
fe2fff5882
@ -1,43 +0,0 @@
|
|||||||
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 proc_macro2::TokenStream;
|
|
||||||
|
|
||||||
mod leaf_enum_build_fn;
|
|
||||||
mod leaf_struct_build_fn;
|
|
||||||
mod node_production_build_fn;
|
|
||||||
mod polymorphic_enum_loop_build_fn;
|
|
||||||
mod polymorphic_pass_through_build_fn;
|
|
||||||
mod polymorphic_type_build_fn;
|
|
||||||
mod production_build_fn;
|
|
||||||
mod struct_build_fn;
|
|
||||||
mod tree_enum_build_fn;
|
|
||||||
|
|
||||||
pub fn make_build_fn(build_spec: &BuildSpec) -> TokenStream {
|
|
||||||
match build_spec {
|
|
||||||
BuildSpec::Struct(struct_spec) => make_struct_build_fn(struct_spec),
|
|
||||||
BuildSpec::LeafStruct(leaf_struct_spec) => make_leaf_struct_build_fn(leaf_struct_spec),
|
|
||||||
BuildSpec::Enum(enum_spec) => make_enum_build_fn(enum_spec),
|
|
||||||
BuildSpec::LeafEnum(leaf_enum_spec) => make_leaf_enum_build_fn(leaf_enum_spec),
|
|
||||||
BuildSpec::Production(production_spec) => make_production_build_fn(production_spec),
|
|
||||||
BuildSpec::NodeProduction(node_production_spec) => {
|
|
||||||
make_node_production_build_fn(node_production_spec)
|
|
||||||
}
|
|
||||||
BuildSpec::PolymorphicType(polymorphic_type_spec) => {
|
|
||||||
make_polymorphic_type_build_fn(polymorphic_type_spec)
|
|
||||||
}
|
|
||||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop_spec) => {
|
|
||||||
make_polymorphic_enum_loop_build_fn(polymorphic_enum_loop_spec)
|
|
||||||
}
|
|
||||||
BuildSpec::PolymorphicPassThrough(polymorphic_pass_through_spec) => {
|
|
||||||
make_polymorphic_pass_through_build_fn(polymorphic_pass_through_spec)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
use crate::deserialize::util::make_build_pair;
|
|
||||||
use crate::spec::node_production_spec::NodeProductionBuildSpec;
|
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
|
|
||||||
pub fn make_node_production_build_fn(spec: &NodeProductionBuildSpec) -> TokenStream {
|
|
||||||
let build_fn_ident = format_ident!("{}", spec.with());
|
|
||||||
let pair_ident = format_ident!("{}", make_build_pair(spec.name()));
|
|
||||||
let return_type_ident = format_ident!("{}", spec.kind());
|
|
||||||
let inner_build_fn_ident = format_ident!("{}", spec.with());
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
|
|
||||||
let inner_pair = #pair_ident.into_inner().next().unwrap();
|
|
||||||
#inner_build_fn_ident(inner_pair)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,100 +0,0 @@
|
|||||||
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
|
||||||
use crate::spec::polymorphic_enum_loop_spec::{
|
|
||||||
PolymorphicEnumLoopBuildSpec, PolymorphicEnumLoopRule,
|
|
||||||
PolymorphicEnumLoopRuleBuild, PolymorphicEnumLoopRuleBuildChild,
|
|
||||||
PolymorphicEnumLoopRuleChildOnEach, PolymorphicEnumLoopRulePassThrough,
|
|
||||||
};
|
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
|
|
||||||
fn make_pass_through(pass_through: &PolymorphicEnumLoopRulePassThrough) -> TokenStream {
|
|
||||||
let rule_ident = format_ident!("{}", pass_through.name());
|
|
||||||
let inner_build_fn_ident = format_ident!("{}", pass_through.with());
|
|
||||||
quote! {
|
|
||||||
Rule::#rule_ident => {
|
|
||||||
result = Some(#inner_build_fn_ident(inner_pair))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_on_each_child_build(child: &PolymorphicEnumLoopRuleChildOnEach) -> TokenStream {
|
|
||||||
let child_build_fn_ident = format_ident!("{}", make_build_fn_name(child.rule()));
|
|
||||||
quote! {
|
|
||||||
#child_build_fn_ident(inner_pair)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_build(
|
|
||||||
spec: &PolymorphicEnumLoopBuildSpec,
|
|
||||||
build: &PolymorphicEnumLoopRuleBuild,
|
|
||||||
) -> TokenStream {
|
|
||||||
let rule_ident = format_ident!("{}", build.name());
|
|
||||||
let variant_type_ident = format_ident!("{}", build.name());
|
|
||||||
let return_type_ident = format_ident!("{}", spec.kind());
|
|
||||||
let variant_ident = format_ident!("{}", build.variant());
|
|
||||||
|
|
||||||
let on_each_child = build
|
|
||||||
.children()
|
|
||||||
.find(|child| match child {
|
|
||||||
PolymorphicEnumLoopRuleBuildChild::OnEach(_) => true,
|
|
||||||
_ => false,
|
|
||||||
})
|
|
||||||
.map(|child| {
|
|
||||||
match child {
|
|
||||||
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => on_each,
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let build_on_each_child = make_on_each_child_build(on_each_child);
|
|
||||||
|
|
||||||
let child_args = build
|
|
||||||
.children()
|
|
||||||
.map(|child| match child {
|
|
||||||
PolymorphicEnumLoopRuleBuildChild::UseCurrent(_) => {
|
|
||||||
quote! { result.unwrap() }
|
|
||||||
}
|
|
||||||
PolymorphicEnumLoopRuleBuildChild::OnEach(_) => quote! { on_each_child },
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
Rule::#rule_ident => {
|
|
||||||
let on_each_child = #build_on_each_child;
|
|
||||||
let built = #variant_type_ident::new(#(#child_args),*);
|
|
||||||
result = Some(#return_type_ident::#variant_ident(built))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_match_arm(spec: &PolymorphicEnumLoopBuildSpec, rule: &PolymorphicEnumLoopRule) -> TokenStream {
|
|
||||||
match rule {
|
|
||||||
PolymorphicEnumLoopRule::PassThrough(pass_through) => make_pass_through(pass_through),
|
|
||||||
PolymorphicEnumLoopRule::Build(build) => make_build(spec, build),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn make_polymorphic_enum_loop_build_fn(spec: &PolymorphicEnumLoopBuildSpec) -> 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.kind());
|
|
||||||
|
|
||||||
let match_arms = spec
|
|
||||||
.rules()
|
|
||||||
.map(|rule| make_match_arm(spec, rule))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
|
|
||||||
let mut result: Option<#return_type_ident> = None;
|
|
||||||
for inner_pair in #pair_ident.into_inner() {
|
|
||||||
match inner_pair.as_rule() {
|
|
||||||
#(#match_arms,)*
|
|
||||||
_ => unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
|
||||||
use crate::spec::polymorphic_pass_through_spec::{PolymorphicPassThroughBuildSpec, PolymorphicPassThroughVariant};
|
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
|
|
||||||
pub fn make_polymorphic_pass_through_build_fn(
|
|
||||||
spec: &PolymorphicPassThroughBuildSpec,
|
|
||||||
) -> 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.build_kind());
|
|
||||||
|
|
||||||
let match_arms = spec.variants()
|
|
||||||
.map(|variant| {
|
|
||||||
match variant {
|
|
||||||
PolymorphicPassThroughVariant::Inner { name, kind} => {
|
|
||||||
let rule_ident = format_ident!("{}", kind);
|
|
||||||
let variant_ident = format_ident!("{}", name);
|
|
||||||
let inner_build_fn_ident = format_ident!("{}", make_build_fn_name(kind));
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
Rule::#rule_ident => {
|
|
||||||
#return_type_ident::#variant_ident(
|
|
||||||
#inner_build_fn_ident(inner_pair)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PolymorphicPassThroughVariant::PassThrough { name, kind: _kind } => {
|
|
||||||
let rule_ident = format_ident!("{}", name);
|
|
||||||
let inner_build_fn_ident = format_ident!("{}", make_build_fn_name(name));
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
Rule::#rule_ident => #inner_build_fn_ident(inner_pair)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
|
|
||||||
let inner_pair = #pair_ident.into_inner().next().unwrap();
|
|
||||||
match inner_pair.as_rule() {
|
|
||||||
#(#match_arms,)*
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,215 +0,0 @@
|
|||||||
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
|
||||||
use crate::spec::struct_spec::{
|
|
||||||
MemberChildBuild, NodeMemberBuild, StructChild, StructSpec, VecChild, VecChildBuild,
|
|
||||||
};
|
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
|
|
||||||
fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream {
|
|
||||||
let child_ident = format_ident!("{}", vec_child.name());
|
|
||||||
match vec_child.build() {
|
|
||||||
VecChildBuild::String(_) => {
|
|
||||||
quote! {
|
|
||||||
let mut #child_ident: Vec<String> = vec![]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VecChildBuild::Node(node_build) => {
|
|
||||||
let child_type_ident = format_ident!("{}", node_build.kind());
|
|
||||||
quote! {
|
|
||||||
let mut #child_ident: Vec<Box<#child_type_ident>> = vec![]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_node_child_holder(name: &str, node_child: &NodeMemberBuild) -> TokenStream {
|
|
||||||
let child_ident = format_ident!("{}", name);
|
|
||||||
let child_type_ident = format_ident!("{}", node_child.kind());
|
|
||||||
quote! {
|
|
||||||
let mut #child_ident: Option<Box<#child_type_ident>> = None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_boolean_child_holder(name: &str) -> TokenStream {
|
|
||||||
let child_ident = format_ident!("{}", name);
|
|
||||||
quote! {
|
|
||||||
let mut #child_ident: bool = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_child_holder(child_spec: &StructChild) -> Option<TokenStream> {
|
|
||||||
match child_spec {
|
|
||||||
StructChild::SkipChild(_) => None,
|
|
||||||
StructChild::VecChild(vec_child) => Some(make_vec_child_holder(vec_child)),
|
|
||||||
StructChild::MemberChild(member_child) => match member_child.build() {
|
|
||||||
MemberChildBuild::Node(node_child) => {
|
|
||||||
Some(make_node_child_holder(member_child.name(), node_child))
|
|
||||||
}
|
|
||||||
MemberChildBuild::Boolean(_) => Some(make_boolean_child_holder(member_child.name())),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_vec_child_match_action(vec_child: &VecChild) -> TokenStream {
|
|
||||||
let child_name_ident = format_ident!("{}", vec_child.name());
|
|
||||||
match vec_child.build() {
|
|
||||||
VecChildBuild::String(string_build) => {
|
|
||||||
let build_fn_ident = format_ident!("{}", string_build.with());
|
|
||||||
quote! {
|
|
||||||
#child_name_ident.push(#build_fn_ident(inner_pair))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VecChildBuild::Node(node_build) => {
|
|
||||||
let build_fn_ident = format_ident!("{}", node_build.with());
|
|
||||||
quote! {
|
|
||||||
#child_name_ident.push(Box::new(#build_fn_ident(inner_pair)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_node_member_child_match_action(name: &str, node_child: &NodeMemberBuild) -> TokenStream {
|
|
||||||
let child_name_ident = format_ident!("{}", name);
|
|
||||||
let build_fn_ident = format_ident!("{}", node_child.with());
|
|
||||||
quote! {
|
|
||||||
#child_name_ident = Some(Box::new(#build_fn_ident(inner_pair)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_boolean_member_child_match_action(name: &str) -> TokenStream {
|
|
||||||
let child_name_ident = format_ident!("{}", name);
|
|
||||||
quote! {
|
|
||||||
#child_name_ident = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_match_action(child_spec: &StructChild) -> TokenStream {
|
|
||||||
match child_spec {
|
|
||||||
StructChild::SkipChild(_) => quote! {},
|
|
||||||
StructChild::VecChild(vec_child) => make_vec_child_match_action(vec_child),
|
|
||||||
StructChild::MemberChild(member_child) => match member_child.build() {
|
|
||||||
MemberChildBuild::Node(node_child) => {
|
|
||||||
make_node_member_child_match_action(member_child.name(), node_child)
|
|
||||||
}
|
|
||||||
MemberChildBuild::Boolean(_) => {
|
|
||||||
make_boolean_member_child_match_action(member_child.name())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_rule_matcher(child_spec: &StructChild) -> TokenStream {
|
|
||||||
let rule_ident = match child_spec {
|
|
||||||
StructChild::SkipChild(skip_child) => format_ident!("{}", skip_child.rule()),
|
|
||||||
StructChild::VecChild(vec_child) => format_ident!("{}", vec_child.rule()),
|
|
||||||
StructChild::MemberChild(single_child) => format_ident!("{}", single_child.rule()),
|
|
||||||
};
|
|
||||||
let action = make_match_action(child_spec);
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
Rule::#rule_ident => {
|
|
||||||
#action;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_vec_child_arg(vec_child: &VecChild) -> TokenStream {
|
|
||||||
let child_ident = format_ident!("{}", vec_child.name());
|
|
||||||
quote! { #child_ident }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_node_member_child_arg(
|
|
||||||
name: &str,
|
|
||||||
optional: bool,
|
|
||||||
node_child: &NodeMemberBuild,
|
|
||||||
) -> TokenStream {
|
|
||||||
let child_ident = format_ident!("{}", name);
|
|
||||||
if optional {
|
|
||||||
quote! { #child_ident }
|
|
||||||
} else if let Some(or_else) = node_child.or_else() {
|
|
||||||
let child_type_ident = format_ident!("{}", node_child.kind());
|
|
||||||
let or_else_ident = format_ident!("{}", or_else);
|
|
||||||
quote! {
|
|
||||||
#child_ident.unwrap_or_else(|| Box::new(#child_type_ident::#or_else_ident()))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
quote! { #child_ident.unwrap() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_boolean_member_child_arg(name: &str) -> TokenStream {
|
|
||||||
let child_ident = format_ident!("{}", name);
|
|
||||||
quote! { #child_ident }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_child_arg(child_spec: &StructChild) -> Option<TokenStream> {
|
|
||||||
match child_spec {
|
|
||||||
StructChild::SkipChild(_) => None,
|
|
||||||
StructChild::VecChild(vec_child) => Some(make_vec_child_arg(vec_child)),
|
|
||||||
StructChild::MemberChild(member_child) => match member_child.build() {
|
|
||||||
MemberChildBuild::Node(node_member_build) => Some(make_node_member_child_arg(
|
|
||||||
member_child.name(),
|
|
||||||
member_child.optional(),
|
|
||||||
node_member_build,
|
|
||||||
)),
|
|
||||||
MemberChildBuild::Boolean(_) => {
|
|
||||||
Some(make_boolean_member_child_arg(member_child.name()))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_return_value_stream(build_spec: &StructSpec) -> TokenStream {
|
|
||||||
let type_ident = format_ident!("{}", build_spec.build());
|
|
||||||
let child_args = build_spec
|
|
||||||
.children()
|
|
||||||
.map(|child| make_child_arg(child))
|
|
||||||
.filter(|child_arg| child_arg.is_some())
|
|
||||||
.map(|child_arg| child_arg.unwrap())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#type_ident::new(
|
|
||||||
#(#child_args,)*
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn make_struct_build_fn(build_spec: &StructSpec) -> TokenStream {
|
|
||||||
let build_fn_ident = format_ident!("{}", make_build_fn_name(build_spec.build()));
|
|
||||||
let pair_ident = format_ident!("{}", make_build_pair(build_spec.build()));
|
|
||||||
let return_type_ident = format_ident!("{}", build_spec.build());
|
|
||||||
|
|
||||||
let child_holders = build_spec
|
|
||||||
.children()
|
|
||||||
.map(|child_spec| make_child_holder(child_spec))
|
|
||||||
.filter(|child_holder| child_holder.is_some())
|
|
||||||
.map(|child_holder| child_holder.unwrap())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let rule_matchers = build_spec
|
|
||||||
.children()
|
|
||||||
.map(|child_spec| make_rule_matcher(child_spec))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let iter_stream = quote! {
|
|
||||||
for inner_pair in #pair_ident.into_inner() {
|
|
||||||
match inner_pair.as_rule() {
|
|
||||||
#(#rule_matchers)*
|
|
||||||
_ => panic!("Unexpected rule: {:?}", inner_pair.as_rule())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let new_stream = make_return_value_stream(build_spec);
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
|
|
||||||
#(#child_holders;)*
|
|
||||||
|
|
||||||
#iter_stream
|
|
||||||
|
|
||||||
#new_stream
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
432
ast-generator/src/deserialize.rs
Normal file
432
ast-generator/src/deserialize.rs
Normal file
@ -0,0 +1,432 @@
|
|||||||
|
use crate::spec::{AlternativeAction, AlternativeBuild, AlternativeBuildChild, AlternativeChild, AlternativeTest, BooleanChildToBuild, BuildSpec, EnumBuildSpec, EnumRule, EnumRuleChild, EnumRuleChildKind, EnumRuleNodeChild, LeafEnumBuildSpec, LeafEnumRule, LeafStructBuildSpec, LeafStructMember, LeafStructMemberKind, MemberChild, MemberChildToBuild, NameAndKind, NodeChildToBuild, PolymorphicBuildAlternative, PolymorphicBuildBuildSpec, PolymorphicEnumBuildSpec, PolymorphicEnumMember, PolymorphicEnumRule, PolymorphicTypeBuildSpec, ProductionBuildSpec, ProductionKind, ProductionStringFrom, SkipChild, StructBuildSpec, StructChildSpec, VecChild, VecChildToBuild, VecNodeChildToBuild};
|
||||||
|
use convert_case::{Case, Casing};
|
||||||
|
use yaml_rust2::{Yaml, YamlLoader};
|
||||||
|
|
||||||
|
fn get_as_bool(yaml: &Yaml) -> bool {
|
||||||
|
yaml.as_bool().unwrap_or_else(|| false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unwrap_single_member_hash(hash: &Yaml) -> (String, &Yaml) {
|
||||||
|
let as_hash = hash.as_hash().unwrap();
|
||||||
|
if as_hash.is_empty() {
|
||||||
|
panic!("empty hash");
|
||||||
|
} else if as_hash.len() > 1 {
|
||||||
|
panic!("hash contains more than one key");
|
||||||
|
}
|
||||||
|
let (member_key, member_value) = as_hash.iter().collect::<Vec<(&Yaml, &Yaml)>>()[0];
|
||||||
|
let key_as_string = member_key.as_str().unwrap().to_string();
|
||||||
|
(key_as_string, member_value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_polymorphic_enum_build_spec(name: &str, build_spec: &Yaml) -> PolymorphicEnumBuildSpec {
|
||||||
|
let return_type = build_spec["return_type"].as_str().unwrap();
|
||||||
|
let rules = build_spec["rules"]
|
||||||
|
.as_vec()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|rule_yaml| {
|
||||||
|
let (rule_name, props) = unwrap_single_member_hash(rule_yaml);
|
||||||
|
if props["wrap"].is_hash() {
|
||||||
|
PolymorphicEnumRule::Wrap(NameAndKind::new(
|
||||||
|
&rule_name,
|
||||||
|
props["wrap"]["enum_variant"].as_str().unwrap()
|
||||||
|
))
|
||||||
|
} else if props["return_build"].is_hash() {
|
||||||
|
PolymorphicEnumRule::ReturnBuild(NameAndKind::new(
|
||||||
|
&rule_name,
|
||||||
|
props["return_build"]["kind"].as_str().unwrap()
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(Box::new)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
PolymorphicEnumBuildSpec::new(name, return_type, rules)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_polymorphic_action(action_yaml: &Yaml) -> AlternativeAction {
|
||||||
|
if action_yaml["return_build"].is_hash() {
|
||||||
|
let kind = action_yaml["return_build"]["kind"].as_str().unwrap();
|
||||||
|
AlternativeAction::ReturnBuild(kind.to_string())
|
||||||
|
} else if action_yaml["build"].is_hash() {
|
||||||
|
let build_children = action_yaml["build"]["children"]
|
||||||
|
.as_vec()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|child_yaml| {
|
||||||
|
let (child_name, child_props) = unwrap_single_member_hash(child_yaml);
|
||||||
|
if get_as_bool(&child_props["skip"]) {
|
||||||
|
AlternativeChild::Skip
|
||||||
|
} else {
|
||||||
|
let kind = child_props["kind"].as_str().unwrap();
|
||||||
|
let rule = child_props["rule"].as_str().unwrap();
|
||||||
|
AlternativeChild::Build(AlternativeBuildChild::new(&child_name, kind, rule))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(Box::new)
|
||||||
|
.collect();
|
||||||
|
let enum_variant = action_yaml["build"]["enum_variant"].as_str().unwrap();
|
||||||
|
let build = AlternativeBuild::new(enum_variant, build_children);
|
||||||
|
AlternativeAction::Build(build)
|
||||||
|
} else {
|
||||||
|
panic!("return_build or build is required for an alternative")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_polymorphic_build_build_spec(
|
||||||
|
name: &str,
|
||||||
|
polymorphic_build_yaml: &Yaml
|
||||||
|
) -> PolymorphicBuildBuildSpec {
|
||||||
|
let return_type = polymorphic_build_yaml["return_type"].as_str().unwrap();
|
||||||
|
let alternatives = polymorphic_build_yaml["alternatives"]
|
||||||
|
.as_vec()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|alternative_yaml| {
|
||||||
|
let number_of_pairs = alternative_yaml["test"]["number_of_pairs"].as_i64().unwrap();
|
||||||
|
let action = deserialize_polymorphic_action(&alternative_yaml["action"]);
|
||||||
|
PolymorphicBuildAlternative::new(
|
||||||
|
AlternativeTest::NumberOfPairs(number_of_pairs),
|
||||||
|
action
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.map(Box::new)
|
||||||
|
.collect();
|
||||||
|
PolymorphicBuildBuildSpec::new(name, return_type, alternatives)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_polymorphic_enum_members(
|
||||||
|
enum_members_yaml: &Yaml,
|
||||||
|
) -> Vec<Box<PolymorphicEnumMember>> {
|
||||||
|
enum_members_yaml
|
||||||
|
.as_vec()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|enum_member_yaml| {
|
||||||
|
let (member_name, member_hash) = unwrap_single_member_hash(enum_member_yaml);
|
||||||
|
let inner_kind = member_hash["inner"]["kind"].as_str().unwrap();
|
||||||
|
PolymorphicEnumMember::new(&member_name, inner_kind)
|
||||||
|
})
|
||||||
|
.map(Box::new)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_polymorphic_spec(name: &str, spec_props: &Yaml) -> PolymorphicTypeBuildSpec {
|
||||||
|
let enum_members = deserialize_polymorphic_enum_members(&spec_props["enum_members"]);
|
||||||
|
let build_kind = spec_props["build"]["kind"].as_str().unwrap();
|
||||||
|
PolymorphicTypeBuildSpec::new(name, enum_members, build_kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_production_spec(rule: &str, production_yaml: &Yaml) -> ProductionBuildSpec {
|
||||||
|
let kind = if production_yaml["kind"].is_hash() {
|
||||||
|
let node = production_yaml["kind"]["node"].as_str().unwrap();
|
||||||
|
ProductionKind::Node(node.to_string())
|
||||||
|
} else {
|
||||||
|
match production_yaml["kind"].as_str().unwrap() {
|
||||||
|
"int" => ProductionKind::Int,
|
||||||
|
"long" => ProductionKind::Long,
|
||||||
|
"double" => ProductionKind::Double,
|
||||||
|
"boolean" => ProductionKind::Boolean,
|
||||||
|
"string" => {
|
||||||
|
let from = match production_yaml["from"].as_str().unwrap() {
|
||||||
|
"string_inner" => ProductionStringFrom::StringInner,
|
||||||
|
"whole_pair" => ProductionStringFrom::WholePair,
|
||||||
|
_ => panic!(
|
||||||
|
"invalid from: {}",
|
||||||
|
production_yaml["from"].as_str().unwrap()
|
||||||
|
),
|
||||||
|
};
|
||||||
|
ProductionKind::String(from)
|
||||||
|
}
|
||||||
|
_ => panic!(
|
||||||
|
"invalid kind: {}",
|
||||||
|
production_yaml["kind"].as_str().unwrap()
|
||||||
|
),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ProductionBuildSpec::new(rule, kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_leaf_enum_rule(rule_yaml: &Yaml) -> Box<LeafEnumRule> {
|
||||||
|
Box::new(LeafEnumRule::new(rule_yaml.as_str().unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_leaf_enum_rules(rules_yaml: &Yaml) -> Vec<Box<LeafEnumRule>> {
|
||||||
|
rules_yaml
|
||||||
|
.as_vec()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|rule_yaml| deserialize_leaf_enum_rule(rule_yaml))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_enum_rule_custom_child(rule_props: &Yaml) -> Option<Box<EnumRuleChild>> {
|
||||||
|
if !rule_props["child"].as_bool().unwrap_or(true) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let kind = match rule_props["kind"].as_str().unwrap() {
|
||||||
|
"int" => EnumRuleChildKind::Int,
|
||||||
|
"long" => EnumRuleChildKind::Long,
|
||||||
|
"double" => EnumRuleChildKind::Double,
|
||||||
|
"usize" => EnumRuleChildKind::USize,
|
||||||
|
"string" => EnumRuleChildKind::String,
|
||||||
|
"boolean" => EnumRuleChildKind::Boolean,
|
||||||
|
_ => panic!(
|
||||||
|
"unsupported enum rule kind: {}",
|
||||||
|
rule_props["kind"].as_str().unwrap()
|
||||||
|
),
|
||||||
|
};
|
||||||
|
Some(Box::new(EnumRuleChild::new(Box::new(kind))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_enum_rule_node_child(rule: &str) -> Box<EnumRuleChild> {
|
||||||
|
Box::new(EnumRuleChild::new(Box::new(EnumRuleChildKind::Node(
|
||||||
|
EnumRuleNodeChild::new(rule),
|
||||||
|
))))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_enum_rule(rule_yaml: &Yaml) -> Box<EnumRule> {
|
||||||
|
if rule_yaml.is_hash() {
|
||||||
|
let (rule, rule_props) = unwrap_single_member_hash(rule_yaml);
|
||||||
|
Box::new(EnumRule::new(
|
||||||
|
&rule,
|
||||||
|
deserialize_enum_rule_custom_child(rule_props),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
let rule_as_str = rule_yaml.as_str().unwrap();
|
||||||
|
Box::new(EnumRule::new(
|
||||||
|
rule_as_str,
|
||||||
|
Some(deserialize_enum_rule_node_child(rule_as_str)),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_enum_rules(rules_yaml: &Yaml) -> Vec<Box<EnumRule>> {
|
||||||
|
rules_yaml
|
||||||
|
.as_vec()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|rule_yaml| deserialize_enum_rule(rule_yaml))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_leaf_struct_member(name: &str, props: &Yaml) -> Box<LeafStructMember> {
|
||||||
|
let kind = props["kind"].as_str().unwrap();
|
||||||
|
if kind == "string" {
|
||||||
|
Box::new(LeafStructMember::new(name, LeafStructMemberKind::String))
|
||||||
|
} else {
|
||||||
|
panic!("invalid member kind: {}", kind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_leaf_struct_members(members_yaml: &Yaml) -> Vec<Box<LeafStructMember>> {
|
||||||
|
members_yaml
|
||||||
|
.as_vec()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|member| {
|
||||||
|
let (member_name, member_props) = unwrap_single_member_hash(member);
|
||||||
|
deserialize_leaf_struct_member(&member_name, member_props)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_member_node_to_build(
|
||||||
|
rule: &str,
|
||||||
|
build_props: &Yaml,
|
||||||
|
optional: bool,
|
||||||
|
) -> Box<MemberChildToBuild> {
|
||||||
|
let or_else = build_props["or_else"]
|
||||||
|
.as_str()
|
||||||
|
.or_else(|| {
|
||||||
|
if get_as_bool(&build_props["or_else_default"]) {
|
||||||
|
Some("default")
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(ToString::to_string);
|
||||||
|
|
||||||
|
Box::new(MemberChildToBuild::Node(NodeChildToBuild::new(
|
||||||
|
rule, or_else, optional,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_member_boolean_to_build(name: &str) -> Box<MemberChildToBuild> {
|
||||||
|
Box::new(MemberChildToBuild::Boolean(BooleanChildToBuild::new(name)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_member_child_to_build(
|
||||||
|
name: &str,
|
||||||
|
rule: &str,
|
||||||
|
props: &Yaml,
|
||||||
|
optional: bool,
|
||||||
|
) -> Box<MemberChildToBuild> {
|
||||||
|
if props["build"].is_hash() {
|
||||||
|
let build_props = &props["build"];
|
||||||
|
let kind = build_props["kind"].as_str().or(Some("node")).unwrap();
|
||||||
|
if kind == "node" {
|
||||||
|
deserialize_member_node_to_build(rule, build_props, optional)
|
||||||
|
} else if kind == "boolean" {
|
||||||
|
deserialize_member_boolean_to_build(name)
|
||||||
|
} else {
|
||||||
|
panic!("unsupported kind: {}", kind)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let optional = get_as_bool(&props["optional"]);
|
||||||
|
Box::new(MemberChildToBuild::Node(NodeChildToBuild::new(
|
||||||
|
rule, None, optional,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_member_child(
|
||||||
|
name: &str,
|
||||||
|
rule: &str,
|
||||||
|
optional: bool,
|
||||||
|
props: &Yaml,
|
||||||
|
) -> Box<StructChildSpec> {
|
||||||
|
Box::new(StructChildSpec::MemberChild(MemberChild::new(
|
||||||
|
name,
|
||||||
|
rule,
|
||||||
|
deserialize_member_child_to_build(name, rule, props, optional),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_vec_node_child(name: &str, props: &Yaml) -> Box<StructChildSpec> {
|
||||||
|
let rule = props["rule"].as_str().unwrap();
|
||||||
|
Box::new(StructChildSpec::VecChild(VecChild::new(
|
||||||
|
name,
|
||||||
|
rule,
|
||||||
|
Box::new(VecChildToBuild::Node(VecNodeChildToBuild::new(rule))),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_vec_string_child(name: &str, props: &Yaml) -> Box<StructChildSpec> {
|
||||||
|
let rule = props["rule"].as_str().unwrap();
|
||||||
|
Box::new(StructChildSpec::VecChild(VecChild::new(
|
||||||
|
name,
|
||||||
|
rule,
|
||||||
|
Box::new(VecChildToBuild::String),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_vec_child(name: &str, props: &Yaml) -> Box<StructChildSpec> {
|
||||||
|
let kind = props["kind"].as_str().or_else(|| Some("node")).unwrap();
|
||||||
|
if kind == "node" {
|
||||||
|
deserialize_vec_node_child(name, props)
|
||||||
|
} else if kind == "string" {
|
||||||
|
deserialize_vec_string_child(name, props)
|
||||||
|
} else {
|
||||||
|
panic!("invalid kind: {}", kind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_skip_child(name: &str, rule: &str) -> Box<StructChildSpec> {
|
||||||
|
Box::new(StructChildSpec::SkipChild(SkipChild::new(name, rule)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_struct_hash_child(child: &Yaml) -> Box<StructChildSpec> {
|
||||||
|
let (name, props) = unwrap_single_member_hash(child);
|
||||||
|
|
||||||
|
let rule = props["rule"]
|
||||||
|
.as_str()
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.unwrap_or(name.to_case(Case::Pascal));
|
||||||
|
|
||||||
|
if get_as_bool(&props["skip"]) {
|
||||||
|
deserialize_skip_child(&name, &rule)
|
||||||
|
} else {
|
||||||
|
if get_as_bool(&props["vec"]) {
|
||||||
|
deserialize_vec_child(&name, props)
|
||||||
|
} else {
|
||||||
|
let optional = get_as_bool(&props["optional"]);
|
||||||
|
deserialize_member_child(&name, &rule, optional, props)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_struct_string_child(child: &Yaml) -> Box<StructChildSpec> {
|
||||||
|
let child_as_str = child.as_str().unwrap();
|
||||||
|
let child_name_pascal = child_as_str.to_case(Case::Pascal);
|
||||||
|
Box::new(StructChildSpec::MemberChild(MemberChild::new(
|
||||||
|
child_as_str,
|
||||||
|
&child_name_pascal,
|
||||||
|
Box::new(MemberChildToBuild::Node(NodeChildToBuild::new(
|
||||||
|
&child_name_pascal,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
))),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_struct_children(children: &Yaml) -> Vec<Box<StructChildSpec>> {
|
||||||
|
children
|
||||||
|
.as_vec()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|child_spec| {
|
||||||
|
if child_spec.is_hash() {
|
||||||
|
deserialize_struct_hash_child(child_spec)
|
||||||
|
} else {
|
||||||
|
deserialize_struct_string_child(child_spec)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_build_spec(build_spec_name: &str, build_spec: &Yaml) -> BuildSpec {
|
||||||
|
if build_spec["children"].is_array() {
|
||||||
|
let children = deserialize_struct_children(&build_spec["children"]);
|
||||||
|
BuildSpec::Struct(StructBuildSpec::new(build_spec_name, children))
|
||||||
|
} else if build_spec["members"].is_array() {
|
||||||
|
let members = deserialize_leaf_struct_members(&build_spec["members"]);
|
||||||
|
BuildSpec::LeafStruct(LeafStructBuildSpec::new(build_spec_name, members))
|
||||||
|
} else if build_spec["rules"].is_array() {
|
||||||
|
let rules = deserialize_enum_rules(&build_spec["rules"]);
|
||||||
|
BuildSpec::Enum(EnumBuildSpec::new(build_spec_name, rules))
|
||||||
|
} else if build_spec["leaf_rules"].is_array() {
|
||||||
|
let leaf_rules = deserialize_leaf_enum_rules(&build_spec["leaf_rules"]);
|
||||||
|
BuildSpec::LeafEnum(LeafEnumBuildSpec::new(build_spec_name, leaf_rules))
|
||||||
|
} else if build_spec["produce"].is_hash() {
|
||||||
|
BuildSpec::Production(deserialize_production_spec(
|
||||||
|
build_spec_name,
|
||||||
|
&build_spec["produce"],
|
||||||
|
))
|
||||||
|
} else if build_spec["polymorphic_type"].is_hash() {
|
||||||
|
BuildSpec::Polymorphic(deserialize_polymorphic_spec(
|
||||||
|
build_spec_name,
|
||||||
|
&build_spec["polymorphic_type"],
|
||||||
|
))
|
||||||
|
} else if build_spec["polymorphic_build"].is_hash() {
|
||||||
|
BuildSpec::PolymorphicBuild(deserialize_polymorphic_build_build_spec(
|
||||||
|
build_spec_name,
|
||||||
|
&build_spec["polymorphic_build"],
|
||||||
|
))
|
||||||
|
} else if build_spec["polymorphic_enum"].is_hash() {
|
||||||
|
BuildSpec::PolymorphicEnum(deserialize_polymorphic_enum_build_spec(
|
||||||
|
build_spec_name,
|
||||||
|
&build_spec["polymorphic_enum"],
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
panic!(
|
||||||
|
"Expected a node spec for either a struct, leaf_struct, enum, leaf_enum node type, production, polymorphic type, or polymorphic build type."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize_yaml_spec(yaml: &str) -> Vec<BuildSpec> {
|
||||||
|
let docs = YamlLoader::load_from_str(yaml).unwrap();
|
||||||
|
let doc = &docs[0];
|
||||||
|
|
||||||
|
doc.as_hash()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|(build_spec_name, build_spec)| {
|
||||||
|
let name_as_str = build_spec_name.as_str().unwrap();
|
||||||
|
deserialize_build_spec(name_as_str, build_spec)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
@ -1,13 +0,0 @@
|
|||||||
use yaml_rust2::Yaml;
|
|
||||||
use crate::spec::leaf_enum_spec::LeafEnumBuildSpec;
|
|
||||||
|
|
||||||
pub fn deserialize_leaf_enum(name: &str, props: &Yaml) -> LeafEnumBuildSpec {
|
|
||||||
let rules = props["rules"].as_vec()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.map(|rule_yaml| {
|
|
||||||
rule_yaml.as_str().unwrap().to_string()
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
LeafEnumBuildSpec::new(name, rules)
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
use crate::deserialize::util::unwrap_single_member_hash;
|
|
||||||
use yaml_rust2::Yaml;
|
|
||||||
use crate::spec::leaf_struct_spec::{LeafStructBuildSpec, LeafStructMember, LeafStructMemberKind};
|
|
||||||
|
|
||||||
fn deserialize_member(member_name: &str) -> LeafStructMember {
|
|
||||||
LeafStructMember::new(member_name, LeafStructMemberKind::String)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize_leaf_struct(name: &str, props: &Yaml) -> LeafStructBuildSpec {
|
|
||||||
let members = props["members"]
|
|
||||||
.as_vec()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.map(|member_hash| {
|
|
||||||
let (member_name, _props) = unwrap_single_member_hash(member_hash);
|
|
||||||
deserialize_member(&member_name)
|
|
||||||
})
|
|
||||||
.map(Box::new)
|
|
||||||
.collect();
|
|
||||||
LeafStructBuildSpec::new(name, members)
|
|
||||||
}
|
|
||||||
@ -1,87 +0,0 @@
|
|||||||
mod leaf_enum_spec;
|
|
||||||
mod leaf_struct_spec;
|
|
||||||
mod node_production_spec;
|
|
||||||
mod polymorphic_enum_loop_spec;
|
|
||||||
mod polymorphic_pass_through_spec;
|
|
||||||
mod polymorphic_type_spec;
|
|
||||||
mod production_spec;
|
|
||||||
mod struct_spec;
|
|
||||||
mod tree_enum_spec;
|
|
||||||
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_loop_spec::deserialize_polymorphic_enum_loop;
|
|
||||||
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;
|
|
||||||
|
|
||||||
fn deserialize_build_spec(build_spec_name: &str, build_spec: &Yaml) -> BuildSpec {
|
|
||||||
if build_spec["struct"].is_hash() {
|
|
||||||
BuildSpec::Struct(deserialize_struct_spec(
|
|
||||||
build_spec_name,
|
|
||||||
&build_spec["struct"],
|
|
||||||
))
|
|
||||||
} else if build_spec["leaf_struct"].is_hash() {
|
|
||||||
BuildSpec::LeafStruct(deserialize_leaf_struct(
|
|
||||||
build_spec_name,
|
|
||||||
&build_spec["leaf_struct"],
|
|
||||||
))
|
|
||||||
} else if build_spec["tree_enum"].is_hash() {
|
|
||||||
BuildSpec::Enum(deserialize_tree_enum(
|
|
||||||
build_spec_name,
|
|
||||||
&build_spec["tree_enum"],
|
|
||||||
))
|
|
||||||
} else if build_spec["leaf_enum"].is_hash() {
|
|
||||||
BuildSpec::LeafEnum(deserialize_leaf_enum(
|
|
||||||
build_spec_name,
|
|
||||||
&build_spec["leaf_enum"],
|
|
||||||
))
|
|
||||||
} else if build_spec["production"].is_hash() {
|
|
||||||
BuildSpec::Production(deserialize_production(
|
|
||||||
build_spec_name,
|
|
||||||
&build_spec["production"],
|
|
||||||
))
|
|
||||||
} else if build_spec["node_production"].is_hash() {
|
|
||||||
BuildSpec::NodeProduction(deserialize_node_production(
|
|
||||||
build_spec_name,
|
|
||||||
&build_spec["node_production"],
|
|
||||||
))
|
|
||||||
} else if build_spec["polymorphic_type"].is_hash() {
|
|
||||||
BuildSpec::PolymorphicType(deserialize_polymorphic_type(
|
|
||||||
build_spec_name,
|
|
||||||
&build_spec["polymorphic_type"],
|
|
||||||
))
|
|
||||||
} else if build_spec["polymorphic_enum_loop_build"].is_hash() {
|
|
||||||
BuildSpec::PolymorphicEnumLoop(deserialize_polymorphic_enum_loop(
|
|
||||||
build_spec_name,
|
|
||||||
&build_spec["polymorphic_enum_loop_build"],
|
|
||||||
))
|
|
||||||
} else if build_spec["polymorphic_pass_through"].is_hash() {
|
|
||||||
BuildSpec::PolymorphicPassThrough(deserialize_polymorphic_pass_through(
|
|
||||||
build_spec_name,
|
|
||||||
&build_spec["polymorphic_pass_through"],
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
panic!("Missing or incorrect build type for {}", build_spec_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize_yaml_spec(yaml: &str) -> Vec<BuildSpec> {
|
|
||||||
let docs = YamlLoader::load_from_str(yaml).unwrap();
|
|
||||||
let doc = &docs[0];
|
|
||||||
|
|
||||||
doc.as_hash()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.map(|(build_spec_name, build_spec)| {
|
|
||||||
let name_as_str = build_spec_name.as_str().unwrap();
|
|
||||||
deserialize_build_spec(name_as_str, build_spec)
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
use crate::deserialize::util::make_build_fn_name;
|
|
||||||
use crate::spec::node_production_spec::NodeProductionBuildSpec;
|
|
||||||
use yaml_rust2::Yaml;
|
|
||||||
|
|
||||||
pub fn deserialize_node_production(name: &str, props: &Yaml) -> NodeProductionBuildSpec {
|
|
||||||
let kind = props["kind"].as_str().unwrap();
|
|
||||||
let with = make_build_fn_name(props["with"].as_str().unwrap());
|
|
||||||
NodeProductionBuildSpec::new(name, kind, &with)
|
|
||||||
}
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
use crate::deserialize::util::{make_build_fn_name, unwrap_single_member_hash};
|
|
||||||
use crate::spec::polymorphic_enum_loop_spec::{
|
|
||||||
PolymorphicEnumLoopBuildSpec, PolymorphicEnumLoopChildUseCurrent, PolymorphicEnumLoopRule,
|
|
||||||
PolymorphicEnumLoopRuleBuild, PolymorphicEnumLoopRuleBuildChild,
|
|
||||||
PolymorphicEnumLoopRuleChildOnEach, PolymorphicEnumLoopRulePassThrough,
|
|
||||||
};
|
|
||||||
use yaml_rust2::Yaml;
|
|
||||||
|
|
||||||
fn deserialize_build_child(child_name: &str, props: &Yaml) -> PolymorphicEnumLoopRuleBuildChild {
|
|
||||||
if props["use_current"].is_hash() {
|
|
||||||
let kind = props["use_current"]["kind"].as_str().unwrap();
|
|
||||||
PolymorphicEnumLoopRuleBuildChild::UseCurrent(PolymorphicEnumLoopChildUseCurrent::new(
|
|
||||||
child_name, kind,
|
|
||||||
))
|
|
||||||
} else if props["on_each"].is_hash() {
|
|
||||||
let rule = props["on_each"]["rule"].as_str().unwrap();
|
|
||||||
PolymorphicEnumLoopRuleBuildChild::OnEach(PolymorphicEnumLoopRuleChildOnEach::new(
|
|
||||||
child_name, rule,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
panic!("Expected 'use_current' or 'on_each' hash for polymorphic enum loop build child");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_build(name: &str, props: &Yaml) -> PolymorphicEnumLoopRuleBuild {
|
|
||||||
let variant = props["variant"].as_str().unwrap();
|
|
||||||
let children = props["children"]
|
|
||||||
.as_vec()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.map(|child_yaml| {
|
|
||||||
let (child_name, child_props) = unwrap_single_member_hash(child_yaml);
|
|
||||||
deserialize_build_child(&child_name, child_props)
|
|
||||||
})
|
|
||||||
.map(Box::new)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
PolymorphicEnumLoopRuleBuild::new(name, variant, children)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_pass_through(name: &str, props: &Yaml) -> PolymorphicEnumLoopRulePassThrough {
|
|
||||||
let kind = props["kind"].as_str().unwrap();
|
|
||||||
let with = make_build_fn_name(
|
|
||||||
props["with"].as_str()
|
|
||||||
.unwrap_or(kind)
|
|
||||||
);
|
|
||||||
PolymorphicEnumLoopRulePassThrough::new(name, kind, &with)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_rule(rule_name: &str, props: &Yaml) -> PolymorphicEnumLoopRule {
|
|
||||||
if props["pass_through"].is_hash() {
|
|
||||||
PolymorphicEnumLoopRule::PassThrough(deserialize_pass_through(
|
|
||||||
rule_name,
|
|
||||||
&props["pass_through"],
|
|
||||||
))
|
|
||||||
} else if props["build"].is_hash() {
|
|
||||||
PolymorphicEnumLoopRule::Build(deserialize_build(rule_name, &props["build"]))
|
|
||||||
} else {
|
|
||||||
panic!("Polymorphic enum loop rule must have 'pass_through' or 'build' hash.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize_polymorphic_enum_loop(name: &str, props: &Yaml) -> PolymorphicEnumLoopBuildSpec {
|
|
||||||
let kind = props["kind"].as_str().unwrap();
|
|
||||||
let rules = props["rules"]
|
|
||||||
.as_vec()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.map(|rule_yaml| {
|
|
||||||
let (rule_name, rule_props) = unwrap_single_member_hash(rule_yaml);
|
|
||||||
deserialize_rule(&rule_name, rule_props)
|
|
||||||
})
|
|
||||||
.map(Box::new)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
PolymorphicEnumLoopBuildSpec::new(name, kind, rules)
|
|
||||||
}
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
use crate::deserialize::util::unwrap_single_member_hash;
|
|
||||||
use crate::spec::polymorphic_pass_through_spec::{PolymorphicPassThroughBuildSpec, PolymorphicPassThroughVariant};
|
|
||||||
use yaml_rust2::Yaml;
|
|
||||||
|
|
||||||
pub fn deserialize_polymorphic_pass_through(name: &str, props: &Yaml) -> PolymorphicPassThroughBuildSpec {
|
|
||||||
let build_kind = props["build"]["kind"].as_str().unwrap();
|
|
||||||
let variants = props["variants"].as_vec().unwrap()
|
|
||||||
.iter()
|
|
||||||
.map(|variant_yaml| {
|
|
||||||
let (variant_name, variant_props) = unwrap_single_member_hash(variant_yaml);
|
|
||||||
if variant_props["inner"].is_hash() {
|
|
||||||
let inner_kind = variant_props["inner"]["kind"].as_str().unwrap();
|
|
||||||
PolymorphicPassThroughVariant::Inner {
|
|
||||||
name: variant_name,
|
|
||||||
kind: inner_kind.to_string(),
|
|
||||||
}
|
|
||||||
} else if variant_props["pass_through"].is_hash() {
|
|
||||||
let pass_through_kind = variant_props["pass_through"]["kind"].is_hash();
|
|
||||||
PolymorphicPassThroughVariant::PassThrough {
|
|
||||||
name: variant_name,
|
|
||||||
kind: pass_through_kind.to_string(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic!()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(Box::new)
|
|
||||||
.collect();
|
|
||||||
PolymorphicPassThroughBuildSpec::new(name, build_kind, variants)
|
|
||||||
}
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
use crate::deserialize::util::unwrap_single_member_hash;
|
|
||||||
use crate::spec::polymorphic_type_spec::{PolymorphicTypeBuildSpec, PolymorphicTypeVariant};
|
|
||||||
use yaml_rust2::Yaml;
|
|
||||||
|
|
||||||
fn deserialize_variant(variant_name: &str, props: &Yaml) -> PolymorphicTypeVariant {
|
|
||||||
let inner_kind = props["inner"]["kind"].as_str().unwrap();
|
|
||||||
PolymorphicTypeVariant::new(variant_name, inner_kind)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize_polymorphic_type(name: &str, props: &Yaml) -> PolymorphicTypeBuildSpec {
|
|
||||||
let variants = props["variants"]
|
|
||||||
.as_vec()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.map(|variant_yaml| {
|
|
||||||
let (variant_name, variant_props) = unwrap_single_member_hash(variant_yaml);
|
|
||||||
deserialize_variant(&variant_name, variant_props)
|
|
||||||
})
|
|
||||||
.map(Box::new)
|
|
||||||
.collect();
|
|
||||||
let kind = props["build"]["kind"].as_str().unwrap();
|
|
||||||
PolymorphicTypeBuildSpec::new(name, variants, kind)
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
use crate::spec::production_spec::{ProductionBooleanFrom, ProductionBuildSpec, ProductionKind, ProductionStringFrom};
|
|
||||||
use yaml_rust2::Yaml;
|
|
||||||
|
|
||||||
pub fn deserialize_production(name: &str, props: &Yaml) -> ProductionBuildSpec {
|
|
||||||
let kind = match props["kind"].as_str().unwrap() {
|
|
||||||
"int" => ProductionKind::Int,
|
|
||||||
"long" => ProductionKind::Long,
|
|
||||||
"double" => ProductionKind::Double,
|
|
||||||
"string" => {
|
|
||||||
let from = match props["from"].as_str().unwrap() {
|
|
||||||
"string_inner" => ProductionStringFrom::StringInner,
|
|
||||||
"whole_pair" => ProductionStringFrom::WholePair,
|
|
||||||
_ => panic!("Unknown string production from: {}", props["from"].as_str().unwrap())
|
|
||||||
};
|
|
||||||
ProductionKind::String(from)
|
|
||||||
},
|
|
||||||
"boolean" => ProductionKind::Boolean(ProductionBooleanFrom::ParseWholePair),
|
|
||||||
_ => panic!("Unknown production kind: {}", props["kind"].as_str().unwrap()),
|
|
||||||
};
|
|
||||||
ProductionBuildSpec::new(name, kind)
|
|
||||||
}
|
|
||||||
@ -1,155 +0,0 @@
|
|||||||
use crate::deserialize_error;
|
|
||||||
use convert_case::{Case, Casing};
|
|
||||||
|
|
||||||
use crate::deserialize::util::{get_as_bool, make_build_fn_name, unwrap_single_member_hash};
|
|
||||||
use crate::spec::struct_spec::*;
|
|
||||||
use yaml_rust2::Yaml;
|
|
||||||
|
|
||||||
fn deserialize_skip_child(props: &Yaml) -> StructChild {
|
|
||||||
let rule = props["rule"].as_str().unwrap();
|
|
||||||
StructChild::SkipChild(SkipChild::new(rule))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_vec_child(child_name: &str, props: &Yaml) -> StructChild {
|
|
||||||
let rule = props["rule"].as_str().unwrap();
|
|
||||||
let kind = props["kind"].as_str()
|
|
||||||
.unwrap_or(rule);
|
|
||||||
if kind == "string" {
|
|
||||||
let build = VecChildBuild::String(VecChildStringBuild::new(
|
|
||||||
&make_build_fn_name(rule)
|
|
||||||
));
|
|
||||||
StructChild::VecChild(VecChild::new(
|
|
||||||
child_name,
|
|
||||||
rule,
|
|
||||||
Box::new(build),
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
let build = VecChildBuild::Node(VecChildNodeBuild::new(
|
|
||||||
rule,
|
|
||||||
&make_build_fn_name(rule)
|
|
||||||
));
|
|
||||||
StructChild::VecChild(VecChild::new(child_name, rule, Box::new(build)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_member_build(child_name: &str, rule: &str, props: &Yaml) -> MemberChildBuild {
|
|
||||||
if props["node"].is_hash() {
|
|
||||||
let node_props = &props["node"];
|
|
||||||
let kind = node_props["kind"].as_str().unwrap_or(rule);
|
|
||||||
let with = node_props["with"]
|
|
||||||
.as_str()
|
|
||||||
.map(ToString::to_string)
|
|
||||||
.unwrap_or_else(|| make_build_fn_name(kind));
|
|
||||||
|
|
||||||
let or_else = if get_as_bool(&node_props["or_else_default"]) {
|
|
||||||
Some(String::from("default"))
|
|
||||||
} else if let Some(or_else) = node_props["or_else"].as_str() {
|
|
||||||
Some(or_else.to_string())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
MemberChildBuild::Node(NodeMemberBuild::new(kind, &with, or_else))
|
|
||||||
} else if props["boolean"].is_hash() {
|
|
||||||
let boolean_props = &props["boolean"];
|
|
||||||
if let Some(on) = boolean_props["on"].as_str() {
|
|
||||||
if on == "rule_present" {
|
|
||||||
MemberChildBuild::Boolean(BooleanMemberBuild::new(
|
|
||||||
BooleanMemberBuildOn::RulePresent,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
panic!(
|
|
||||||
"Expected 'on' in 'boolean' in 'build' in {} to be 'rule_present'",
|
|
||||||
child_name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic!("Expected 'on' in 'boolean' in 'build' in {}", child_name);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic!(
|
|
||||||
"Expected either of 'node' or 'boolean' in 'build' in {}",
|
|
||||||
child_name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_member_child(child_name: &str, props: &Yaml) -> StructChild {
|
|
||||||
let rule = props["rule"]
|
|
||||||
.as_str()
|
|
||||||
.map(ToString::to_string)
|
|
||||||
.unwrap_or_else(|| child_name.to_case(Case::Pascal));
|
|
||||||
let optional = get_as_bool(&props["optional"]);
|
|
||||||
if props["build"].is_hash() {
|
|
||||||
let build = deserialize_member_build(child_name, &rule, &props["build"]);
|
|
||||||
StructChild::MemberChild(MemberChild::new(
|
|
||||||
child_name,
|
|
||||||
&rule,
|
|
||||||
optional,
|
|
||||||
Box::new(build),
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
StructChild::MemberChild(MemberChild::new(
|
|
||||||
child_name,
|
|
||||||
&rule,
|
|
||||||
optional,
|
|
||||||
Box::new(MemberChildBuild::Node(NodeMemberBuild::new(
|
|
||||||
&rule,
|
|
||||||
&make_build_fn_name(&rule),
|
|
||||||
None,
|
|
||||||
))),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild {
|
|
||||||
if props["skip"].is_hash() {
|
|
||||||
deserialize_skip_child(&props["skip"])
|
|
||||||
} else if props["vec"].is_hash() {
|
|
||||||
deserialize_vec_child(name, &props["vec"])
|
|
||||||
} else if props["member"].is_hash() {
|
|
||||||
deserialize_member_child(name, &props["member"])
|
|
||||||
} else {
|
|
||||||
panic!("Expected 'skip' or 'vec' in 'member' in {}", name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_string_child(name: &str) -> StructChild {
|
|
||||||
let name_pascal = name.to_case(Case::Pascal);
|
|
||||||
StructChild::MemberChild(MemberChild::new(
|
|
||||||
name,
|
|
||||||
&name_pascal,
|
|
||||||
false,
|
|
||||||
Box::new(MemberChildBuild::Node(NodeMemberBuild::new(
|
|
||||||
&name_pascal,
|
|
||||||
&make_build_fn_name(name),
|
|
||||||
None,
|
|
||||||
))),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_children(children_yaml: &Yaml) -> Vec<Box<StructChild>> {
|
|
||||||
children_yaml
|
|
||||||
.as_vec()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.map(|child_yaml| {
|
|
||||||
if let Some(name) = child_yaml.as_str() {
|
|
||||||
deserialize_string_child(name)
|
|
||||||
} else {
|
|
||||||
let (child_name, child_props) = unwrap_single_member_hash(child_yaml);
|
|
||||||
deserialize_hash_child(&child_name, child_props)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(Box::new)
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize_struct_spec(name: &str, struct_yaml: &Yaml) -> StructSpec {
|
|
||||||
let children = if struct_yaml["children"].is_array() {
|
|
||||||
deserialize_children(&struct_yaml["children"])
|
|
||||||
} else {
|
|
||||||
deserialize_error!("array", "children", name);
|
|
||||||
};
|
|
||||||
StructSpec::new(name, children)
|
|
||||||
}
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
use convert_case::{Case, Casing};
|
|
||||||
use crate::deserialize::util::{get_as_bool_or, make_build_fn_name, unwrap_single_member_hash};
|
|
||||||
use crate::spec::tree_enum_spec::{EnumRuleChild, EnumRuleChildKind, EnumRuleChildNodeKind, NameAndWith, TreeEnumBuildSpec, TreeEnumRule};
|
|
||||||
use yaml_rust2::Yaml;
|
|
||||||
|
|
||||||
fn deserialize_hash_enum_rule(rule: &str, props: &Yaml) -> TreeEnumRule {
|
|
||||||
if get_as_bool_or(&props["child"], true) {
|
|
||||||
let name_and_with = NameAndWith::new(
|
|
||||||
&rule.to_case(Case::Snake),
|
|
||||||
&make_build_fn_name(rule)
|
|
||||||
);
|
|
||||||
let kind = match props["kind"].as_str().unwrap() {
|
|
||||||
"int" => EnumRuleChildKind::Int(name_and_with),
|
|
||||||
"long" => EnumRuleChildKind::Long(name_and_with),
|
|
||||||
"double" => EnumRuleChildKind::Double(name_and_with),
|
|
||||||
"string" => EnumRuleChildKind::String(name_and_with),
|
|
||||||
"boolean" => EnumRuleChildKind::Boolean(name_and_with),
|
|
||||||
_ => panic!("Invalid kind: {}", props["kind"].as_str().unwrap()),
|
|
||||||
};
|
|
||||||
TreeEnumRule::new(rule, Some(Box::new(EnumRuleChild::new(Box::new(kind)))))
|
|
||||||
} else {
|
|
||||||
// no child
|
|
||||||
TreeEnumRule::new(rule, None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_string_enum_rule(rule: &str) -> TreeEnumRule {
|
|
||||||
TreeEnumRule::new(
|
|
||||||
rule,
|
|
||||||
Some(Box::new(EnumRuleChild::new(Box::new(
|
|
||||||
EnumRuleChildKind::Node(EnumRuleChildNodeKind::new(
|
|
||||||
rule,
|
|
||||||
&make_build_fn_name(rule)
|
|
||||||
)),
|
|
||||||
)))),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize_tree_enum(name: &str, props: &Yaml) -> TreeEnumBuildSpec {
|
|
||||||
let rules = props["rules"]
|
|
||||||
.as_vec()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.map(|rule_yaml| {
|
|
||||||
if let Some(rule) = rule_yaml.as_str() {
|
|
||||||
deserialize_string_enum_rule(rule)
|
|
||||||
} else {
|
|
||||||
let (rule, props) = unwrap_single_member_hash(rule_yaml);
|
|
||||||
deserialize_hash_enum_rule(&rule, props)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(Box::new)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
TreeEnumBuildSpec::new(name, rules)
|
|
||||||
}
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
use convert_case::{Case, Casing};
|
|
||||||
use yaml_rust2::Yaml;
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! deserialize_error {
|
|
||||||
($kind:expr, $key:expr, $name:expr) => {
|
|
||||||
panic!("Expected {} '{}' in {}.", $kind, $key, $name);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn make_build_fn_name(s: &str) -> String {
|
|
||||||
format!("build_{}", s.to_case(Case::Snake))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn make_build_pair(s: &str) -> String {
|
|
||||||
format!("{}_pair", s.to_case(Case::Snake))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unwrap_single_member_hash(hash: &Yaml) -> (String, &Yaml) {
|
|
||||||
let as_hash = hash.as_hash().unwrap();
|
|
||||||
if as_hash.is_empty() {
|
|
||||||
panic!("empty hash");
|
|
||||||
} else if as_hash.len() > 1 {
|
|
||||||
panic!("hash contains more than one key");
|
|
||||||
}
|
|
||||||
let (member_key, member_value) = as_hash.iter().collect::<Vec<(&Yaml, &Yaml)>>()[0];
|
|
||||||
let key_as_string = member_key.as_str().unwrap().to_string();
|
|
||||||
(key_as_string, member_value)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_as_bool(yaml: &Yaml) -> bool {
|
|
||||||
yaml.as_bool().unwrap_or(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_as_bool_or(yaml: &Yaml, or: bool) -> bool {
|
|
||||||
yaml.as_bool().unwrap_or(or)
|
|
||||||
}
|
|
||||||
@ -1,9 +1,9 @@
|
|||||||
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
use crate::spec::{EnumBuildSpec, EnumRuleChildKind};
|
||||||
use crate::spec::tree_enum_spec::{EnumRuleChildKind, TreeEnumBuildSpec};
|
use crate::util::{make_build_fn_name, make_build_pair};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
pub fn make_enum_build_fn(enum_build_spec: &TreeEnumBuildSpec) -> TokenStream {
|
pub fn make_enum_build_fn(enum_build_spec: &EnumBuildSpec) -> TokenStream {
|
||||||
let build_fn_ident = format_ident!("{}", make_build_fn_name(enum_build_spec.build()));
|
let build_fn_ident = format_ident!("{}", make_build_fn_name(enum_build_spec.build()));
|
||||||
let pair_ident = format_ident!("{}", make_build_pair(enum_build_spec.build()));
|
let pair_ident = format_ident!("{}", make_build_pair(enum_build_spec.build()));
|
||||||
let return_type_ident = format_ident!("{}", enum_build_spec.build());
|
let return_type_ident = format_ident!("{}", enum_build_spec.build());
|
||||||
@ -16,27 +16,12 @@ pub fn make_enum_build_fn(enum_build_spec: &TreeEnumBuildSpec) -> TokenStream {
|
|||||||
let inner_builder = match child.kind() {
|
let inner_builder = match child.kind() {
|
||||||
EnumRuleChildKind::Node(node_child) => {
|
EnumRuleChildKind::Node(node_child) => {
|
||||||
let inner_build_fn_ident =
|
let inner_build_fn_ident =
|
||||||
format_ident!("{}", node_child.with());
|
format_ident!("{}", make_build_fn_name(node_child.build()));
|
||||||
quote! { #inner_build_fn_ident(inner_pair) }
|
quote! { #inner_build_fn_ident(inner_pair) }
|
||||||
}
|
}
|
||||||
EnumRuleChildKind::Int(name_and_with) => {
|
_ => {
|
||||||
let inner_build_fn_ident = format_ident!("{}", name_and_with.with());
|
let inner_build_fn_ident =
|
||||||
quote! { #inner_build_fn_ident(inner_pair) }
|
format_ident!("{}", make_build_fn_name(enum_rule.rule()));
|
||||||
}
|
|
||||||
EnumRuleChildKind::Long(name_and_with) => {
|
|
||||||
let inner_build_fn_ident = format_ident!("{}", name_and_with.with());
|
|
||||||
quote! { #inner_build_fn_ident(inner_pair) }
|
|
||||||
}
|
|
||||||
EnumRuleChildKind::Double(name_and_with) => {
|
|
||||||
let inner_build_fn_ident = format_ident!("{}", name_and_with.with());
|
|
||||||
quote! { #inner_build_fn_ident(inner_pair) }
|
|
||||||
}
|
|
||||||
EnumRuleChildKind::String(name_and_with) => {
|
|
||||||
let inner_build_fn_ident = format_ident!("{}", name_and_with.with());
|
|
||||||
quote! { #inner_build_fn_ident(inner_pair) }
|
|
||||||
}
|
|
||||||
EnumRuleChildKind::Boolean(name_and_with) => {
|
|
||||||
let inner_build_fn_ident = format_ident!("{}", name_and_with.with());
|
|
||||||
quote! { #inner_build_fn_ident(inner_pair) }
|
quote! { #inner_build_fn_ident(inner_pair) }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
use crate::spec::LeafEnumBuildSpec;
|
||||||
use crate::spec::leaf_enum_spec::LeafEnumBuildSpec;
|
use crate::util::{make_build_fn_name, make_build_pair};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
@ -8,10 +8,9 @@ pub fn make_leaf_enum_build_fn(leaf_enum_build_spec: &LeafEnumBuildSpec) -> Toke
|
|||||||
let pair_ident = format_ident!("{}", make_build_pair(leaf_enum_build_spec.build()));
|
let pair_ident = format_ident!("{}", make_build_pair(leaf_enum_build_spec.build()));
|
||||||
let return_type_ident = format_ident!("{}", leaf_enum_build_spec.build());
|
let return_type_ident = format_ident!("{}", leaf_enum_build_spec.build());
|
||||||
|
|
||||||
let rule_branches = leaf_enum_build_spec
|
let rule_branches = leaf_enum_build_spec.rules()
|
||||||
.rules()
|
|
||||||
.map(|leaf_enum_rule| {
|
.map(|leaf_enum_rule| {
|
||||||
let rule_ident = format_ident!("{}", leaf_enum_rule);
|
let rule_ident = format_ident!("{}", leaf_enum_rule.rule());
|
||||||
quote! {
|
quote! {
|
||||||
Rule::#rule_ident => #return_type_ident::#rule_ident
|
Rule::#rule_ident => #return_type_ident::#rule_ident
|
||||||
}
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
use crate::spec::{LeafStructBuildSpec, LeafStructMemberKind};
|
||||||
use crate::spec::leaf_struct_spec::{LeafStructBuildSpec, LeafStructMemberKind};
|
use crate::util::{make_build_fn_name, make_build_pair};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
@ -1,12 +1,26 @@
|
|||||||
mod build_fn;
|
pub mod deserialize;
|
||||||
mod deserialize;
|
mod enum_build_fn;
|
||||||
|
mod leaf_enum_build_fn;
|
||||||
|
mod leaf_struct_build_fn;
|
||||||
|
mod polymorphic_build_build_fn;
|
||||||
|
mod polymorphic_build_fn;
|
||||||
|
mod polymorphic_enum_build_fn;
|
||||||
mod pretty_print;
|
mod pretty_print;
|
||||||
|
mod production_build_fn;
|
||||||
mod spec;
|
mod spec;
|
||||||
|
mod struct_build_fn;
|
||||||
mod type_gen;
|
mod type_gen;
|
||||||
|
mod util;
|
||||||
|
|
||||||
use crate::build_fn::make_build_fn;
|
use crate::enum_build_fn::make_enum_build_fn;
|
||||||
use crate::deserialize::deserialize_yaml_spec;
|
use crate::leaf_enum_build_fn::make_leaf_enum_build_fn;
|
||||||
// use crate::pretty_print::make_pretty_print_impl;
|
use crate::leaf_struct_build_fn::make_leaf_struct_build_fn;
|
||||||
|
use crate::polymorphic_build_build_fn::make_polymorphic_build_build_fn;
|
||||||
|
use crate::polymorphic_build_fn::make_polymorphic_build_fn;
|
||||||
|
use crate::polymorphic_enum_build_fn::make_polymorphic_enum_build_fn;
|
||||||
|
use crate::pretty_print::make_pretty_print_impl;
|
||||||
|
use crate::production_build_fn::make_production_build_fn;
|
||||||
|
use crate::struct_build_fn::make_struct_build_fn;
|
||||||
use crate::type_gen::make_type;
|
use crate::type_gen::make_type;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
@ -32,30 +46,24 @@ fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
BuildSpec::Production(production_build_spec) => {
|
BuildSpec::Production(production_build_spec) => {
|
||||||
println!("Production Spec - name: {}", production_build_spec.name());
|
println!("Production Spec - rule: {}", production_build_spec.rule());
|
||||||
}
|
}
|
||||||
BuildSpec::NodeProduction(node_production_build_spec) => {
|
BuildSpec::Polymorphic(polymorphic_build_spec) => {
|
||||||
println!(
|
|
||||||
"Node Production Spec - name: {}",
|
|
||||||
node_production_build_spec.name()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
BuildSpec::PolymorphicType(polymorphic_build_spec) => {
|
|
||||||
println!(
|
println!(
|
||||||
"Polymorphic Type Spec - name: {}",
|
"Polymorphic Type Spec - name: {}",
|
||||||
polymorphic_build_spec.name()
|
polymorphic_build_spec.name()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop_build_spec) => {
|
BuildSpec::PolymorphicBuild(polymorphic_build_build_spec) => {
|
||||||
println!(
|
println!(
|
||||||
"Polymorphic Enum Loop Spec - name: {}",
|
"Polymorphic Build Spec - name: {}",
|
||||||
polymorphic_enum_loop_build_spec.name()
|
polymorphic_build_build_spec.name()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
BuildSpec::PolymorphicPassThrough(pass_through_build_spec) => {
|
BuildSpec::PolymorphicEnum(polymorphic_enum_build_spec) => {
|
||||||
println!(
|
println!(
|
||||||
"Polymorphic Pass Through Spec - name: {}",
|
"Polymorphic Enum Spec - name: {}",
|
||||||
pass_through_build_spec.name()
|
polymorphic_enum_build_spec.name()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,13 +85,49 @@ fn token_stream_to_string(token_stream: TokenStream) -> String {
|
|||||||
fn generate_build_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
fn generate_build_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
||||||
let build_fns = build_specs
|
let build_fns = build_specs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|build_spec| {
|
.map(|build_spec| match build_spec {
|
||||||
let build_fn = make_build_fn(build_spec);
|
BuildSpec::Enum(enum_build_spec) => {
|
||||||
debug_built_spec(build_spec, &build_fn);
|
let stream = make_enum_build_fn(enum_build_spec);
|
||||||
build_fn
|
debug_built_spec(build_spec, &stream);
|
||||||
|
stream
|
||||||
|
}
|
||||||
|
BuildSpec::LeafEnum(leaf_enum_build_spec) => {
|
||||||
|
let stream = make_leaf_enum_build_fn(leaf_enum_build_spec);
|
||||||
|
debug_built_spec(build_spec, &stream);
|
||||||
|
stream
|
||||||
|
}
|
||||||
|
BuildSpec::Struct(struct_build_spec) => {
|
||||||
|
let stream = make_struct_build_fn(struct_build_spec);
|
||||||
|
debug_built_spec(build_spec, &stream);
|
||||||
|
stream
|
||||||
|
}
|
||||||
|
BuildSpec::LeafStruct(leaf_struct_build_spec) => {
|
||||||
|
let stream = make_leaf_struct_build_fn(leaf_struct_build_spec);
|
||||||
|
debug_built_spec(build_spec, &stream);
|
||||||
|
stream
|
||||||
|
}
|
||||||
|
BuildSpec::Production(production_build_spec) => {
|
||||||
|
let stream = make_production_build_fn(production_build_spec);
|
||||||
|
debug_built_spec(build_spec, &stream);
|
||||||
|
stream
|
||||||
|
}
|
||||||
|
BuildSpec::Polymorphic(polymorphic_build_spec) => {
|
||||||
|
let stream = make_polymorphic_build_fn(polymorphic_build_spec);
|
||||||
|
debug_built_spec(build_spec, &stream);
|
||||||
|
stream
|
||||||
|
}
|
||||||
|
BuildSpec::PolymorphicBuild(polymorphic_build_build_spec) => {
|
||||||
|
let stream = make_polymorphic_build_build_fn(polymorphic_build_build_spec);
|
||||||
|
debug_built_spec(build_spec, &stream);
|
||||||
|
stream
|
||||||
|
}
|
||||||
|
BuildSpec::PolymorphicEnum(polymorphic_enum_build_spec) => {
|
||||||
|
let stream = make_polymorphic_enum_build_fn(polymorphic_enum_build_spec);
|
||||||
|
debug_built_spec(build_spec, &stream);
|
||||||
|
stream
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let combined = quote! {
|
let combined = quote! {
|
||||||
//noinspection RsUnusedImport
|
//noinspection RsUnusedImport
|
||||||
use crate::parser::Rule;
|
use crate::parser::Rule;
|
||||||
@ -94,7 +138,6 @@ fn generate_build_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
|||||||
|
|
||||||
#(#build_fns)*
|
#(#build_fns)*
|
||||||
};
|
};
|
||||||
|
|
||||||
AstGeneratedFile {
|
AstGeneratedFile {
|
||||||
name: String::from("build.rs"),
|
name: String::from("build.rs"),
|
||||||
contents: token_stream_to_string(combined),
|
contents: token_stream_to_string(combined),
|
||||||
@ -117,34 +160,29 @@ fn generate_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn generate_pretty_print_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
fn generate_pretty_print_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
||||||
// let impls = build_specs
|
let impls = build_specs
|
||||||
// .iter()
|
.iter()
|
||||||
// .map(|build_spec| {
|
.map(|build_spec| {
|
||||||
// let stream = make_pretty_print_impl(build_spec);
|
let stream = make_pretty_print_impl(build_spec);
|
||||||
// debug_built_spec(build_spec, &stream);
|
debug_built_spec(build_spec, &stream);
|
||||||
// stream
|
stream
|
||||||
// })
|
})
|
||||||
// .collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
//
|
|
||||||
// let combined = quote! {
|
let combined = quote! {
|
||||||
// use crate::ast::node::*;
|
use crate::ast::node::*;
|
||||||
// #(#impls)*
|
#(#impls)*
|
||||||
// };
|
};
|
||||||
// AstGeneratedFile {
|
AstGeneratedFile {
|
||||||
// name: String::from("pretty_print.rs"),
|
name: String::from("pretty_print.rs"),
|
||||||
// contents: token_stream_to_string(combined),
|
contents: token_stream_to_string(combined),
|
||||||
// }
|
}
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_build_specs(yaml: &str) -> Vec<BuildSpec> {
|
|
||||||
deserialize_yaml_spec(yaml)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_files(build_specs: &[BuildSpec]) -> Vec<AstGeneratedFile> {
|
pub fn generate_files(build_specs: &[BuildSpec]) -> Vec<AstGeneratedFile> {
|
||||||
vec![
|
vec![
|
||||||
generate_build_file(build_specs),
|
generate_build_file(build_specs),
|
||||||
generate_node_file(build_specs),
|
generate_node_file(build_specs),
|
||||||
// generate_pretty_print_file(build_specs),
|
generate_pretty_print_file(build_specs),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
134
ast-generator/src/polymorphic_build_build_fn.rs
Normal file
134
ast-generator/src/polymorphic_build_build_fn.rs
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
use convert_case::{Case, Casing};
|
||||||
|
use crate::spec::{AlternativeAction, AlternativeBuild, AlternativeBuildChild, AlternativeChild, AlternativeTest, PolymorphicBuildBuildSpec};
|
||||||
|
use crate::util::{make_build_fn_name, make_build_pair};
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
fn make_build_child(build_child: &AlternativeBuildChild) -> TokenStream {
|
||||||
|
let rule_ident = format_ident!("{}", build_child.rule());
|
||||||
|
let child_ident = format_ident!("{}", build_child.name());
|
||||||
|
let child_build_fn_ident = format_ident!("{}", make_build_fn_name(build_child.rule()));
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
Rule::#rule_ident => {
|
||||||
|
#child_ident = Some(#child_build_fn_ident(inner_pair));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_build_action(
|
||||||
|
spec: &PolymorphicBuildBuildSpec,
|
||||||
|
alternative_build: &AlternativeBuild,
|
||||||
|
) -> TokenStream {
|
||||||
|
let enum_type_ident = format_ident!("{}", spec.return_type());
|
||||||
|
let enum_variant_ident = format_ident!("{}", alternative_build.enum_variant());
|
||||||
|
|
||||||
|
let child_holders = alternative_build
|
||||||
|
.children()
|
||||||
|
.map(|child| {
|
||||||
|
match child {
|
||||||
|
AlternativeChild::Skip => None,
|
||||||
|
AlternativeChild::Build(build_child) => {
|
||||||
|
let child_ident = format_ident!("{}", build_child.name());
|
||||||
|
let child_type_ident = format_ident!("{}", build_child.kind());
|
||||||
|
Some(quote! {
|
||||||
|
let mut #child_ident: Option<#child_type_ident> = None
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let pair_ident = format_ident!("{}", make_build_pair(spec.name()));
|
||||||
|
|
||||||
|
let rule_matchers = alternative_build
|
||||||
|
.children()
|
||||||
|
.map(|child| {
|
||||||
|
match child {
|
||||||
|
AlternativeChild::Skip => None,
|
||||||
|
AlternativeChild::Build(build_child) => {
|
||||||
|
Some(make_build_child(build_child))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let built_ident = format_ident!("{}", spec.name().to_case(Case::Snake));
|
||||||
|
let inner_type_ident = format_ident!("{}", spec.name());
|
||||||
|
let child_args = alternative_build.children()
|
||||||
|
.map(|child| {
|
||||||
|
match child {
|
||||||
|
AlternativeChild::Skip => None,
|
||||||
|
AlternativeChild::Build(child_build) => {
|
||||||
|
let child_ident = format_ident!("{}", child_build.name());
|
||||||
|
Some(quote! {
|
||||||
|
Box::new(#child_ident.unwrap())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#(#child_holders;)*
|
||||||
|
|
||||||
|
for inner_pair in #pair_ident.into_inner() {
|
||||||
|
match inner_pair.as_rule() {
|
||||||
|
#(#rule_matchers),*
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let #built_ident = #inner_type_ident::new(#(#child_args),*);
|
||||||
|
|
||||||
|
#enum_type_ident::#enum_variant_ident(#built_ident)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_polymorphic_build_build_fn(spec: &PolymorphicBuildBuildSpec) -> 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.return_type());
|
||||||
|
|
||||||
|
let alternatives = spec
|
||||||
|
.alternatives()
|
||||||
|
.map(|alternative| {
|
||||||
|
let count_to_match: usize = match alternative.test() {
|
||||||
|
AlternativeTest::NumberOfPairs(count) => count.clone().try_into().unwrap(),
|
||||||
|
};
|
||||||
|
let action = match alternative.action() {
|
||||||
|
AlternativeAction::ReturnBuild(kind) => {
|
||||||
|
let inner_build_fn_ident = format_ident!("{}", make_build_fn_name(kind));
|
||||||
|
quote! {
|
||||||
|
let inner_pair = #pair_ident.into_inner().next().unwrap();
|
||||||
|
#inner_build_fn_ident(inner_pair)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AlternativeAction::Build(alternative_build) => {
|
||||||
|
make_build_action(spec, alternative_build)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
#count_to_match => {
|
||||||
|
#action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||||
|
let count = #pair_ident.clone().into_inner().count();
|
||||||
|
match count {
|
||||||
|
#(#alternatives,)*
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,13 +1,13 @@
|
|||||||
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
use crate::spec::PolymorphicTypeBuildSpec;
|
||||||
use crate::spec::polymorphic_type_spec::PolymorphicTypeBuildSpec;
|
use crate::util::{make_build_fn_name, make_build_pair};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
pub fn make_polymorphic_type_build_fn(build_spec: &PolymorphicTypeBuildSpec) -> TokenStream {
|
pub fn make_polymorphic_build_fn(build_spec: &PolymorphicTypeBuildSpec) -> TokenStream {
|
||||||
let build_fn_ident = format_ident!("{}", make_build_fn_name(build_spec.name()));
|
let build_fn_ident = format_ident!("{}", make_build_fn_name(build_spec.name()));
|
||||||
let pair_ident = format_ident!("{}", make_build_pair(&build_spec.name()));
|
let pair_ident = format_ident!("{}", make_build_pair(&build_spec.name()));
|
||||||
let return_type_ident = format_ident!("{}", build_spec.name());
|
let return_type_ident = format_ident!("{}", build_spec.name());
|
||||||
let inner_build_fn_ident = format_ident!("{}", make_build_fn_name(build_spec.kind()));
|
let inner_build_fn_ident = format_ident!("{}", make_build_fn_name(build_spec.build_kind()));
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
|
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||||
42
ast-generator/src/polymorphic_enum_build_fn.rs
Normal file
42
ast-generator/src/polymorphic_enum_build_fn.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
use crate::spec::{PolymorphicEnumBuildSpec, PolymorphicEnumRule};
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
use crate::util::{make_build_fn_name, make_build_pair};
|
||||||
|
|
||||||
|
pub fn make_polymorphic_enum_build_fn(spec: &PolymorphicEnumBuildSpec) -> 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.return_type());
|
||||||
|
|
||||||
|
let match_arms = spec.rules()
|
||||||
|
.map(|rule| {
|
||||||
|
match rule {
|
||||||
|
PolymorphicEnumRule::Wrap(name_and_kind) => {
|
||||||
|
let rule_ident = format_ident!("{}", name_and_kind.name());
|
||||||
|
let enum_variant_ident = format_ident!("{}", name_and_kind.kind());
|
||||||
|
let rule_build_fn = format_ident!("{}", make_build_fn_name(name_and_kind.name()));
|
||||||
|
quote! {
|
||||||
|
Rule::#rule_ident => #return_type_ident::#enum_variant_ident(#rule_build_fn(inner_pair))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PolymorphicEnumRule::ReturnBuild(name_and_kind) => {
|
||||||
|
let rule_ident = format_ident!("{}", name_and_kind.name());
|
||||||
|
let rule_build_fn = format_ident!("{}", make_build_fn_name(name_and_kind.kind()));
|
||||||
|
quote! {
|
||||||
|
Rule::#rule_ident => #rule_build_fn(inner_pair)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||||
|
let inner_pair = #pair_ident.into_inner().next().unwrap();
|
||||||
|
match inner_pair.as_rule() {
|
||||||
|
#(#match_arms,)*
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,260 +1,256 @@
|
|||||||
// use crate::spec::leaf_enum_spec::LeafEnumBuildSpec;
|
use crate::spec::{
|
||||||
// use crate::spec::leaf_struct_spec::{LeafStructBuildSpec, LeafStructMemberKind};
|
AlternativeChild, BuildSpec, EnumBuildSpec, EnumRuleChildKind, LeafEnumBuildSpec,
|
||||||
// use crate::spec::polymorphic_type_spec::PolymorphicTypeBuildSpec;
|
LeafStructBuildSpec, LeafStructMemberKind, MemberChildToBuild, PolymorphicBuildBuildSpec,
|
||||||
// use crate::spec::production_spec::ProductionBuildSpec;
|
PolymorphicEnumBuildSpec, PolymorphicTypeBuildSpec, ProductionBuildSpec, StructBuildSpec,
|
||||||
// use crate::spec::struct_spec::StructSpec;
|
StructChildSpec, VecChildToBuild,
|
||||||
// use crate::spec::tree_enum_spec::{EnumRuleChildKind, TreeEnumBuildSpec};
|
};
|
||||||
// use crate::spec::{
|
use convert_case::{Case, Casing};
|
||||||
// AlternativeChild, BuildSpec, MemberChildToBuild, PolymorphicBuildBuildSpec,
|
use proc_macro2::TokenStream;
|
||||||
// PolymorphicEnumBuildSpec, StructChildSpec, VecChildToBuild,
|
use quote::{format_ident, quote};
|
||||||
// };
|
|
||||||
// use convert_case::{Case, Casing};
|
fn make_production_p2_impl(_spec: &ProductionBuildSpec) -> TokenStream {
|
||||||
// use proc_macro2::TokenStream;
|
quote! {}
|
||||||
// use quote::{format_ident, quote};
|
}
|
||||||
//
|
|
||||||
// fn make_production_p2_impl(_spec: &ProductionBuildSpec) -> TokenStream {
|
fn make_polymorphic_enum_p2_impl(_spec: &PolymorphicEnumBuildSpec) -> TokenStream {
|
||||||
// quote! {}
|
quote! {}
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// fn make_polymorphic_enum_p2_impl(_spec: &PolymorphicEnumBuildSpec) -> TokenStream {
|
fn make_polymorphic_build_p2_impl(spec: &PolymorphicBuildBuildSpec) -> TokenStream {
|
||||||
// quote! {}
|
let (_, build) = spec.primary_alternative();
|
||||||
// }
|
let type_ident = format_ident!("{}", spec.name());
|
||||||
//
|
let name_str = spec.name();
|
||||||
// fn make_polymorphic_build_p2_impl(spec: &PolymorphicBuildBuildSpec) -> TokenStream {
|
|
||||||
// let (_, build) = spec.primary_alternative();
|
let child_statements = build
|
||||||
// let type_ident = format_ident!("{}", spec.name());
|
.children()
|
||||||
// let name_str = spec.name();
|
.map(|child| match child {
|
||||||
//
|
AlternativeChild::Skip => None,
|
||||||
// let child_statements = build
|
AlternativeChild::Build(build) => {
|
||||||
// .children()
|
let child_ident = format_ident!("{}", build.name());
|
||||||
// .map(|child| match child {
|
Some(quote! {
|
||||||
// AlternativeChild::Skip => None,
|
self.#child_ident().pretty_print(writer)?
|
||||||
// AlternativeChild::Build(build) => {
|
})
|
||||||
// let child_ident = format_ident!("{}", build.name());
|
}
|
||||||
// Some(quote! {
|
})
|
||||||
// self.#child_ident().pretty_print(writer)?
|
.filter(Option::is_some)
|
||||||
// })
|
.map(Option::unwrap)
|
||||||
// }
|
.collect::<Vec<TokenStream>>();
|
||||||
// })
|
|
||||||
// .filter(Option::is_some)
|
quote! {
|
||||||
// .map(Option::unwrap)
|
impl PrettyPrint for #type_ident {
|
||||||
// .collect::<Vec<TokenStream>>();
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||||
//
|
writer.writeln_indented(#name_str);
|
||||||
// quote! {
|
writer.increase_indent();
|
||||||
// impl PrettyPrint for #type_ident {
|
#(#child_statements;)*
|
||||||
// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
writer.decrease_indent();
|
||||||
// writer.writeln_indented(#name_str);
|
Ok(())
|
||||||
// writer.increase_indent();
|
}
|
||||||
// #(#child_statements;)*
|
}
|
||||||
// writer.decrease_indent();
|
}
|
||||||
// Ok(())
|
}
|
||||||
// }
|
|
||||||
// }
|
fn make_polymorphic_type_p2_impl(spec: &PolymorphicTypeBuildSpec) -> TokenStream {
|
||||||
// }
|
let type_ident = format_ident!("{}", spec.name());
|
||||||
// }
|
let child_matchers = spec
|
||||||
//
|
.enum_members()
|
||||||
// fn make_polymorphic_type_p2_impl(spec: &PolymorphicTypeBuildSpec) -> TokenStream {
|
.map(|member| {
|
||||||
// let type_ident = format_ident!("{}", spec.name());
|
let enum_member_ident = format_ident!("{}", member.name());
|
||||||
// let child_matchers = spec
|
let inner_name = format_ident!("{}", member.inner_kind().to_case(Case::Snake));
|
||||||
// .variants()
|
quote! {
|
||||||
// .map(|member| {
|
#type_ident::#enum_member_ident(#inner_name) => #inner_name.pretty_print(writer)
|
||||||
// let enum_member_ident = format_ident!("{}", member.name());
|
}
|
||||||
// let inner_name = format_ident!("{}", member.inner_kind().to_case(Case::Snake));
|
})
|
||||||
// quote! {
|
.collect::<Vec<_>>();
|
||||||
// #type_ident::#enum_member_ident(#inner_name) => #inner_name.pretty_print(writer)
|
|
||||||
// }
|
quote! {
|
||||||
// })
|
impl PrettyPrint for #type_ident {
|
||||||
// .collect::<Vec<_>>();
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||||
//
|
match self {
|
||||||
// quote! {
|
#(#child_matchers,)*
|
||||||
// impl PrettyPrint for #type_ident {
|
}
|
||||||
// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
}
|
||||||
// match self {
|
}
|
||||||
// #(#child_matchers,)*
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
// }
|
fn make_leaf_enum_p2_impl(spec: &LeafEnumBuildSpec) -> TokenStream {
|
||||||
// }
|
let type_ident = format_ident!("{}", spec.build());
|
||||||
// }
|
let child_matchers = spec
|
||||||
//
|
.rules()
|
||||||
// fn make_leaf_enum_p2_impl(spec: &LeafEnumBuildSpec) -> TokenStream {
|
.map(|rule| {
|
||||||
// let type_ident = format_ident!("{}", spec.build());
|
let enum_variant_ident = format_ident!("{}", rule.rule());
|
||||||
// let child_matchers = spec
|
let name_str = rule.rule();
|
||||||
// .rules()
|
quote! {
|
||||||
// .map(|rule| {
|
#type_ident::#enum_variant_ident => writer.writeln_indented(#name_str)
|
||||||
// let enum_variant_ident = format_ident!("{}", rule.rule());
|
}
|
||||||
// let name_str = rule.rule();
|
})
|
||||||
// quote! {
|
.collect::<Vec<_>>();
|
||||||
// #type_ident::#enum_variant_ident => writer.writeln_indented(#name_str)
|
|
||||||
// }
|
quote! {
|
||||||
// })
|
impl PrettyPrint for #type_ident {
|
||||||
// .collect::<Vec<_>>();
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||||
//
|
match self {
|
||||||
// quote! {
|
#(#child_matchers,)*
|
||||||
// impl PrettyPrint for #type_ident {
|
}
|
||||||
// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
}
|
||||||
// match self {
|
}
|
||||||
// #(#child_matchers,)*
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
// }
|
fn make_enum_p2_impl(spec: &EnumBuildSpec) -> TokenStream {
|
||||||
// }
|
let type_ident = format_ident!("{}", spec.build());
|
||||||
// }
|
let type_str = spec.build();
|
||||||
//
|
|
||||||
// fn make_enum_p2_impl(spec: &TreeEnumBuildSpec) -> TokenStream {
|
let child_matchers = spec
|
||||||
// let type_ident = format_ident!("{}", spec.build());
|
.rules()
|
||||||
// let type_str = spec.build();
|
.map(|rule| {
|
||||||
//
|
let enum_variant_ident = format_ident!("{}", rule.rule());
|
||||||
// let child_matchers = spec
|
if let Some(child) = rule.child() {
|
||||||
// .rules()
|
match child.kind() {
|
||||||
// .map(|rule| {
|
EnumRuleChildKind::Node(node_child) => {
|
||||||
// let enum_variant_ident = format_ident!("{}", rule.rule());
|
let child_name_ident =
|
||||||
// if let Some(child) = rule.child() {
|
format_ident!("{}", node_child.build().to_case(Case::Snake));
|
||||||
// match child.kind() {
|
Some(quote! {
|
||||||
// EnumRuleChildKind::Node(node_child) => {
|
#type_ident::#enum_variant_ident(#child_name_ident) => {
|
||||||
// let child_name_ident =
|
#child_name_ident.pretty_print(writer)?;
|
||||||
// format_ident!("{}", node_child.build().to_case(Case::Snake));
|
}
|
||||||
// Some(quote! {
|
})
|
||||||
// #type_ident::#enum_variant_ident(#child_name_ident) => {
|
}
|
||||||
// #child_name_ident.pretty_print(writer)?;
|
_ => None,
|
||||||
// }
|
}
|
||||||
// })
|
} else {
|
||||||
// }
|
let variant_str = rule.rule();
|
||||||
// _ => None,
|
Some(quote! {
|
||||||
// }
|
#type_ident::#enum_variant_ident => writer.writeln_indented(#variant_str)?
|
||||||
// } else {
|
})
|
||||||
// let variant_str = rule.rule();
|
}
|
||||||
// Some(quote! {
|
})
|
||||||
// #type_ident::#enum_variant_ident => writer.writeln_indented(#variant_str)?
|
.filter(Option::is_some)
|
||||||
// })
|
.map(Option::unwrap)
|
||||||
// }
|
.collect::<Vec<_>>();
|
||||||
// })
|
|
||||||
// .filter(Option::is_some)
|
quote! {
|
||||||
// .map(Option::unwrap)
|
impl PrettyPrint for #type_ident {
|
||||||
// .collect::<Vec<_>>();
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||||
//
|
writer.writeln_indented(#type_str)?;
|
||||||
// quote! {
|
writer.increase_indent();
|
||||||
// impl PrettyPrint for #type_ident {
|
match self {
|
||||||
// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
#(#child_matchers,)*
|
||||||
// writer.writeln_indented(#type_str)?;
|
_ => {}
|
||||||
// writer.increase_indent();
|
}
|
||||||
// match self {
|
writer.decrease_indent();
|
||||||
// #(#child_matchers,)*
|
Ok(())
|
||||||
// _ => {}
|
}
|
||||||
// }
|
}
|
||||||
// writer.decrease_indent();
|
}
|
||||||
// Ok(())
|
}
|
||||||
// }
|
|
||||||
// }
|
fn make_leaf_struct_p2_impl(leaf_struct_build_spec: &LeafStructBuildSpec) -> TokenStream {
|
||||||
// }
|
let type_ident = format_ident!("{}", leaf_struct_build_spec.build());
|
||||||
// }
|
let member_formatters = leaf_struct_build_spec
|
||||||
//
|
.members()
|
||||||
// fn make_leaf_struct_p2_impl(leaf_struct_build_spec: &LeafStructBuildSpec) -> TokenStream {
|
.map(|member| match member.kind() {
|
||||||
// let type_ident = format_ident!("{}", leaf_struct_build_spec.build());
|
LeafStructMemberKind::String => Some("{}"),
|
||||||
// let member_formatters = leaf_struct_build_spec
|
})
|
||||||
// .members()
|
.filter(Option::is_some)
|
||||||
// .map(|member| match member.kind() {
|
.map(Option::unwrap)
|
||||||
// LeafStructMemberKind::String => Some("{}"),
|
.collect::<Vec<_>>()
|
||||||
// })
|
.join(", ");
|
||||||
// .filter(Option::is_some)
|
|
||||||
// .map(Option::unwrap)
|
let format_string = format!("{}({})", leaf_struct_build_spec.build(), member_formatters);
|
||||||
// .collect::<Vec<_>>()
|
|
||||||
// .join(", ");
|
let members = leaf_struct_build_spec
|
||||||
//
|
.members()
|
||||||
// let format_string = format!("{}({})", leaf_struct_build_spec.build(), member_formatters);
|
.map(|member| {
|
||||||
//
|
let member_ident = format_ident!("{}", member.name());
|
||||||
// let members = leaf_struct_build_spec
|
quote! {
|
||||||
// .members()
|
self.#member_ident()
|
||||||
// .map(|member| {
|
}
|
||||||
// let member_ident = format_ident!("{}", member.name());
|
})
|
||||||
// quote! {
|
.collect::<Vec<_>>();
|
||||||
// self.#member_ident()
|
|
||||||
// }
|
quote! {
|
||||||
// })
|
impl PrettyPrint for #type_ident {
|
||||||
// .collect::<Vec<_>>();
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||||
//
|
writer.writeln_indented(&format!(#format_string, #(#members),*))
|
||||||
// quote! {
|
}
|
||||||
// impl PrettyPrint for #type_ident {
|
}
|
||||||
// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
}
|
||||||
// writer.writeln_indented(&format!(#format_string, #(#members),*))
|
}
|
||||||
// }
|
|
||||||
// }
|
fn make_struct_p2_impl(struct_build_spec: &StructBuildSpec) -> TokenStream {
|
||||||
// }
|
let child_print_statements = struct_build_spec
|
||||||
// }
|
.children()
|
||||||
//
|
.map(|child| match child {
|
||||||
// fn make_struct_p2_impl(struct_build_spec: &StructSpec) -> TokenStream {
|
StructChildSpec::SkipChild(_) => None,
|
||||||
// let child_print_statements = struct_build_spec
|
StructChildSpec::VecChild(vec_child) => match vec_child.build() {
|
||||||
// .children()
|
VecChildToBuild::Node(_) => {
|
||||||
// .map(|child| match child {
|
let child_ident = format_ident!("{}", vec_child.name());
|
||||||
// StructChildSpec::SkipChild(_) => None,
|
Some(quote! {
|
||||||
// StructChildSpec::VecChild(vec_child) => match vec_child.build() {
|
for child in self.#child_ident() {
|
||||||
// VecChildToBuild::Node(_) => {
|
child.pretty_print(writer)?;
|
||||||
// let child_ident = format_ident!("{}", vec_child.name());
|
}
|
||||||
// Some(quote! {
|
})
|
||||||
// for child in self.#child_ident() {
|
}
|
||||||
// child.pretty_print(writer)?;
|
VecChildToBuild::String => None,
|
||||||
// }
|
},
|
||||||
// })
|
StructChildSpec::MemberChild(member_child) => match member_child.build() {
|
||||||
// }
|
MemberChildToBuild::Node(node_member_child) => {
|
||||||
// VecChildToBuild::String => None,
|
let child_ident = format_ident!("{}", member_child.name());
|
||||||
// },
|
if node_member_child.optional() {
|
||||||
// StructChildSpec::MemberChild(member_child) => match member_child.build() {
|
Some(quote! {
|
||||||
// MemberChildToBuild::Node(node_member_child) => {
|
if let Some(child) = self.#child_ident() {
|
||||||
// let child_ident = format_ident!("{}", member_child.name());
|
child.pretty_print(writer)?;
|
||||||
// if node_member_child.optional() {
|
}
|
||||||
// Some(quote! {
|
})
|
||||||
// if let Some(child) = self.#child_ident() {
|
} else {
|
||||||
// child.pretty_print(writer)?;
|
Some(quote! {
|
||||||
// }
|
self.#child_ident().pretty_print(writer)?;
|
||||||
// })
|
})
|
||||||
// } else {
|
}
|
||||||
// Some(quote! {
|
}
|
||||||
// self.#child_ident().pretty_print(writer)?;
|
MemberChildToBuild::Boolean(boolean_member_child) => {
|
||||||
// })
|
let format_string = format!("{}({})", boolean_member_child.name(), "{}");
|
||||||
// }
|
let child_ident = format_ident!("{}", boolean_member_child.name());
|
||||||
// }
|
Some(quote! {
|
||||||
// MemberChildToBuild::Boolean(boolean_member_child) => {
|
writer.writeln_indented(&format!(#format_string, self.#child_ident()))?;
|
||||||
// let format_string = format!("{}({})", boolean_member_child.name(), "{}");
|
})
|
||||||
// let child_ident = format_ident!("{}", boolean_member_child.name());
|
}
|
||||||
// Some(quote! {
|
},
|
||||||
// writer.writeln_indented(&format!(#format_string, self.#child_ident()))?;
|
})
|
||||||
// })
|
.filter(Option::is_some)
|
||||||
// }
|
.map(Option::unwrap)
|
||||||
// },
|
.collect::<Vec<_>>();
|
||||||
// })
|
|
||||||
// .filter(Option::is_some)
|
let type_ident = format_ident!("{}", struct_build_spec.build());
|
||||||
// .map(Option::unwrap)
|
let type_string = struct_build_spec.build();
|
||||||
// .collect::<Vec<_>>();
|
|
||||||
//
|
quote! {
|
||||||
// let type_ident = format_ident!("{}", struct_build_spec.build());
|
impl PrettyPrint for #type_ident {
|
||||||
// let type_string = struct_build_spec.build();
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||||
//
|
writer.writeln_indented(#type_string)?;
|
||||||
// quote! {
|
writer.increase_indent();
|
||||||
// impl PrettyPrint for #type_ident {
|
#(#child_print_statements)*
|
||||||
// fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
writer.decrease_indent();
|
||||||
// writer.writeln_indented(#type_string)?;
|
Ok(())
|
||||||
// writer.increase_indent();
|
}
|
||||||
// #(#child_print_statements)*
|
}
|
||||||
// writer.decrease_indent();
|
}
|
||||||
// Ok(())
|
}
|
||||||
// }
|
|
||||||
// }
|
pub fn make_pretty_print_impl(build_spec: &BuildSpec) -> TokenStream {
|
||||||
// }
|
match build_spec {
|
||||||
// }
|
BuildSpec::Struct(struct_spec) => make_struct_p2_impl(struct_spec),
|
||||||
//
|
BuildSpec::LeafStruct(leaf_struct) => make_leaf_struct_p2_impl(leaf_struct),
|
||||||
// pub fn make_pretty_print_impl(build_spec: &BuildSpec) -> TokenStream {
|
BuildSpec::Enum(enum_spec) => make_enum_p2_impl(enum_spec),
|
||||||
// match build_spec {
|
BuildSpec::LeafEnum(leaf_enum) => make_leaf_enum_p2_impl(leaf_enum),
|
||||||
// BuildSpec::Struct(struct_spec) => make_struct_p2_impl(struct_spec),
|
BuildSpec::Polymorphic(polymorphic) => make_polymorphic_type_p2_impl(polymorphic),
|
||||||
// BuildSpec::LeafStruct(leaf_struct) => make_leaf_struct_p2_impl(leaf_struct),
|
BuildSpec::PolymorphicBuild(polymorphic_build) => {
|
||||||
// BuildSpec::Enum(enum_spec) => make_enum_p2_impl(enum_spec),
|
make_polymorphic_build_p2_impl(polymorphic_build)
|
||||||
// BuildSpec::LeafEnum(leaf_enum) => make_leaf_enum_p2_impl(leaf_enum),
|
}
|
||||||
// BuildSpec::PolymorphicType(polymorphic) => make_polymorphic_type_p2_impl(polymorphic),
|
BuildSpec::PolymorphicEnum(polymorphic_enum) => {
|
||||||
// BuildSpec::PolymorphicBuild(polymorphic_build) => {
|
make_polymorphic_enum_p2_impl(polymorphic_enum)
|
||||||
// make_polymorphic_build_p2_impl(polymorphic_build)
|
}
|
||||||
// }
|
BuildSpec::Production(production) => make_production_p2_impl(production),
|
||||||
// BuildSpec::PolymorphicEnum(polymorphic_enum) => {
|
}
|
||||||
// make_polymorphic_enum_p2_impl(polymorphic_enum)
|
}
|
||||||
// }
|
|
||||||
// BuildSpec::Production(production) => make_production_p2_impl(production),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|||||||
@ -1,18 +1,19 @@
|
|||||||
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
use crate::spec::{ProductionBuildSpec, ProductionKind, ProductionStringFrom};
|
||||||
use crate::spec::production_spec::{ProductionBuildSpec, ProductionKind, ProductionStringFrom};
|
use crate::util::{make_build_fn_name, make_build_pair};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
pub fn make_production_build_fn(production_build_spec: &ProductionBuildSpec) -> TokenStream {
|
pub fn make_production_build_fn(production_build_spec: &ProductionBuildSpec) -> TokenStream {
|
||||||
let build_fn_ident = format_ident!("{}", make_build_fn_name(production_build_spec.name()));
|
let build_fn_ident = format_ident!("{}", make_build_fn_name(production_build_spec.rule()));
|
||||||
let return_type_ident = match production_build_spec.kind() {
|
let return_type_ident = match production_build_spec.kind() {
|
||||||
ProductionKind::Int => format_ident!("i32"),
|
ProductionKind::Int => format_ident!("i32"),
|
||||||
ProductionKind::Long => format_ident!("i64"),
|
ProductionKind::Long => format_ident!("i64"),
|
||||||
ProductionKind::Double => format_ident!("f64"),
|
ProductionKind::Double => format_ident!("f64"),
|
||||||
ProductionKind::String(_) => format_ident!("String"),
|
ProductionKind::String(_) => format_ident!("String"),
|
||||||
ProductionKind::Boolean(_) => format_ident!("bool"),
|
ProductionKind::Boolean => format_ident!("bool"),
|
||||||
|
ProductionKind::Node(node_type) => format_ident!("{}", node_type),
|
||||||
};
|
};
|
||||||
let pair_ident = format_ident!("{}", make_build_pair(production_build_spec.name()));
|
let pair_ident = format_ident!("{}", make_build_pair(production_build_spec.rule()));
|
||||||
|
|
||||||
let pair_mapper = match production_build_spec.kind() {
|
let pair_mapper = match production_build_spec.kind() {
|
||||||
ProductionKind::Int => quote! {
|
ProductionKind::Int => quote! {
|
||||||
@ -74,9 +75,16 @@ pub fn make_production_build_fn(production_build_spec: &ProductionBuildSpec) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ProductionKind::Boolean(_) => quote! {
|
ProductionKind::Boolean => quote! {
|
||||||
#pair_ident.as_str().parse::<bool>().unwrap()
|
#pair_ident.as_str().parse::<bool>().unwrap()
|
||||||
},
|
},
|
||||||
|
ProductionKind::Node(node_type) => {
|
||||||
|
let build_fn_ident = format_ident!("{}", make_build_fn_name(node_type));
|
||||||
|
quote! {
|
||||||
|
let inner_pair = #pair_ident.into_inner().next().unwrap();
|
||||||
|
#build_fn_ident(inner_pair)
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
672
ast-generator/src/spec.rs
Normal file
672
ast-generator/src/spec.rs
Normal file
@ -0,0 +1,672 @@
|
|||||||
|
pub enum BuildSpec {
|
||||||
|
Enum(EnumBuildSpec),
|
||||||
|
LeafEnum(LeafEnumBuildSpec),
|
||||||
|
Struct(StructBuildSpec),
|
||||||
|
LeafStruct(LeafStructBuildSpec),
|
||||||
|
Production(ProductionBuildSpec),
|
||||||
|
Polymorphic(PolymorphicTypeBuildSpec),
|
||||||
|
PolymorphicBuild(PolymorphicBuildBuildSpec),
|
||||||
|
PolymorphicEnum(PolymorphicEnumBuildSpec),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enum build spec
|
||||||
|
|
||||||
|
pub struct EnumBuildSpec {
|
||||||
|
build: String,
|
||||||
|
rules: Vec<Box<EnumRule>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnumBuildSpec {
|
||||||
|
pub fn new(build: &str, rules: Vec<Box<EnumRule>>) -> Self {
|
||||||
|
EnumBuildSpec {
|
||||||
|
build: build.to_string(),
|
||||||
|
rules,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The enum type to be built, in Pascal case.
|
||||||
|
pub fn build(&self) -> &str {
|
||||||
|
&self.build
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The individual rule specs.
|
||||||
|
pub fn rules(&self) -> impl Iterator<Item = &EnumRule> {
|
||||||
|
self.rules.iter().map(Box::as_ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EnumRule {
|
||||||
|
rule: String,
|
||||||
|
child: Option<Box<EnumRuleChild>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnumRule {
|
||||||
|
pub fn new(rule: &str, child: Option<Box<EnumRuleChild>>) -> Self {
|
||||||
|
Self {
|
||||||
|
rule: rule.to_string(),
|
||||||
|
child,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The enum rule to match, in Pascal case.
|
||||||
|
pub fn rule(&self) -> &str {
|
||||||
|
&self.rule
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn child(&self) -> Option<&EnumRuleChild> {
|
||||||
|
if let Some(child) = &self.child {
|
||||||
|
Some(child.as_ref())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EnumRuleChild {
|
||||||
|
kind: Box<EnumRuleChildKind>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnumRuleChild {
|
||||||
|
pub fn new(kind: Box<EnumRuleChildKind>) -> Self {
|
||||||
|
Self { kind }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind(&self) -> &EnumRuleChildKind {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum EnumRuleChildKind {
|
||||||
|
Node(EnumRuleNodeChild),
|
||||||
|
Int,
|
||||||
|
Long,
|
||||||
|
Double,
|
||||||
|
USize,
|
||||||
|
String,
|
||||||
|
Boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EnumRuleNodeChild {
|
||||||
|
build: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnumRuleNodeChild {
|
||||||
|
pub fn new(build: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
build: build.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(&self) -> &str {
|
||||||
|
&self.build
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leaf enum build spec
|
||||||
|
|
||||||
|
pub struct LeafEnumBuildSpec {
|
||||||
|
build: String,
|
||||||
|
rules: Vec<Box<LeafEnumRule>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LeafEnumBuildSpec {
|
||||||
|
pub fn new(build: &str, rules: Vec<Box<LeafEnumRule>>) -> Self {
|
||||||
|
Self {
|
||||||
|
build: build.to_string(),
|
||||||
|
rules,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(&self) -> &str {
|
||||||
|
&self.build
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rules(&self) -> impl Iterator<Item = &LeafEnumRule> {
|
||||||
|
self.rules.iter().map(Box::as_ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LeafEnumRule {
|
||||||
|
rule: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LeafEnumRule {
|
||||||
|
pub fn new(rule: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
rule: rule.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rule(&self) -> &str {
|
||||||
|
&self.rule
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Struct build spec
|
||||||
|
|
||||||
|
pub struct StructBuildSpec {
|
||||||
|
build: String,
|
||||||
|
children: Vec<Box<StructChildSpec>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StructBuildSpec {
|
||||||
|
pub fn new(build: &str, children: Vec<Box<StructChildSpec>>) -> Self {
|
||||||
|
Self {
|
||||||
|
build: build.to_string(),
|
||||||
|
children,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The type to be built, in Pascal case.
|
||||||
|
pub fn build(&self) -> &str {
|
||||||
|
&self.build
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The children for this build spec.
|
||||||
|
pub fn children(&self) -> impl Iterator<Item = &StructChildSpec> {
|
||||||
|
self.children.iter().map(Box::as_ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum StructChildSpec {
|
||||||
|
SkipChild(SkipChild),
|
||||||
|
VecChild(VecChild),
|
||||||
|
MemberChild(MemberChild),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SkipChild {
|
||||||
|
name: String,
|
||||||
|
rule: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SkipChild {
|
||||||
|
pub fn new(name: &str, rule: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
rule: rule.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The name of this child spec.
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The grammar rule to match.
|
||||||
|
pub fn rule(&self) -> &str {
|
||||||
|
&self.rule
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct VecChild {
|
||||||
|
name: String,
|
||||||
|
rule: String,
|
||||||
|
build: Box<VecChildToBuild>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VecChild {
|
||||||
|
pub fn new(name: &str, rule: &str, build: Box<VecChildToBuild>) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
rule: rule.to_string(),
|
||||||
|
build,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The name of this child.
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The rule to match to build this child.
|
||||||
|
pub fn rule(&self) -> &str {
|
||||||
|
&self.rule
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The build info for this child.
|
||||||
|
pub fn build(&self) -> &VecChildToBuild {
|
||||||
|
&self.build
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum VecChildToBuild {
|
||||||
|
Node(VecNodeChildToBuild),
|
||||||
|
String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct VecNodeChildToBuild {
|
||||||
|
build: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VecNodeChildToBuild {
|
||||||
|
pub fn new(build: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
build: build.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The type to build, in Pascal case.
|
||||||
|
pub fn build(&self) -> &str {
|
||||||
|
&self.build
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct MemberChild {
|
||||||
|
name: String,
|
||||||
|
rule: String,
|
||||||
|
build: Box<MemberChildToBuild>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemberChild {
|
||||||
|
pub fn new(name: &str, rule: &str, build: Box<MemberChildToBuild>) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
rule: rule.to_string(),
|
||||||
|
build,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The name of this child in the yaml file, in snake case.
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The grammar rule to match to build this child.
|
||||||
|
pub fn rule(&self) -> &str {
|
||||||
|
&self.rule
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The specification for what to actually build.
|
||||||
|
pub fn build(&self) -> &MemberChildToBuild {
|
||||||
|
&self.build
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum MemberChildToBuild {
|
||||||
|
Node(NodeChildToBuild),
|
||||||
|
Boolean(BooleanChildToBuild),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NodeChildToBuild {
|
||||||
|
build: String,
|
||||||
|
or_else: Option<String>,
|
||||||
|
optional: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NodeChildToBuild {
|
||||||
|
pub fn new(build: &str, or_else: Option<String>, optional: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
build: build.to_string(),
|
||||||
|
or_else,
|
||||||
|
optional,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The type to build, in Pascal case.
|
||||||
|
pub fn build(&self) -> &str {
|
||||||
|
&self.build
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The default fn to call when unwrapping the child (before passing as arg to new).
|
||||||
|
pub fn or_else(&self) -> Option<&str> {
|
||||||
|
self.or_else.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If the type should be wrapped in an Option.
|
||||||
|
pub fn optional(&self) -> bool {
|
||||||
|
self.optional
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BooleanChildToBuild {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BooleanChildToBuild {
|
||||||
|
pub fn new(name: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leaf Struct build spec
|
||||||
|
|
||||||
|
pub struct LeafStructBuildSpec {
|
||||||
|
build: String,
|
||||||
|
members: Vec<Box<LeafStructMember>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LeafStructBuildSpec {
|
||||||
|
pub fn new(build: &str, members: Vec<Box<LeafStructMember>>) -> Self {
|
||||||
|
Self {
|
||||||
|
build: build.to_string(),
|
||||||
|
members,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(&self) -> &str {
|
||||||
|
&self.build
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn members(&self) -> impl Iterator<Item = &LeafStructMember> {
|
||||||
|
self.members.iter().map(Box::as_ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LeafStructMember {
|
||||||
|
name: String,
|
||||||
|
kind: LeafStructMemberKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LeafStructMember {
|
||||||
|
pub fn new(name: &str, kind: LeafStructMemberKind) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
kind,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind(&self) -> &LeafStructMemberKind {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum LeafStructMemberKind {
|
||||||
|
String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ProductionBuildSpec {
|
||||||
|
rule: String,
|
||||||
|
kind: ProductionKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProductionBuildSpec {
|
||||||
|
pub fn new(rule: &str, kind: ProductionKind) -> Self {
|
||||||
|
Self {
|
||||||
|
rule: rule.to_string(),
|
||||||
|
kind,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rule(&self) -> &str {
|
||||||
|
&self.rule
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind(&self) -> &ProductionKind {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ProductionKind {
|
||||||
|
Int,
|
||||||
|
Long,
|
||||||
|
Double,
|
||||||
|
String(ProductionStringFrom),
|
||||||
|
Boolean,
|
||||||
|
Node(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ProductionStringFrom {
|
||||||
|
StringInner,
|
||||||
|
WholePair,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Polymorphic build spec
|
||||||
|
|
||||||
|
pub struct PolymorphicTypeBuildSpec {
|
||||||
|
name: String,
|
||||||
|
enum_members: Vec<Box<PolymorphicEnumMember>>,
|
||||||
|
build_kind: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PolymorphicTypeBuildSpec {
|
||||||
|
pub fn new(
|
||||||
|
name: &str,
|
||||||
|
enum_members: Vec<Box<PolymorphicEnumMember>>,
|
||||||
|
build_kind: &str,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
enum_members,
|
||||||
|
build_kind: build_kind.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enum_members(&self) -> impl Iterator<Item = &PolymorphicEnumMember> {
|
||||||
|
self.enum_members.iter().map(Box::as_ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_kind(&self) -> &str {
|
||||||
|
self.build_kind.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PolymorphicEnumMember {
|
||||||
|
name: String,
|
||||||
|
inner_kind: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PolymorphicEnumMember {
|
||||||
|
pub fn new(name: &str, inner_kind: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
inner_kind: inner_kind.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inner_kind(&self) -> &str {
|
||||||
|
&self.inner_kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PolymorphicBuildBuildSpec {
|
||||||
|
name: String,
|
||||||
|
return_type: String,
|
||||||
|
alternatives: Vec<Box<PolymorphicBuildAlternative>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PolymorphicBuildBuildSpec {
|
||||||
|
pub fn new(
|
||||||
|
name: &str,
|
||||||
|
return_type: &str,
|
||||||
|
alternatives: Vec<Box<PolymorphicBuildAlternative>>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
return_type: return_type.to_string(),
|
||||||
|
alternatives,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn return_type(&self) -> &str {
|
||||||
|
&self.return_type
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn alternatives(&self) -> impl Iterator<Item = &PolymorphicBuildAlternative> {
|
||||||
|
self.alternatives.iter().map(Box::as_ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn primary_alternative(&self) -> (&AlternativeTest, &AlternativeBuild) {
|
||||||
|
let primary_build_alternative = self
|
||||||
|
.alternatives
|
||||||
|
.iter()
|
||||||
|
.find(|alternative| match alternative.action {
|
||||||
|
AlternativeAction::Build(_) => true,
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
.map(Box::as_ref)
|
||||||
|
.unwrap();
|
||||||
|
let alternative_build =
|
||||||
|
if let AlternativeAction::Build(build) = &primary_build_alternative.action {
|
||||||
|
build
|
||||||
|
} else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
(primary_build_alternative.test(), alternative_build)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PolymorphicBuildAlternative {
|
||||||
|
test: AlternativeTest,
|
||||||
|
action: AlternativeAction,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PolymorphicBuildAlternative {
|
||||||
|
pub fn new(test: AlternativeTest, action: AlternativeAction) -> Self {
|
||||||
|
Self { test, action }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn test(&self) -> &AlternativeTest {
|
||||||
|
&self.test
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn action(&self) -> &AlternativeAction {
|
||||||
|
&self.action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum AlternativeTest {
|
||||||
|
NumberOfPairs(i64),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum AlternativeAction {
|
||||||
|
ReturnBuild(String),
|
||||||
|
Build(AlternativeBuild),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AlternativeBuild {
|
||||||
|
enum_variant: String,
|
||||||
|
children: Vec<Box<AlternativeChild>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AlternativeBuild {
|
||||||
|
pub fn new(enum_variant: &str, children: Vec<Box<AlternativeChild>>) -> Self {
|
||||||
|
Self {
|
||||||
|
enum_variant: enum_variant.to_string(),
|
||||||
|
children,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enum_variant(&self) -> &str {
|
||||||
|
&self.enum_variant
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn children(&self) -> impl Iterator<Item = &AlternativeChild> {
|
||||||
|
self.children.iter().map(Box::as_ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum AlternativeChild {
|
||||||
|
Skip,
|
||||||
|
Build(AlternativeBuildChild),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AlternativeBuildChild {
|
||||||
|
name: String,
|
||||||
|
kind: String,
|
||||||
|
rule: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AlternativeBuildChild {
|
||||||
|
pub fn new(name: &str, kind: &str, rule: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
kind: kind.to_string(),
|
||||||
|
rule: rule.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind(&self) -> &str {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rule(&self) -> &str {
|
||||||
|
&self.rule
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PolymorphicEnumBuildSpec {
|
||||||
|
name: String,
|
||||||
|
return_type: String,
|
||||||
|
rules: Vec<Box<PolymorphicEnumRule>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PolymorphicEnumBuildSpec {
|
||||||
|
pub fn new(name: &str, return_type: &str, rules: Vec<Box<PolymorphicEnumRule>>) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
return_type: return_type.to_string(),
|
||||||
|
rules,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn return_type(&self) -> &str {
|
||||||
|
&self.return_type
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rules(&self) -> impl Iterator<Item = &PolymorphicEnumRule> {
|
||||||
|
self.rules.iter().map(Box::as_ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum PolymorphicEnumRule {
|
||||||
|
Wrap(NameAndKind),
|
||||||
|
ReturnBuild(NameAndKind),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NameAndKind {
|
||||||
|
name: String,
|
||||||
|
kind: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NameAndKind {
|
||||||
|
pub fn new(name: &str, kind: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
kind: kind.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind(&self) -> &str {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,21 +0,0 @@
|
|||||||
pub struct LeafEnumBuildSpec {
|
|
||||||
build: String,
|
|
||||||
rules: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LeafEnumBuildSpec {
|
|
||||||
pub fn new(build: &str, rules: Vec<String>) -> Self {
|
|
||||||
Self {
|
|
||||||
build: build.to_string(),
|
|
||||||
rules,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build(&self) -> &str {
|
|
||||||
&self.build
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rules(&self) -> impl Iterator<Item = &str> {
|
|
||||||
self.rules.iter().map(AsRef::as_ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
pub struct LeafStructBuildSpec {
|
|
||||||
build: String,
|
|
||||||
members: Vec<Box<LeafStructMember>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LeafStructBuildSpec {
|
|
||||||
pub fn new(build: &str, members: Vec<Box<LeafStructMember>>) -> Self {
|
|
||||||
Self {
|
|
||||||
build: build.to_string(),
|
|
||||||
members,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build(&self) -> &str {
|
|
||||||
&self.build
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn members(&self) -> impl Iterator<Item = &LeafStructMember> {
|
|
||||||
self.members.iter().map(Box::as_ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LeafStructMember {
|
|
||||||
name: String,
|
|
||||||
kind: LeafStructMemberKind,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LeafStructMember {
|
|
||||||
pub fn new(name: &str, kind: LeafStructMemberKind) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
kind,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> &LeafStructMemberKind {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum LeafStructMemberKind {
|
|
||||||
String,
|
|
||||||
}
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
use crate::spec::node_production_spec::NodeProductionBuildSpec;
|
|
||||||
use crate::spec::polymorphic_enum_loop_spec::PolymorphicEnumLoopBuildSpec;
|
|
||||||
use leaf_enum_spec::LeafEnumBuildSpec;
|
|
||||||
use leaf_struct_spec::LeafStructBuildSpec;
|
|
||||||
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;
|
|
||||||
|
|
||||||
pub(crate) mod leaf_enum_spec;
|
|
||||||
pub(crate) mod leaf_struct_spec;
|
|
||||||
pub(crate) mod node_production_spec;
|
|
||||||
pub(crate) mod polymorphic_enum_loop_spec;
|
|
||||||
pub(crate) mod polymorphic_pass_through_spec;
|
|
||||||
pub(crate) mod polymorphic_type_spec;
|
|
||||||
pub(crate) mod production_spec;
|
|
||||||
pub(crate) mod struct_spec;
|
|
||||||
pub(crate) mod tree_enum_spec;
|
|
||||||
|
|
||||||
pub enum BuildSpec {
|
|
||||||
Enum(TreeEnumBuildSpec),
|
|
||||||
LeafEnum(LeafEnumBuildSpec),
|
|
||||||
Struct(StructSpec),
|
|
||||||
LeafStruct(LeafStructBuildSpec),
|
|
||||||
Production(ProductionBuildSpec),
|
|
||||||
NodeProduction(NodeProductionBuildSpec),
|
|
||||||
PolymorphicType(PolymorphicTypeBuildSpec),
|
|
||||||
PolymorphicEnumLoop(PolymorphicEnumLoopBuildSpec),
|
|
||||||
PolymorphicPassThrough(PolymorphicPassThroughBuildSpec)
|
|
||||||
}
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
pub struct NodeProductionBuildSpec {
|
|
||||||
name: String,
|
|
||||||
kind: String,
|
|
||||||
with: String
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NodeProductionBuildSpec {
|
|
||||||
pub fn new(name: &str, kind: &str, with: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
kind: kind.to_string(),
|
|
||||||
with: with.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> &str {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with(&self) -> &str {
|
|
||||||
&self.with
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,137 +0,0 @@
|
|||||||
pub struct PolymorphicEnumLoopBuildSpec {
|
|
||||||
name: String,
|
|
||||||
kind: String,
|
|
||||||
rules: Vec<Box<PolymorphicEnumLoopRule>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PolymorphicEnumLoopBuildSpec {
|
|
||||||
pub fn new(name: &str, kind: &str, rules: Vec<Box<PolymorphicEnumLoopRule>>) -> 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 = &PolymorphicEnumLoopRule> {
|
|
||||||
self.rules.iter().map(Box::as_ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum PolymorphicEnumLoopRule {
|
|
||||||
PassThrough(PolymorphicEnumLoopRulePassThrough),
|
|
||||||
Build(PolymorphicEnumLoopRuleBuild),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PolymorphicEnumLoopRulePassThrough {
|
|
||||||
name: String,
|
|
||||||
kind: String,
|
|
||||||
with: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PolymorphicEnumLoopRulePassThrough {
|
|
||||||
pub fn new(name: &str, kind: &str, with: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
kind: kind.to_string(),
|
|
||||||
with: with.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> &str {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with(&self) -> &str {
|
|
||||||
&self.with
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PolymorphicEnumLoopRuleBuild {
|
|
||||||
name: String,
|
|
||||||
variant: String,
|
|
||||||
children: Vec<Box<PolymorphicEnumLoopRuleBuildChild>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PolymorphicEnumLoopRuleBuild {
|
|
||||||
pub fn new(name: &str, variant: &str, children: Vec<Box<PolymorphicEnumLoopRuleBuildChild>>) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
variant: variant.to_string(),
|
|
||||||
children,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn variant(&self) -> &str {
|
|
||||||
&self.variant
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn children(&self) -> impl Iterator<Item = &PolymorphicEnumLoopRuleBuildChild> {
|
|
||||||
self.children.iter().map(Box::as_ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum PolymorphicEnumLoopRuleBuildChild {
|
|
||||||
UseCurrent(PolymorphicEnumLoopChildUseCurrent),
|
|
||||||
OnEach(PolymorphicEnumLoopRuleChildOnEach),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PolymorphicEnumLoopChildUseCurrent {
|
|
||||||
name: String,
|
|
||||||
kind: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PolymorphicEnumLoopChildUseCurrent {
|
|
||||||
pub fn new(name: &str, kind: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
kind: kind.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> &str {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PolymorphicEnumLoopRuleChildOnEach {
|
|
||||||
name: String,
|
|
||||||
rule: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PolymorphicEnumLoopRuleChildOnEach {
|
|
||||||
pub fn new(name: &str, rule: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
rule: rule.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rule(&self) -> &str {
|
|
||||||
&self.rule
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
pub struct PolymorphicPassThroughBuildSpec {
|
|
||||||
name: String,
|
|
||||||
build_kind: String,
|
|
||||||
variants: Vec<Box<PolymorphicPassThroughVariant>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PolymorphicPassThroughBuildSpec {
|
|
||||||
pub fn new(
|
|
||||||
name: &str,
|
|
||||||
build_kind: &str,
|
|
||||||
variants: Vec<Box<PolymorphicPassThroughVariant>>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
build_kind: build_kind.to_string(),
|
|
||||||
variants,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build_kind(&self) -> &str {
|
|
||||||
&self.build_kind
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn variants(&self) -> impl Iterator<Item = &PolymorphicPassThroughVariant> {
|
|
||||||
self.variants.iter().map(Box::as_ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum PolymorphicPassThroughVariant {
|
|
||||||
Inner { name: String, kind: String },
|
|
||||||
PassThrough { name: String, kind: String },
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
pub struct PolymorphicTypeBuildSpec {
|
|
||||||
name: String,
|
|
||||||
variants: Vec<Box<PolymorphicTypeVariant>>,
|
|
||||||
kind: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PolymorphicTypeBuildSpec {
|
|
||||||
pub fn new(name: &str, variants: Vec<Box<PolymorphicTypeVariant>>, kind: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
variants,
|
|
||||||
kind: kind.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn variants(&self) -> impl Iterator<Item = &PolymorphicTypeVariant> {
|
|
||||||
self.variants.iter().map(Box::as_ref)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> &str {
|
|
||||||
self.kind.as_str()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PolymorphicTypeVariant {
|
|
||||||
name: String,
|
|
||||||
inner_kind: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PolymorphicTypeVariant {
|
|
||||||
pub fn new(name: &str, inner_kind: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
inner_kind: inner_kind.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn inner_kind(&self) -> &str {
|
|
||||||
&self.inner_kind
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
pub struct ProductionBuildSpec {
|
|
||||||
name: String,
|
|
||||||
kind: ProductionKind,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ProductionBuildSpec {
|
|
||||||
pub fn new(name: &str, kind: ProductionKind) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
kind,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> &ProductionKind {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ProductionKind {
|
|
||||||
Int,
|
|
||||||
Long,
|
|
||||||
Double,
|
|
||||||
String(ProductionStringFrom),
|
|
||||||
Boolean(ProductionBooleanFrom),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ProductionStringFrom {
|
|
||||||
StringInner,
|
|
||||||
WholePair,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ProductionBooleanFrom {
|
|
||||||
ParseWholePair,
|
|
||||||
}
|
|
||||||
@ -1,212 +0,0 @@
|
|||||||
pub struct StructSpec {
|
|
||||||
build: String,
|
|
||||||
children: Vec<Box<StructChild>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StructSpec {
|
|
||||||
pub fn new(build: &str, children: Vec<Box<StructChild>>) -> Self {
|
|
||||||
Self {
|
|
||||||
build: build.to_string(),
|
|
||||||
children,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The type to be built, in Pascal case.
|
|
||||||
pub fn build(&self) -> &str {
|
|
||||||
&self.build
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The children for this build spec.
|
|
||||||
pub fn children(&self) -> impl Iterator<Item = &StructChild> {
|
|
||||||
self.children.iter().map(Box::as_ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum StructChild {
|
|
||||||
SkipChild(SkipChild),
|
|
||||||
VecChild(VecChild),
|
|
||||||
MemberChild(MemberChild),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SkipChild {
|
|
||||||
rule: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SkipChild {
|
|
||||||
pub fn new(rule: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
rule: rule.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The grammar rule to match.
|
|
||||||
pub fn rule(&self) -> &str {
|
|
||||||
&self.rule
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct VecChild {
|
|
||||||
name: String,
|
|
||||||
rule: String,
|
|
||||||
build: Box<VecChildBuild>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VecChild {
|
|
||||||
pub fn new(name: &str, rule: &str, build: Box<VecChildBuild>) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
rule: rule.to_string(),
|
|
||||||
build
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The name of this child.
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The rule to match to build this child.
|
|
||||||
pub fn rule(&self) -> &str {
|
|
||||||
&self.rule
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build(&self) -> &VecChildBuild {
|
|
||||||
&self.build
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum VecChildBuild {
|
|
||||||
String(VecChildStringBuild),
|
|
||||||
Node(VecChildNodeBuild)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct VecChildStringBuild {
|
|
||||||
with: String
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VecChildStringBuild {
|
|
||||||
pub fn new(with: &str) -> Self {
|
|
||||||
Self { with: with.to_string() }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with(&self) -> &str {
|
|
||||||
&self.with
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct VecChildNodeBuild {
|
|
||||||
kind: String,
|
|
||||||
with: String
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VecChildNodeBuild {
|
|
||||||
pub fn new(kind: &str, with: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
kind: kind.to_string(),
|
|
||||||
with: with.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> &str {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with(&self) -> &str {
|
|
||||||
&self.with
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct MemberChild {
|
|
||||||
name: String,
|
|
||||||
rule: String,
|
|
||||||
optional: bool,
|
|
||||||
build: Box<MemberChildBuild>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MemberChild {
|
|
||||||
pub fn new(name: &str, rule: &str, optional: bool, build: Box<MemberChildBuild>) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
rule: rule.to_string(),
|
|
||||||
optional,
|
|
||||||
build,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The name of this child in the yaml file, in snake case.
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The grammar rule to match to build this child.
|
|
||||||
pub fn rule(&self) -> &str {
|
|
||||||
&self.rule
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn optional(&self) -> bool {
|
|
||||||
self.optional
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The specification for what to actually build.
|
|
||||||
pub fn build(&self) -> &MemberChildBuild {
|
|
||||||
&self.build
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum MemberChildBuild {
|
|
||||||
Node(NodeMemberBuild),
|
|
||||||
Boolean(BooleanMemberBuild),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct NodeMemberBuild {
|
|
||||||
kind: String,
|
|
||||||
with: String,
|
|
||||||
or_else: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NodeMemberBuild {
|
|
||||||
pub fn new(kind: &str, with: &str, or_else: Option<String>) -> Self {
|
|
||||||
Self {
|
|
||||||
kind: kind.to_string(),
|
|
||||||
with: with.to_string(),
|
|
||||||
or_else,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The type to build, in Pascal case.
|
|
||||||
pub fn kind(&self) -> &str {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with(&self) -> &str {
|
|
||||||
&self.with
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The default fn to call when unwrapping the child (before passing as arg to new).
|
|
||||||
pub fn or_else(&self) -> Option<&str> {
|
|
||||||
self.or_else.as_deref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct BooleanMemberBuild {
|
|
||||||
on: BooleanMemberBuildOn,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BooleanMemberBuild {
|
|
||||||
pub fn new(on: BooleanMemberBuildOn) -> Self {
|
|
||||||
Self { on }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn on(&self) -> &BooleanMemberBuildOn {
|
|
||||||
&self.on
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum BooleanMemberBuildOn {
|
|
||||||
RulePresent
|
|
||||||
}
|
|
||||||
@ -1,117 +0,0 @@
|
|||||||
pub struct TreeEnumBuildSpec {
|
|
||||||
build: String,
|
|
||||||
rules: Vec<Box<TreeEnumRule>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TreeEnumBuildSpec {
|
|
||||||
pub fn new(build: &str, rules: Vec<Box<TreeEnumRule>>) -> Self {
|
|
||||||
TreeEnumBuildSpec {
|
|
||||||
build: build.to_string(),
|
|
||||||
rules,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The enum type to be built, in Pascal case.
|
|
||||||
pub fn build(&self) -> &str {
|
|
||||||
&self.build
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The individual rule specs.
|
|
||||||
pub fn rules(&self) -> impl Iterator<Item = &TreeEnumRule> {
|
|
||||||
self.rules.iter().map(Box::as_ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TreeEnumRule {
|
|
||||||
rule: String,
|
|
||||||
child: Option<Box<EnumRuleChild>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TreeEnumRule {
|
|
||||||
pub fn new(rule: &str, child: Option<Box<EnumRuleChild>>) -> Self {
|
|
||||||
Self {
|
|
||||||
rule: rule.to_string(),
|
|
||||||
child,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The enum rule to match, in Pascal case.
|
|
||||||
pub fn rule(&self) -> &str {
|
|
||||||
&self.rule
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn child(&self) -> Option<&EnumRuleChild> {
|
|
||||||
if let Some(child) = &self.child {
|
|
||||||
Some(child.as_ref())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct EnumRuleChild {
|
|
||||||
kind: Box<EnumRuleChildKind>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EnumRuleChild {
|
|
||||||
pub fn new(kind: Box<EnumRuleChildKind>) -> Self {
|
|
||||||
Self { kind }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> &EnumRuleChildKind {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum EnumRuleChildKind {
|
|
||||||
Node(EnumRuleChildNodeKind),
|
|
||||||
Int(NameAndWith),
|
|
||||||
Long(NameAndWith),
|
|
||||||
Double(NameAndWith),
|
|
||||||
String(NameAndWith),
|
|
||||||
Boolean(NameAndWith),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct EnumRuleChildNodeKind {
|
|
||||||
node_kind: String,
|
|
||||||
with: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EnumRuleChildNodeKind {
|
|
||||||
pub fn new(node_kind: &str, with: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
node_kind: node_kind.to_string(),
|
|
||||||
with: with.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn node_kind(&self) -> &str {
|
|
||||||
&self.node_kind
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with(&self) -> &str {
|
|
||||||
&self.with
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct NameAndWith {
|
|
||||||
name: String,
|
|
||||||
with: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NameAndWith {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
216
ast-generator/src/struct_build_fn.rs
Normal file
216
ast-generator/src/struct_build_fn.rs
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
use crate::spec::{BooleanChildToBuild, MemberChildToBuild, NodeChildToBuild, StructBuildSpec, StructChildSpec, VecChild, VecChildToBuild};
|
||||||
|
use crate::util::{make_build_fn_name, make_build_pair};
|
||||||
|
use convert_case::{Case, Casing};
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
fn make_var_name(s: &str) -> String {
|
||||||
|
s.to_case(Case::Snake)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream {
|
||||||
|
let child_ident = format_ident!("{}", vec_child.name());
|
||||||
|
match vec_child.build() {
|
||||||
|
VecChildToBuild::Node(node_child) => {
|
||||||
|
let child_type_ident = format_ident!("{}", node_child.build());
|
||||||
|
quote! {
|
||||||
|
let mut #child_ident: Vec<Box<#child_type_ident >> = vec![]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
VecChildToBuild::String => quote! {
|
||||||
|
let mut #child_ident: Vec<String> = vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_node_child_holder(name: &str, node_child: &NodeChildToBuild) -> TokenStream {
|
||||||
|
let child_ident = format_ident!("{}", name);
|
||||||
|
let child_type_ident = format_ident!("{}", node_child.build());
|
||||||
|
quote! {
|
||||||
|
let mut #child_ident: Option<Box<#child_type_ident>> = None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_boolean_child_holder(boolean_child: &BooleanChildToBuild) -> TokenStream {
|
||||||
|
let child_ident = format_ident!("{}", boolean_child.name());
|
||||||
|
quote! {
|
||||||
|
let mut #child_ident: bool = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_child_holder(child_spec: &StructChildSpec) -> Option<TokenStream> {
|
||||||
|
match child_spec {
|
||||||
|
StructChildSpec::SkipChild(_) => None,
|
||||||
|
StructChildSpec::VecChild(vec_child) => Some(make_vec_child_holder(vec_child)),
|
||||||
|
StructChildSpec::MemberChild(member_child) => match member_child.build() {
|
||||||
|
MemberChildToBuild::Node(node_child) => {
|
||||||
|
Some(make_node_child_holder(member_child.name(), node_child))
|
||||||
|
}
|
||||||
|
MemberChildToBuild::Boolean(boolean_child) => {
|
||||||
|
Some(make_boolean_child_holder(boolean_child))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_vec_child_match_action(vec_child: &VecChild) -> TokenStream {
|
||||||
|
let child_name_ident = format_ident!("{}", vec_child.name());
|
||||||
|
match vec_child.build() {
|
||||||
|
VecChildToBuild::Node(vec_node_child) => {
|
||||||
|
let build_fn_ident = format_ident!("{}", make_build_fn_name(vec_node_child.build()));
|
||||||
|
quote! {
|
||||||
|
#child_name_ident.push(Box::new(#build_fn_ident(inner_pair)))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
VecChildToBuild::String => {
|
||||||
|
let build_fn_ident = format_ident!("{}", make_build_fn_name(vec_child.rule()));
|
||||||
|
quote! {
|
||||||
|
#child_name_ident.push(#build_fn_ident(inner_pair))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_node_member_child_match_action(name: &str, node_child: &NodeChildToBuild) -> TokenStream {
|
||||||
|
let child_name_ident = format_ident!("{}", name);
|
||||||
|
let build_fn_ident = format_ident!("{}", make_build_fn_name(node_child.build()));
|
||||||
|
quote! {
|
||||||
|
#child_name_ident = Some(Box::new(#build_fn_ident(inner_pair)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_boolean_member_child_match_action(boolean_child: &BooleanChildToBuild) -> TokenStream {
|
||||||
|
let child_name_ident = format_ident!("{}", make_var_name(boolean_child.name()));
|
||||||
|
quote! {
|
||||||
|
#child_name_ident = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_match_action(child_spec: &StructChildSpec) -> TokenStream {
|
||||||
|
match child_spec {
|
||||||
|
StructChildSpec::SkipChild(_) => quote! {},
|
||||||
|
StructChildSpec::VecChild(vec_child) => {
|
||||||
|
make_vec_child_match_action(vec_child)
|
||||||
|
}
|
||||||
|
StructChildSpec::MemberChild(member_child) => match member_child.build() {
|
||||||
|
MemberChildToBuild::Node(node_child) => {
|
||||||
|
make_node_member_child_match_action(member_child.name(), node_child)
|
||||||
|
}
|
||||||
|
MemberChildToBuild::Boolean(boolean_child) => {
|
||||||
|
make_boolean_member_child_match_action(boolean_child)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_rule_matcher(child_spec: &StructChildSpec) -> TokenStream {
|
||||||
|
let rule_ident = match child_spec {
|
||||||
|
StructChildSpec::SkipChild(skip_child) => format_ident!("{}", skip_child.rule()),
|
||||||
|
StructChildSpec::VecChild(vec_child) => format_ident!("{}", vec_child.rule()),
|
||||||
|
StructChildSpec::MemberChild(single_child) => format_ident!("{}", single_child.rule()),
|
||||||
|
};
|
||||||
|
let action = make_match_action(child_spec);
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
Rule::#rule_ident => {
|
||||||
|
#action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_vec_child_arg(vec_child: &VecChild) -> TokenStream {
|
||||||
|
let child_ident = format_ident!("{}", vec_child.name());
|
||||||
|
quote! { #child_ident }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_node_member_child_arg(name: &str, node_child: &NodeChildToBuild) -> TokenStream {
|
||||||
|
let child_ident = format_ident!("{}", name);
|
||||||
|
if node_child.optional() {
|
||||||
|
quote! { #child_ident }
|
||||||
|
} else if let Some(or_else) = node_child.or_else() {
|
||||||
|
let child_type_ident = format_ident!("{}", node_child.build());
|
||||||
|
let or_else_ident = format_ident!("{}", or_else);
|
||||||
|
quote! {
|
||||||
|
#child_ident.unwrap_or_else(|| Box::new(#child_type_ident::#or_else_ident()))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! { #child_ident.unwrap() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_boolean_member_child_arg(boolean_child: &BooleanChildToBuild) -> TokenStream {
|
||||||
|
let child_ident = format_ident!("{}", boolean_child.name());
|
||||||
|
quote! { #child_ident }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_child_arg(child_spec: &StructChildSpec) -> Option<TokenStream> {
|
||||||
|
match child_spec {
|
||||||
|
StructChildSpec::SkipChild(_) => None,
|
||||||
|
StructChildSpec::VecChild(vec_child) => {
|
||||||
|
Some(make_vec_child_arg(vec_child))
|
||||||
|
}
|
||||||
|
StructChildSpec::MemberChild(member_child) => match member_child.build() {
|
||||||
|
MemberChildToBuild::Node(single_type_child) => {
|
||||||
|
Some(make_node_member_child_arg(member_child.name(), single_type_child))
|
||||||
|
}
|
||||||
|
MemberChildToBuild::Boolean(boolean_child) => {
|
||||||
|
Some(make_boolean_member_child_arg(boolean_child))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_return_value_stream(build_spec: &StructBuildSpec) -> TokenStream {
|
||||||
|
let type_ident = format_ident!("{}", build_spec.build());
|
||||||
|
let child_args = build_spec
|
||||||
|
.children()
|
||||||
|
.map(|child| make_child_arg(child))
|
||||||
|
.filter(|child_arg| child_arg.is_some())
|
||||||
|
.map(|child_arg| child_arg.unwrap())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#type_ident::new(
|
||||||
|
#(#child_args,)*
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_struct_build_fn(build_spec: &StructBuildSpec) -> TokenStream {
|
||||||
|
let build_fn_ident = format_ident!("{}", make_build_fn_name(build_spec.build()));
|
||||||
|
let pair_ident = format_ident!("{}", make_build_pair(build_spec.build()));
|
||||||
|
let return_type_ident = format_ident!("{}", build_spec.build());
|
||||||
|
|
||||||
|
let child_holders = build_spec
|
||||||
|
.children()
|
||||||
|
.map(|child_spec| make_child_holder(child_spec))
|
||||||
|
.filter(|child_holder| child_holder.is_some())
|
||||||
|
.map(|child_holder| child_holder.unwrap())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let rule_matchers = build_spec
|
||||||
|
.children()
|
||||||
|
.map(|child_spec| make_rule_matcher(child_spec))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let iter_stream = quote! {
|
||||||
|
for inner_pair in #pair_ident.into_inner() {
|
||||||
|
match inner_pair.as_rule() {
|
||||||
|
#(#rule_matchers)*
|
||||||
|
_ => panic!("Unexpected rule: {:?}", inner_pair.as_rule())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let new_stream = make_return_value_stream(build_spec);
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||||
|
#(#child_holders;)*
|
||||||
|
|
||||||
|
#iter_stream
|
||||||
|
|
||||||
|
#new_stream
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
464
ast-generator/src/type_gen.rs
Normal file
464
ast-generator/src/type_gen.rs
Normal file
@ -0,0 +1,464 @@
|
|||||||
|
use crate::spec::{
|
||||||
|
AlternativeAction, AlternativeChild, BooleanChildToBuild, BuildSpec, EnumBuildSpec,
|
||||||
|
EnumRuleChildKind, LeafEnumBuildSpec, LeafStructBuildSpec, LeafStructMemberKind,
|
||||||
|
MemberChildToBuild, NodeChildToBuild, PolymorphicBuildBuildSpec, PolymorphicTypeBuildSpec,
|
||||||
|
StructBuildSpec, StructChildSpec, VecChild, VecChildToBuild,
|
||||||
|
};
|
||||||
|
use proc_macro2::{Ident, TokenStream};
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
fn make_polymorphic_build_type(build_spec: &PolymorphicBuildBuildSpec) -> TokenStream {
|
||||||
|
let alternative_action = build_spec
|
||||||
|
.alternatives()
|
||||||
|
.find(|alternative| {
|
||||||
|
if let AlternativeAction::Build(_) = alternative.action() {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let alternative_build =
|
||||||
|
if let AlternativeAction::Build(alternative_build) = alternative_action.action() {
|
||||||
|
alternative_build
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
let annotated_members = alternative_build
|
||||||
|
.children()
|
||||||
|
.map(|child| match child {
|
||||||
|
AlternativeChild::Skip => None,
|
||||||
|
AlternativeChild::Build(build_child) => {
|
||||||
|
let child_name_ident = format_ident!("{}", build_child.name());
|
||||||
|
let type_ident = format_ident!("{}", build_child.kind());
|
||||||
|
Some(quote! {
|
||||||
|
#child_name_ident: Box<#type_ident>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let initializers = alternative_build
|
||||||
|
.children()
|
||||||
|
.map(|child| match child {
|
||||||
|
AlternativeChild::Skip => None,
|
||||||
|
AlternativeChild::Build(build_child) => Some(format_ident!("{}", build_child.name())),
|
||||||
|
})
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let accessors = alternative_build
|
||||||
|
.children()
|
||||||
|
.map(|child| match child {
|
||||||
|
AlternativeChild::Skip => None,
|
||||||
|
AlternativeChild::Build(build_child) => {
|
||||||
|
let child_ident = format_ident!("{}", build_child.name());
|
||||||
|
let child_ident_mut = format_ident!("{}_mut", build_child.name());
|
||||||
|
let child_type_ident = format_ident!("{}", build_child.kind());
|
||||||
|
Some(quote! {
|
||||||
|
pub fn #child_ident(&self) -> &#child_type_ident {
|
||||||
|
&self.#child_ident
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn #child_ident_mut(&mut self) -> &mut #child_type_ident {
|
||||||
|
&mut self.#child_ident
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let type_ident = format_ident!("{}", build_spec.name());
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
pub struct #type_ident {
|
||||||
|
#(#annotated_members),*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl #type_ident {
|
||||||
|
pub fn new(#(#annotated_members),*) -> Self {
|
||||||
|
Self {
|
||||||
|
#(#initializers),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#(#accessors)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_polymorphic_type_type(build_spec: &PolymorphicTypeBuildSpec) -> TokenStream {
|
||||||
|
let members = build_spec
|
||||||
|
.enum_members()
|
||||||
|
.map(|enum_member| {
|
||||||
|
let member_ident = format_ident!("{}", enum_member.name());
|
||||||
|
let inner_type_ident = format_ident!("{}", enum_member.inner_kind());
|
||||||
|
quote! {
|
||||||
|
#member_ident(#inner_type_ident)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let type_name_ident = format_ident!("{}", build_spec.name());
|
||||||
|
quote! {
|
||||||
|
pub enum #type_name_ident {
|
||||||
|
#(#members),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_enum_type(build_spec: &EnumBuildSpec) -> TokenStream {
|
||||||
|
let children: Vec<TokenStream> = build_spec
|
||||||
|
.rules()
|
||||||
|
.map(|enum_rule| {
|
||||||
|
let member_name_ident = format_ident!("{}", enum_rule.rule());
|
||||||
|
if let Some(enum_rule_child) = enum_rule.child() {
|
||||||
|
let child_type_ident = match enum_rule_child.kind() {
|
||||||
|
EnumRuleChildKind::Node(node_child) => {
|
||||||
|
format_ident!("{}", node_child.build())
|
||||||
|
}
|
||||||
|
EnumRuleChildKind::Int => format_ident!("i32"),
|
||||||
|
EnumRuleChildKind::Long => format_ident!("i64"),
|
||||||
|
EnumRuleChildKind::Double => format_ident!("f64"),
|
||||||
|
EnumRuleChildKind::USize => format_ident!("usize"),
|
||||||
|
EnumRuleChildKind::String => format_ident!("String"),
|
||||||
|
EnumRuleChildKind::Boolean => format_ident!("bool"),
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
#member_name_ident(#child_type_ident)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
#member_name_ident
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let type_name_ident = format_ident!("{}", build_spec.build());
|
||||||
|
quote! {
|
||||||
|
pub enum #type_name_ident {
|
||||||
|
#(#children),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_leaf_enum_type(build_spec: &LeafEnumBuildSpec) -> TokenStream {
|
||||||
|
let type_name_ident = format_ident!("{}", build_spec.build());
|
||||||
|
let children = build_spec
|
||||||
|
.rules()
|
||||||
|
.map(|leaf_enum_rule| {
|
||||||
|
let rule_name_ident = format_ident!("{}", leaf_enum_rule.rule());
|
||||||
|
quote! {
|
||||||
|
#rule_name_ident
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
pub enum #type_name_ident {
|
||||||
|
#(#children),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_vec_child(
|
||||||
|
vec_child: &VecChild,
|
||||||
|
member_names: &mut Vec<Ident>,
|
||||||
|
annotated_members: &mut Vec<TokenStream>,
|
||||||
|
member_args: &mut Vec<TokenStream>,
|
||||||
|
accessors: &mut Vec<TokenStream>,
|
||||||
|
) {
|
||||||
|
let (child_ident, child_ident_mut) = (
|
||||||
|
format_ident!("{}", vec_child.name()),
|
||||||
|
format_ident!("{}_mut", vec_child.name()),
|
||||||
|
);
|
||||||
|
let child_type_ident = match vec_child.build() {
|
||||||
|
VecChildToBuild::Node(vec_node_child) => format_ident!("{}", vec_node_child.build()),
|
||||||
|
VecChildToBuild::String => format_ident!("{}", "String"),
|
||||||
|
};
|
||||||
|
|
||||||
|
member_names.push(child_ident.clone());
|
||||||
|
|
||||||
|
match vec_child.build() {
|
||||||
|
VecChildToBuild::Node(_) => {
|
||||||
|
annotated_members.push(quote! {
|
||||||
|
#child_ident: Vec<Box<#child_type_ident>>
|
||||||
|
});
|
||||||
|
member_args.push(quote! {
|
||||||
|
#child_ident: Vec<Box<#child_type_ident>>
|
||||||
|
});
|
||||||
|
}
|
||||||
|
VecChildToBuild::String => {
|
||||||
|
annotated_members.push(quote! {
|
||||||
|
#child_ident: Vec<String>
|
||||||
|
});
|
||||||
|
member_args.push(quote! {
|
||||||
|
#child_ident: Vec<String>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match vec_child.build() {
|
||||||
|
VecChildToBuild::Node(_) => {
|
||||||
|
accessors.push(quote! {
|
||||||
|
pub fn #child_ident(&self) -> impl Iterator<Item = &#child_type_ident> {
|
||||||
|
self.#child_ident.iter().map(Box::as_ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn #child_ident_mut(&mut self) -> impl Iterator<Item = &mut #child_type_ident> {
|
||||||
|
self.#child_ident.iter_mut().map(Box::as_mut)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
VecChildToBuild::String => accessors.push(quote! {
|
||||||
|
pub fn #child_ident(&self) -> impl Iterator<Item = &str> {
|
||||||
|
self.#child_ident.iter().map(String::as_str)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_node_child(
|
||||||
|
name: &str,
|
||||||
|
node_child: &NodeChildToBuild,
|
||||||
|
member_names: &mut Vec<Ident>,
|
||||||
|
annotated_members: &mut Vec<TokenStream>,
|
||||||
|
member_args: &mut Vec<TokenStream>,
|
||||||
|
accessors: &mut Vec<TokenStream>,
|
||||||
|
) {
|
||||||
|
let child_ident = format_ident!("{}", name);
|
||||||
|
let child_ident_mut = format_ident!("{}_mut", name);
|
||||||
|
let child_type_ident = format_ident!("{}", node_child.build());
|
||||||
|
|
||||||
|
member_names.push(child_ident.clone());
|
||||||
|
|
||||||
|
if node_child.optional() {
|
||||||
|
annotated_members.push(quote! {
|
||||||
|
#child_ident: Option<Box<#child_type_ident>>
|
||||||
|
});
|
||||||
|
member_args.push(quote! {
|
||||||
|
#child_ident: Option<Box<#child_type_ident>>
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
annotated_members.push(quote! {
|
||||||
|
#child_ident: Box<#child_type_ident>
|
||||||
|
});
|
||||||
|
member_args.push(quote! {
|
||||||
|
#child_ident: Box<#child_type_ident>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if node_child.optional() {
|
||||||
|
accessors.push(quote! {
|
||||||
|
pub fn #child_ident(&self) -> Option<&#child_type_ident> {
|
||||||
|
if let Some(#child_ident) = &self.#child_ident {
|
||||||
|
Some(#child_ident.as_ref())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn #child_ident_mut(&mut self) -> Option<&mut #child_type_ident> {
|
||||||
|
if let Some(#child_ident) = &mut self.#child_ident {
|
||||||
|
Some(#child_ident.as_mut())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
accessors.push(quote! {
|
||||||
|
pub fn #child_ident(&self) -> &#child_type_ident {
|
||||||
|
self.#child_ident.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn #child_ident_mut(&mut self) -> &mut #child_type_ident {
|
||||||
|
self.#child_ident.as_mut()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_boolean_child(
|
||||||
|
single_boolean_child: &BooleanChildToBuild,
|
||||||
|
member_names: &mut Vec<Ident>,
|
||||||
|
annotated_members: &mut Vec<TokenStream>,
|
||||||
|
member_args: &mut Vec<TokenStream>,
|
||||||
|
accessors: &mut Vec<TokenStream>,
|
||||||
|
) {
|
||||||
|
let child_ident = format_ident!("{}", single_boolean_child.name());
|
||||||
|
member_names.push(child_ident.clone());
|
||||||
|
annotated_members.push(quote! {
|
||||||
|
#child_ident: bool
|
||||||
|
});
|
||||||
|
member_args.push(quote! {
|
||||||
|
#child_ident: bool
|
||||||
|
});
|
||||||
|
accessors.push(quote! {
|
||||||
|
pub fn #child_ident(&self) -> bool {
|
||||||
|
self.#child_ident
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_struct_type(build_spec: &StructBuildSpec) -> TokenStream {
|
||||||
|
let mut member_names: Vec<Ident> = vec![];
|
||||||
|
let mut annotated_members: Vec<TokenStream> = vec![];
|
||||||
|
let mut member_args: Vec<TokenStream> = vec![];
|
||||||
|
let mut accessors: Vec<TokenStream> = vec![];
|
||||||
|
|
||||||
|
for child_spec in build_spec.children() {
|
||||||
|
match child_spec {
|
||||||
|
StructChildSpec::SkipChild(_) => {}
|
||||||
|
StructChildSpec::VecChild(vec_child) => {
|
||||||
|
handle_vec_child(
|
||||||
|
vec_child,
|
||||||
|
&mut member_names,
|
||||||
|
&mut annotated_members,
|
||||||
|
&mut member_args,
|
||||||
|
&mut accessors,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
StructChildSpec::MemberChild(member_child) => {
|
||||||
|
match member_child.build() {
|
||||||
|
MemberChildToBuild::Node(node_child) => {
|
||||||
|
handle_node_child(
|
||||||
|
member_child.name(),
|
||||||
|
node_child,
|
||||||
|
&mut member_names,
|
||||||
|
&mut annotated_members,
|
||||||
|
&mut member_args,
|
||||||
|
&mut accessors,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
MemberChildToBuild::Boolean(boolean_child) => {
|
||||||
|
handle_boolean_child(
|
||||||
|
boolean_child,
|
||||||
|
&mut member_names,
|
||||||
|
&mut annotated_members,
|
||||||
|
&mut member_args,
|
||||||
|
&mut accessors,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let type_ident = format_ident!("{}", build_spec.build());
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
pub struct #type_ident {
|
||||||
|
#(#annotated_members),*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl #type_ident {
|
||||||
|
pub fn new(#(#annotated_members),*) -> Self {
|
||||||
|
Self {
|
||||||
|
#(#member_names),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#(#accessors)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_leaf_struct_type(build_spec: &LeafStructBuildSpec) -> TokenStream {
|
||||||
|
let type_ident = format_ident!("{}", build_spec.build());
|
||||||
|
|
||||||
|
let annotated_members = build_spec
|
||||||
|
.members()
|
||||||
|
.map(|member| {
|
||||||
|
let name_ident = format_ident!("{}", member.name());
|
||||||
|
let type_ident = match member.kind() {
|
||||||
|
LeafStructMemberKind::String => format_ident!("{}", "String"),
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
#name_ident: #type_ident
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let member_args = build_spec.members().map(|member| {
|
||||||
|
let name_ident = format_ident!("{}", member.name());
|
||||||
|
let type_stream = match member.kind() {
|
||||||
|
LeafStructMemberKind::String => {
|
||||||
|
quote! { &str }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
#name_ident: #type_stream
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let initializers = build_spec
|
||||||
|
.members()
|
||||||
|
.map(|leaf_struct_member| {
|
||||||
|
let member_ident = format_ident!("{}", leaf_struct_member.name());
|
||||||
|
match leaf_struct_member.kind() {
|
||||||
|
LeafStructMemberKind::String => {
|
||||||
|
quote! {
|
||||||
|
#member_ident: #member_ident.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let accessors = build_spec
|
||||||
|
.members()
|
||||||
|
.map(|member| {
|
||||||
|
let name_ident = format_ident!("{}", member.name());
|
||||||
|
match member.kind() {
|
||||||
|
LeafStructMemberKind::String => {
|
||||||
|
quote! {
|
||||||
|
pub fn #name_ident(&self) -> &str {
|
||||||
|
&self.#name_ident
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
pub struct #type_ident {
|
||||||
|
#(#annotated_members),*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl #type_ident {
|
||||||
|
pub fn new(#(#member_args),*) -> Self {
|
||||||
|
Self {
|
||||||
|
#(#initializers),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#(#accessors)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||||
|
match build_spec {
|
||||||
|
BuildSpec::Enum(enum_build_spec) => Some(make_enum_type(enum_build_spec)),
|
||||||
|
BuildSpec::LeafEnum(leaf_enum_build_spec) => {
|
||||||
|
Some(make_leaf_enum_type(leaf_enum_build_spec))
|
||||||
|
}
|
||||||
|
BuildSpec::Struct(struct_build_spec) => Some(make_struct_type(struct_build_spec)),
|
||||||
|
BuildSpec::LeafStruct(leaf_struct_build_spec) => {
|
||||||
|
Some(make_leaf_struct_type(leaf_struct_build_spec))
|
||||||
|
}
|
||||||
|
BuildSpec::Production(_) => None,
|
||||||
|
BuildSpec::Polymorphic(polymorphic_build_spec) => {
|
||||||
|
Some(make_polymorphic_type_type(polymorphic_build_spec))
|
||||||
|
}
|
||||||
|
BuildSpec::PolymorphicBuild(polymorphic_build_build_spec) => {
|
||||||
|
Some(make_polymorphic_build_type(polymorphic_build_build_spec))
|
||||||
|
}
|
||||||
|
BuildSpec::PolymorphicEnum(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,37 +0,0 @@
|
|||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
use crate::spec::tree_enum_spec::{EnumRuleChildKind, TreeEnumBuildSpec};
|
|
||||||
|
|
||||||
pub fn make_enum_type(build_spec: &TreeEnumBuildSpec) -> TokenStream {
|
|
||||||
let children: Vec<TokenStream> = build_spec
|
|
||||||
.rules()
|
|
||||||
.map(|enum_rule| {
|
|
||||||
let member_name_ident = format_ident!("{}", enum_rule.rule());
|
|
||||||
if let Some(enum_rule_child) = enum_rule.child() {
|
|
||||||
let child_type_ident = match enum_rule_child.kind() {
|
|
||||||
EnumRuleChildKind::Node(node_child) => {
|
|
||||||
format_ident!("{}", node_child.node_kind())
|
|
||||||
}
|
|
||||||
EnumRuleChildKind::Int(_) => format_ident!("i32"),
|
|
||||||
EnumRuleChildKind::Long(_) => format_ident!("i64"),
|
|
||||||
EnumRuleChildKind::Double(_) => format_ident!("f64"),
|
|
||||||
EnumRuleChildKind::String(_) => format_ident!("String"),
|
|
||||||
EnumRuleChildKind::Boolean(_) => format_ident!("bool"),
|
|
||||||
};
|
|
||||||
quote! {
|
|
||||||
#member_name_ident(#child_type_ident)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
quote! {
|
|
||||||
#member_name_ident
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
let type_name_ident = format_ident!("{}", build_spec.build());
|
|
||||||
quote! {
|
|
||||||
pub enum #type_name_ident {
|
|
||||||
#(#children),*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
use crate::spec::leaf_enum_spec::LeafEnumBuildSpec;
|
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
|
|
||||||
pub fn make_leaf_enum_type(build_spec: &LeafEnumBuildSpec) -> TokenStream {
|
|
||||||
let type_name_ident = format_ident!("{}", build_spec.build());
|
|
||||||
let children = build_spec
|
|
||||||
.rules()
|
|
||||||
.map(|leaf_enum_rule| {
|
|
||||||
let rule_name_ident = format_ident!("{}", leaf_enum_rule);
|
|
||||||
quote! {
|
|
||||||
#rule_name_ident
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
pub enum #type_name_ident {
|
|
||||||
#(#children),*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
use crate::spec::leaf_struct_spec::{LeafStructBuildSpec, LeafStructMemberKind};
|
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
|
|
||||||
pub fn make_leaf_struct_type(build_spec: &LeafStructBuildSpec) -> TokenStream {
|
|
||||||
let type_ident = format_ident!("{}", build_spec.build());
|
|
||||||
|
|
||||||
let annotated_members = build_spec
|
|
||||||
.members()
|
|
||||||
.map(|member| {
|
|
||||||
let name_ident = format_ident!("{}", member.name());
|
|
||||||
let type_ident = match member.kind() {
|
|
||||||
LeafStructMemberKind::String => format_ident!("{}", "String"),
|
|
||||||
};
|
|
||||||
quote! {
|
|
||||||
#name_ident: #type_ident
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let member_args = build_spec.members().map(|member| {
|
|
||||||
let name_ident = format_ident!("{}", member.name());
|
|
||||||
let type_stream = match member.kind() {
|
|
||||||
LeafStructMemberKind::String => {
|
|
||||||
quote! { &str }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
quote! {
|
|
||||||
#name_ident: #type_stream
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let initializers = build_spec
|
|
||||||
.members()
|
|
||||||
.map(|leaf_struct_member| {
|
|
||||||
let member_ident = format_ident!("{}", leaf_struct_member.name());
|
|
||||||
match leaf_struct_member.kind() {
|
|
||||||
LeafStructMemberKind::String => {
|
|
||||||
quote! {
|
|
||||||
#member_ident: #member_ident.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let accessors = build_spec
|
|
||||||
.members()
|
|
||||||
.map(|member| {
|
|
||||||
let name_ident = format_ident!("{}", member.name());
|
|
||||||
match member.kind() {
|
|
||||||
LeafStructMemberKind::String => {
|
|
||||||
quote! {
|
|
||||||
pub fn #name_ident(&self) -> &str {
|
|
||||||
&self.#name_ident
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
pub struct #type_ident {
|
|
||||||
#(#annotated_members),*
|
|
||||||
}
|
|
||||||
|
|
||||||
impl #type_ident {
|
|
||||||
pub fn new(#(#member_args),*) -> Self {
|
|
||||||
Self {
|
|
||||||
#(#initializers),*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#(#accessors)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
mod enum_type;
|
|
||||||
mod leaf_enum_type;
|
|
||||||
mod leaf_struct_type;
|
|
||||||
mod polymorphic_type_type;
|
|
||||||
mod struct_type;
|
|
||||||
|
|
||||||
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_type_type::make_polymorphic_type_type;
|
|
||||||
use crate::type_gen::struct_type::make_struct_type;
|
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
|
|
||||||
pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> {
|
|
||||||
match build_spec {
|
|
||||||
BuildSpec::Struct(struct_build_spec) => Some(make_struct_type(struct_build_spec)),
|
|
||||||
BuildSpec::LeafStruct(leaf_struct_build_spec) => {
|
|
||||||
Some(make_leaf_struct_type(leaf_struct_build_spec))
|
|
||||||
}
|
|
||||||
BuildSpec::Enum(enum_build_spec) => Some(make_enum_type(enum_build_spec)),
|
|
||||||
BuildSpec::LeafEnum(leaf_enum_build_spec) => {
|
|
||||||
Some(make_leaf_enum_type(leaf_enum_build_spec))
|
|
||||||
}
|
|
||||||
BuildSpec::Production(_) => None,
|
|
||||||
BuildSpec::NodeProduction(_) => None,
|
|
||||||
BuildSpec::PolymorphicType(polymorphic_build_spec) => {
|
|
||||||
Some(make_polymorphic_type_type(polymorphic_build_spec))
|
|
||||||
}
|
|
||||||
BuildSpec::PolymorphicEnumLoop(_) => None,
|
|
||||||
BuildSpec::PolymorphicPassThrough(_) => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
use crate::spec::polymorphic_type_spec::PolymorphicTypeBuildSpec;
|
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
|
|
||||||
pub fn make_polymorphic_type_type(build_spec: &PolymorphicTypeBuildSpec) -> TokenStream {
|
|
||||||
let members = build_spec
|
|
||||||
.variants()
|
|
||||||
.map(|enum_member| {
|
|
||||||
let member_ident = format_ident!("{}", enum_member.name());
|
|
||||||
let inner_type_ident = format_ident!("{}", enum_member.inner_kind());
|
|
||||||
quote! {
|
|
||||||
#member_ident(#inner_type_ident)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let type_name_ident = format_ident!("{}", build_spec.name());
|
|
||||||
quote! {
|
|
||||||
pub enum #type_name_ident {
|
|
||||||
#(#members),*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,193 +0,0 @@
|
|||||||
use crate::spec::struct_spec::{MemberChild, MemberChildBuild, StructChild, StructSpec, VecChild, VecChildBuild};
|
|
||||||
use proc_macro2::{Ident, TokenStream};
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
|
|
||||||
fn make_vec_child_accessors(vec_child: &VecChild) -> TokenStream {
|
|
||||||
let child_ident = format_ident!("{}", vec_child.name());
|
|
||||||
match vec_child.build() {
|
|
||||||
VecChildBuild::String(_) => {
|
|
||||||
quote! {
|
|
||||||
pub fn #child_ident(&self) -> impl Iterator<Item = &str> {
|
|
||||||
self.#child_ident.iter().map(String::as_str)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
VecChildBuild::Node(vec_child_node_build) => {
|
|
||||||
let child_type_ident = format_ident!("{}", vec_child_node_build.kind());
|
|
||||||
let child_ident_mut = format_ident!("{}_mut", vec_child.name());
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
pub fn #child_ident(&self) -> impl Iterator<Item = &#child_type_ident> {
|
|
||||||
self.#child_ident.iter().map(Box::as_ref)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn #child_ident_mut(&mut self) -> impl Iterator<Item = &mut child_type_ident> {
|
|
||||||
self.#child_ident.iter().map(Box::as_mut)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_member_child_accessors(member_child: &MemberChild) -> TokenStream {
|
|
||||||
let child_ident = format_ident!("{}", member_child.name());
|
|
||||||
match member_child.build() {
|
|
||||||
MemberChildBuild::Node(node_member_build) => {
|
|
||||||
let return_type_ident = format_ident!("{}", node_member_build.kind());
|
|
||||||
let child_ident_mut = format_ident!("{}_mut", member_child.name());
|
|
||||||
|
|
||||||
if member_child.optional() {
|
|
||||||
quote! {
|
|
||||||
pub fn #child_ident(&self) -> Option<&#return_type_ident> {
|
|
||||||
if let Some(#child_ident) = &self.#child_ident {
|
|
||||||
Some(#child_ident.as_ref())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn #child_ident_mut(&mut self) -> Option<&mut #return_type_ident> {
|
|
||||||
if let Some(#child_ident) = &mut self.#child_ident {
|
|
||||||
Some(#child_ident.as_mut())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
quote! {
|
|
||||||
pub fn #child_ident(&self) -> &#return_type_ident {
|
|
||||||
self.#child_ident.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn #child_ident_mut(&mut self) -> &mut #return_type_ident {
|
|
||||||
self.#child_ident.as_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MemberChildBuild::Boolean(_) => {
|
|
||||||
quote! {
|
|
||||||
pub fn #child_ident(&self) -> bool {
|
|
||||||
self.#child_ident
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_accessors(child: &StructChild) -> Option<TokenStream> {
|
|
||||||
match child {
|
|
||||||
StructChild::SkipChild(_) => None,
|
|
||||||
StructChild::VecChild(vec_child) => {
|
|
||||||
Some(make_vec_child_accessors(vec_child))
|
|
||||||
}
|
|
||||||
StructChild::MemberChild(member_child) => {
|
|
||||||
Some(make_member_child_accessors(member_child))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_member_ident(child: &StructChild) -> Option<Ident> {
|
|
||||||
match child {
|
|
||||||
StructChild::SkipChild(_) => None,
|
|
||||||
StructChild::VecChild(vec_child) => {
|
|
||||||
Some(format_ident!("{}", vec_child.name()))
|
|
||||||
},
|
|
||||||
StructChild::MemberChild(member_child) => {
|
|
||||||
Some(format_ident!("{}", member_child.name()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_vec_child_annotated_member(vec_child: &VecChild) -> TokenStream {
|
|
||||||
let child_ident = format_ident!("{}", vec_child.name());
|
|
||||||
let type_stream = match vec_child.build() {
|
|
||||||
VecChildBuild::String(_) => quote! { String },
|
|
||||||
VecChildBuild::Node(vec_child_node_build) => {
|
|
||||||
let type_ident = format_ident!("{}", vec_child_node_build.kind());
|
|
||||||
quote! { Box<#type_ident> }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#child_ident: Vec<#type_stream>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_member_child_type_ident(member_child: &MemberChild) -> TokenStream {
|
|
||||||
match member_child.build() {
|
|
||||||
MemberChildBuild::Node(node_member_build) => {
|
|
||||||
let type_ident = format_ident!("{}", node_member_build.kind());
|
|
||||||
quote! { #type_ident }
|
|
||||||
},
|
|
||||||
MemberChildBuild::Boolean(_) => {
|
|
||||||
quote! { bool }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_member_child_annotated_member(member_child: &MemberChild) -> TokenStream {
|
|
||||||
let child_name_ident = format_ident!("{}", member_child.name());
|
|
||||||
let type_ident = make_member_child_type_ident(member_child);
|
|
||||||
let type_stream = if member_child.optional() {
|
|
||||||
quote! { Option<#type_ident> }
|
|
||||||
} else {
|
|
||||||
type_ident
|
|
||||||
};
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#child_name_ident: #type_stream
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_annotated_member(child: &StructChild) -> Option<TokenStream> {
|
|
||||||
match child {
|
|
||||||
StructChild::SkipChild(_) => None,
|
|
||||||
StructChild::VecChild(vec_child) => Some(make_vec_child_annotated_member(vec_child)),
|
|
||||||
StructChild::MemberChild(member_child) => Some(make_member_child_annotated_member(member_child)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream {
|
|
||||||
let type_ident = format_ident!("{}", build_spec.build());
|
|
||||||
let annotated_members = build_spec.children()
|
|
||||||
.map(|child| {
|
|
||||||
make_annotated_member(child)
|
|
||||||
})
|
|
||||||
.filter(Option::is_some)
|
|
||||||
.map(Option::unwrap)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let member_names = build_spec.children()
|
|
||||||
.map(|child| {
|
|
||||||
make_member_ident(child)
|
|
||||||
})
|
|
||||||
.filter(Option::is_some)
|
|
||||||
.map(Option::unwrap)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let accessors = build_spec.children()
|
|
||||||
.map(|child| {
|
|
||||||
make_accessors(child)
|
|
||||||
})
|
|
||||||
.filter(Option::is_some)
|
|
||||||
.map(Option::unwrap)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
pub struct #type_ident {
|
|
||||||
#(#annotated_members),*
|
|
||||||
}
|
|
||||||
|
|
||||||
impl #type_ident {
|
|
||||||
pub fn new(#(#annotated_members),*) -> Self {
|
|
||||||
Self {
|
|
||||||
#(#member_names),*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#(#accessors)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
9
ast-generator/src/util.rs
Normal file
9
ast-generator/src/util.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
use convert_case::{Case, Casing};
|
||||||
|
|
||||||
|
pub fn make_build_fn_name(s: &str) -> String {
|
||||||
|
format!("build_{}", s.to_case(Case::Snake))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_build_pair(s: &str) -> String {
|
||||||
|
format!("{}_pair", s.to_case(Case::Snake))
|
||||||
|
}
|
||||||
4
build.rs
4
build.rs
@ -1,4 +1,4 @@
|
|||||||
use ast_generator::{get_build_specs, generate_files};
|
use ast_generator::{deserialize, generate_files};
|
||||||
use cst_test_generator::generate_test_files;
|
use cst_test_generator::generate_test_files;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@ -19,7 +19,7 @@ fn generate_ast_files(out_dir: &Path) -> io::Result<()> {
|
|||||||
fs::create_dir_all(&gen_ast_dir)?;
|
fs::create_dir_all(&gen_ast_dir)?;
|
||||||
|
|
||||||
let ast_yaml = include_str!("src/parser/ast.yaml");
|
let ast_yaml = include_str!("src/parser/ast.yaml");
|
||||||
let build_specs = get_build_specs(ast_yaml);
|
let build_specs = deserialize::deserialize_yaml_spec(ast_yaml);
|
||||||
let generated_files = generate_files(&build_specs);
|
let generated_files = generate_files(&build_specs);
|
||||||
for generated_file in &generated_files {
|
for generated_file in &generated_files {
|
||||||
let path = gen_ast_dir.join(&generated_file.name);
|
let path = gen_ast_dir.join(&generated_file.name);
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
fn main()
|
|
||||||
1 + 2 * 3 + 4
|
|
||||||
end
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
pub class Rc<T> : Drop, Copy
|
|
||||||
|
|
||||||
class Inner<T>(t: T)
|
|
||||||
mut count = 1
|
|
||||||
end
|
|
||||||
|
|
||||||
inner: &weak Inner = Null
|
|
||||||
|
|
||||||
pub ctor(t: T)
|
|
||||||
inner = Inner(t)
|
|
||||||
end
|
|
||||||
|
|
||||||
ctor(parent: &Self)
|
|
||||||
parent.inner++
|
|
||||||
inner = &weak parent.inner
|
|
||||||
end
|
|
||||||
|
|
||||||
pub fn copy() -> Self
|
|
||||||
Self(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
impl fn drop(self)
|
|
||||||
if inner.upgrade() is Some(inner) then
|
|
||||||
inner.count--
|
|
||||||
if inner.count == 0 then
|
|
||||||
drop inner
|
|
||||||
end
|
|
||||||
else
|
|
||||||
throw Exception('rc.inner could not be converted from a weak reference')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class Game(player: Player) end
|
|
||||||
|
|
||||||
class Player
|
|
||||||
pub mut game: &weak Game = Null
|
|
||||||
end
|
|
||||||
|
|
||||||
fn circular()
|
|
||||||
let player = Player()
|
|
||||||
let game = Game(player)
|
|
||||||
|
|
||||||
expectThrows(EmptyWeakReferenceException) {
|
|
||||||
player.game.upgrade()
|
|
||||||
}
|
|
||||||
|
|
||||||
player.game = &weak game
|
|
||||||
|
|
||||||
expectDoesNotThrow {
|
|
||||||
player.game.upgrade()
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
class Board
|
|
||||||
pub fn flip()
|
|
||||||
println 'Flipped!'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class ChessGame(pub board: rc Board) end
|
|
||||||
|
|
||||||
class ChessPlayer(pub board: rc Board) end
|
|
||||||
|
|
||||||
fn getGameAndPlayer() -> (ChessGame, ChessPlayer)
|
|
||||||
let board = rc Board() // Rc<Board> count is 1
|
|
||||||
let game = ChessGame(board) // Rc<Board> copied, count is 2
|
|
||||||
let player = ChessPlayer(board) // Rc<Board> copied, count is 3
|
|
||||||
(game, player) // initial Rc<Board> dropped before fn return, count now 2
|
|
||||||
end
|
|
||||||
|
|
||||||
fn playChess()
|
|
||||||
let (game, player) = getGameAndPlayer()
|
|
||||||
// Rc<Board> count is 2
|
|
||||||
let board = game.board // Copy, so count is now 3
|
|
||||||
board.flip()
|
|
||||||
drop board // count now 2
|
|
||||||
drop game // count now 1
|
|
||||||
drop player // count now 0, board memory finally dropped
|
|
||||||
end
|
|
||||||
@ -48,7 +48,7 @@ pub mod build {
|
|||||||
use pest::iterators::Pairs;
|
use pest::iterators::Pairs;
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/src/ast/build.rs"));
|
include!(concat!(env!("OUT_DIR"), "/src/ast/build.rs"));
|
||||||
|
|
||||||
pub fn build_ast(parsed_pairs: &mut Pairs<Rule>) -> Box<CompilationUnit> {
|
pub fn build_ast(parsed_pairs: &mut Pairs<Rule>) -> Box<CompilationUnit> {
|
||||||
let compilation_unit_pair = parsed_pairs.next().unwrap();
|
let compilation_unit_pair = parsed_pairs.next().unwrap();
|
||||||
Box::new(build_compilation_unit(compilation_unit_pair))
|
Box::new(build_compilation_unit(compilation_unit_pair))
|
||||||
@ -138,6 +138,6 @@ pub mod pretty_print {
|
|||||||
pub trait PrettyPrint {
|
pub trait PrettyPrint {
|
||||||
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()>;
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/src/ast/pretty_print.rs"));
|
include!(concat!(env!("OUT_DIR"), "/src/ast/pretty_print.rs"));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,6 +50,6 @@ fn main() {
|
|||||||
// eprintln!("{}", e)
|
// eprintln!("{}", e)
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
_ => todo!(),
|
_ => todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,21 +33,9 @@ $defs:
|
|||||||
- $ref: "#/$defs/EnumNodeDefinition"
|
- $ref: "#/$defs/EnumNodeDefinition"
|
||||||
- $ref: "#/$defs/LeafEnumNodeDefinition"
|
- $ref: "#/$defs/LeafEnumNodeDefinition"
|
||||||
- $ref: "#/$defs/ProductionDefinition"
|
- $ref: "#/$defs/ProductionDefinition"
|
||||||
- $ref: "#/$defs/NodeProductionDefinition"
|
|
||||||
- $ref: "#/$defs/PolymorphicTypeDefinition"
|
|
||||||
- $ref: "#/$defs/PolymorphicEnumLoopBuildDefinition"
|
|
||||||
- $ref: "#/$defs/PolymorphicPassThroughDefinition"
|
|
||||||
|
|
||||||
# Struct
|
# Four main types of nodes
|
||||||
StructNodeDefinition:
|
StructNodeDefinition:
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
struct:
|
|
||||||
$ref: "#/$defs/StructProps"
|
|
||||||
required:
|
|
||||||
- struct
|
|
||||||
StructProps:
|
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
description: A description of a Struct node to be built.
|
description: A description of a Struct node to be built.
|
||||||
@ -56,18 +44,56 @@ $defs:
|
|||||||
type: array
|
type: array
|
||||||
description: Ordered child fields for this node.
|
description: Ordered child fields for this node.
|
||||||
items:
|
items:
|
||||||
$ref: "#/$defs/StructChild"
|
$ref: "#/$defs/StructChildDefinition"
|
||||||
required:
|
required:
|
||||||
- children
|
- children
|
||||||
StructChild:
|
LeafStructNodeDefinition:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: A description of a Leaf-Struct node to be built.
|
||||||
|
properties:
|
||||||
|
members:
|
||||||
|
type: array
|
||||||
|
description: Ordered members for this node.
|
||||||
|
items:
|
||||||
|
$ref: "#/$defs/LeafStructMemberDefinition"
|
||||||
|
required:
|
||||||
|
- members
|
||||||
|
EnumNodeDefinition:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: A description of an Enum node to be built.
|
||||||
|
properties:
|
||||||
|
rules:
|
||||||
|
type: array
|
||||||
|
description: Alternative parse rules that build this node.
|
||||||
|
items:
|
||||||
|
$ref: "#/$defs/EnumChildDefinition"
|
||||||
|
required:
|
||||||
|
- rules
|
||||||
|
LeafEnumNodeDefinition:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: A description of a leaf-enum node to be built.
|
||||||
|
properties:
|
||||||
|
leaf_rules:
|
||||||
|
type: array
|
||||||
|
description: Alternative parse rules that build this node.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- leaf_rules
|
||||||
|
|
||||||
|
# Struct node children
|
||||||
|
StructChildDefinition:
|
||||||
description: |
|
description: |
|
||||||
A definition of a Struct node's child. Either a bare child name (string) in snake case, or an object. The former
|
A definition of a Struct node's child. Either a bare child name (string) in snake case, or an object. The former
|
||||||
is a shorthand where the child name and built type are the same; casing is automatically done. The latter allows
|
is a shorthand where the child name and built type are the same; casing is automatically done. The latter allows
|
||||||
further customization of the built child.
|
further customization of the built child.
|
||||||
oneOf:
|
oneOf:
|
||||||
- type: string
|
- type: string
|
||||||
- $ref: "#/$defs/StructChildHash"
|
- $ref: "#/$defs/StructChildDefinitionWrapper"
|
||||||
StructChildHash:
|
StructChildDefinitionWrapper:
|
||||||
type: object
|
type: object
|
||||||
description: Single-key object mapping the child-name to its advanced definition.
|
description: Single-key object mapping the child-name to its advanced definition.
|
||||||
minProperties: 1
|
minProperties: 1
|
||||||
@ -75,38 +101,28 @@ $defs:
|
|||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
patternProperties:
|
patternProperties:
|
||||||
"^[a-z][a-z0-9_]*$":
|
"^[a-z][a-z0-9_]*$":
|
||||||
$ref: "#/$defs/StructChildProps"
|
$ref: "#/$defs/StructChildAdvancedDefinition"
|
||||||
StructChildProps:
|
StructChildAdvancedDefinition:
|
||||||
type: object
|
type: object
|
||||||
description: One of skip/vec/single child specs.
|
description: One of skip/vec/single child specs.
|
||||||
oneOf:
|
oneOf:
|
||||||
- $ref: "#/$defs/StructChildSkipHash"
|
- $ref: "#/$defs/StructChildSkipChildDefinition"
|
||||||
- $ref: "#/$defs/StructChildVecHash"
|
- $ref: "#/$defs/StructChildVecChildDefinition"
|
||||||
- $ref: "#/$defs/StructChildMemberHash"
|
- $ref: "#/$defs/StructChildMemberDefinition"
|
||||||
StructChildSkipHash:
|
StructChildSkipChildDefinition:
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
skip:
|
|
||||||
$ref: "#/$defs/StructChildSkipProps"
|
|
||||||
required:
|
|
||||||
- skip
|
|
||||||
StructChildSkipProps:
|
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
description: A definition for a child rule that does nothing, i.e., is skipped.
|
description: A definition for a child rule that does nothing, i.e., is skipped.
|
||||||
properties:
|
properties:
|
||||||
rule:
|
rule:
|
||||||
type: string
|
type: string
|
||||||
|
skip:
|
||||||
|
type: boolean
|
||||||
|
const: true
|
||||||
required:
|
required:
|
||||||
- rule
|
- rule
|
||||||
StructChildVecHash:
|
- skip
|
||||||
type: object
|
StructChildVecChildDefinition:
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
vec:
|
|
||||||
$ref: "#/$defs/StructChildVecProps"
|
|
||||||
StructChildVecProps:
|
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
description: A definition for a child rule that can be matched multiple times.
|
description: A definition for a child rule that can be matched multiple times.
|
||||||
@ -115,17 +131,16 @@ $defs:
|
|||||||
type: string
|
type: string
|
||||||
kind:
|
kind:
|
||||||
type: string
|
type: string
|
||||||
|
enum:
|
||||||
|
- node # default
|
||||||
|
- string
|
||||||
|
vec:
|
||||||
|
type: boolean
|
||||||
|
const: true
|
||||||
required:
|
required:
|
||||||
- rule
|
- rule
|
||||||
StructChildMemberHash:
|
- vec
|
||||||
type: object
|
StructChildMemberDefinition:
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
member:
|
|
||||||
$ref: "#/$defs/StructChildMemberProps"
|
|
||||||
required:
|
|
||||||
- member
|
|
||||||
StructChildMemberProps:
|
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
@ -136,75 +151,18 @@ $defs:
|
|||||||
type: boolean
|
type: boolean
|
||||||
description: If true, this child will be stored as an Option.
|
description: If true, this child will be stored as an Option.
|
||||||
build:
|
build:
|
||||||
$ref: "#/$defs/StructChildMemberBuildProps"
|
oneOf:
|
||||||
StructChildMemberBuildProps:
|
- type: string
|
||||||
|
- $ref: "#/$defs/StructChildMemberBuildDefinition"
|
||||||
|
StructChildMemberBuildDefinition:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
description: A definition of what exactly to build for a given child rule.
|
||||||
oneOf:
|
oneOf:
|
||||||
- $ref: "#/$defs/StructChildMemberBuildNodeHash"
|
- $ref: "#/$defs/BuildNode"
|
||||||
- $ref: "#/$defs/StructChildMemberBuildBooleanHash"
|
- $ref: "#/$defs/BuildBoolean"
|
||||||
StructChildMemberBuildNodeHash:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
node:
|
|
||||||
$ref: "#/$defs/StructChildMemberBuildNodeProps"
|
|
||||||
required:
|
|
||||||
- node
|
|
||||||
StructChildMemberBuildNodeProps:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
description: A definition of a single-type child to build.
|
|
||||||
properties:
|
|
||||||
kind:
|
|
||||||
type: string
|
|
||||||
with:
|
|
||||||
type: string
|
|
||||||
or_else:
|
|
||||||
type: string
|
|
||||||
description: The method name to call upon the built-type if the rule is not found. Takes precedence over "or_else_default".
|
|
||||||
or_else_default:
|
|
||||||
type: boolean
|
|
||||||
description: Whether to call the default method on the built-type if the rule is not found.
|
|
||||||
StructChildMemberBuildBooleanHash:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
boolean:
|
|
||||||
$ref: "#/$defs/StructChildMemberBuildBooleanProps"
|
|
||||||
required:
|
|
||||||
- boolean
|
|
||||||
StructChildMemberBuildBooleanProps:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
description: A boolean member to be built.
|
|
||||||
properties:
|
|
||||||
on:
|
|
||||||
type: string
|
|
||||||
enum:
|
|
||||||
- rule_present
|
|
||||||
required:
|
|
||||||
- on
|
|
||||||
|
|
||||||
# Leaf Struct Node
|
# Leaf Struct children
|
||||||
LeafStructNodeDefinition:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
description: A description of a Leaf-Struct node to be built.
|
|
||||||
properties:
|
|
||||||
leaf_struct:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
members:
|
|
||||||
type: array
|
|
||||||
description: Ordered members for this node.
|
|
||||||
items:
|
|
||||||
$ref: "#/$defs/LeafStructMemberDefinition"
|
|
||||||
required:
|
|
||||||
- members
|
|
||||||
required:
|
|
||||||
- leaf_struct
|
|
||||||
LeafStructMemberDefinition:
|
LeafStructMemberDefinition:
|
||||||
type: object
|
type: object
|
||||||
description: Single-key object mapping the member-name to what is to be built by parsing the Parser Pair.
|
description: Single-key object mapping the member-name to what is to be built by parsing the Parser Pair.
|
||||||
@ -214,8 +172,8 @@ $defs:
|
|||||||
patternProperties:
|
patternProperties:
|
||||||
"^[a-z][a-z0-9_]*$":
|
"^[a-z][a-z0-9_]*$":
|
||||||
oneOf:
|
oneOf:
|
||||||
- $ref: "#/$defs/LeafStructBuildMember"
|
- $ref: "#/$defs/BuildMember"
|
||||||
LeafStructBuildMember:
|
BuildMember:
|
||||||
type: object
|
type: object
|
||||||
description: A specification for a member to build.
|
description: A specification for a member to build.
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
@ -223,28 +181,14 @@ $defs:
|
|||||||
kind:
|
kind:
|
||||||
enum:
|
enum:
|
||||||
- string
|
- string
|
||||||
|
from:
|
||||||
|
enum:
|
||||||
|
- whole_pair
|
||||||
required:
|
required:
|
||||||
- kind
|
- kind
|
||||||
|
- from
|
||||||
|
|
||||||
# Enum node
|
# Enum children
|
||||||
EnumNodeDefinition:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
description: A description of an Enum node to be built.
|
|
||||||
properties:
|
|
||||||
tree_enum:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
rules:
|
|
||||||
type: array
|
|
||||||
description: Alternative parse rules that build this node.
|
|
||||||
items:
|
|
||||||
$ref: "#/$defs/EnumChildDefinition"
|
|
||||||
required:
|
|
||||||
- rules
|
|
||||||
required:
|
|
||||||
- tree_enum
|
|
||||||
EnumChildDefinition:
|
EnumChildDefinition:
|
||||||
oneOf:
|
oneOf:
|
||||||
- type: string
|
- type: string
|
||||||
@ -257,263 +201,20 @@ $defs:
|
|||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
patternProperties:
|
patternProperties:
|
||||||
"^([A-Z][a-z]*)*$":
|
"^([A-Z][a-z]*)*$":
|
||||||
properties:
|
type: string
|
||||||
child:
|
enum:
|
||||||
type: boolean
|
- int
|
||||||
kind:
|
- long
|
||||||
enum:
|
- double
|
||||||
- int
|
- usize
|
||||||
- long
|
- string
|
||||||
- double
|
- boolean
|
||||||
- string
|
|
||||||
- boolean
|
|
||||||
|
|
||||||
# Leaf Enum
|
# Production definition
|
||||||
LeafEnumNodeDefinition:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
description: A description of a leaf-enum node to be built.
|
|
||||||
properties:
|
|
||||||
leaf_enum:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
rules:
|
|
||||||
type: array
|
|
||||||
description: Alternative parse rules that build this node.
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- rules
|
|
||||||
required:
|
|
||||||
- leaf_enum
|
|
||||||
|
|
||||||
# Polymorphic Type
|
|
||||||
PolymorphicTypeDefinition:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
polymorphic_type:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
variants:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/$defs/PolymorphicTypeVariantHash"
|
|
||||||
build:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
kind:
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- kind
|
|
||||||
required:
|
|
||||||
- variants
|
|
||||||
- build
|
|
||||||
required:
|
|
||||||
- polymorphic_type
|
|
||||||
PolymorphicTypeVariantHash:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
minProperties: 1
|
|
||||||
maxProperties: 1
|
|
||||||
patternProperties:
|
|
||||||
"^([A-Z][a-z]*)*$":
|
|
||||||
properties:
|
|
||||||
inner:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
kind:
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- kind
|
|
||||||
|
|
||||||
# Polymorphic Enum Loop Build
|
|
||||||
PolymorphicEnumLoopBuildDefinition:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
polymorphic_enum_loop_build:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
kind:
|
|
||||||
type: string
|
|
||||||
rules:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/$defs/PolymorphicEnumLoopBuildRule"
|
|
||||||
required:
|
|
||||||
- kind
|
|
||||||
- rules
|
|
||||||
required:
|
|
||||||
- polymorphic_enum_loop_build
|
|
||||||
PolymorphicEnumLoopBuildRule:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
minProperties: 1
|
|
||||||
maxProperties: 1
|
|
||||||
patternProperties:
|
|
||||||
"^([A-Z][a-z]*)*$":
|
|
||||||
type: object
|
|
||||||
oneOf:
|
|
||||||
- $ref: "#/$defs/PolymorphicEnumLoopBuildPassThrough"
|
|
||||||
- $ref: "#/$defs/PolymorphicEnumLoopBuildBuild"
|
|
||||||
PolymorphicEnumLoopBuildPassThrough:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
pass_through:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
kind:
|
|
||||||
type: string
|
|
||||||
with:
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- kind
|
|
||||||
- with
|
|
||||||
required:
|
|
||||||
- pass_through
|
|
||||||
PolymorphicEnumLoopBuildBuild:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
build:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
variant:
|
|
||||||
type: string
|
|
||||||
children:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/$defs/PolymorphicEnumLoopBuildBuildChild"
|
|
||||||
required:
|
|
||||||
- variant
|
|
||||||
- children
|
|
||||||
required:
|
|
||||||
- build
|
|
||||||
PolymorphicEnumLoopBuildBuildChild:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
minProperties: 1
|
|
||||||
maxProperties: 1
|
|
||||||
patternProperties:
|
|
||||||
"^[a-z][a-z_]*$":
|
|
||||||
type: object
|
|
||||||
oneOf:
|
|
||||||
- $ref: "#/$defs/PolymorphicEnumLoopBuildBuildUseCurrent"
|
|
||||||
- $ref: "#/$defs/PolymorphicEnumLoopBuildBuildOnEach"
|
|
||||||
PolymorphicEnumLoopBuildBuildUseCurrent:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
use_current:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
kind:
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- kind
|
|
||||||
required:
|
|
||||||
- use_current
|
|
||||||
PolymorphicEnumLoopBuildBuildOnEach:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
on_each:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
rule:
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- rule
|
|
||||||
required:
|
|
||||||
- on_each
|
|
||||||
|
|
||||||
# Polymorphic Pass Through
|
|
||||||
PolymorphicPassThroughDefinition:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
polymorphic_pass_through:
|
|
||||||
$ref: "#/$defs/PolymorphicPassThroughProps"
|
|
||||||
required:
|
|
||||||
- polymorphic_pass_through
|
|
||||||
PolymorphicPassThroughProps:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
build:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
kind:
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- kind
|
|
||||||
variants:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/$defs/PolymorphicPassThroughVariantHash"
|
|
||||||
required:
|
|
||||||
- build
|
|
||||||
- variants
|
|
||||||
PolymorphicPassThroughVariantHash:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
minProperties: 1
|
|
||||||
maxProperties: 1
|
|
||||||
patternProperties:
|
|
||||||
"^([A-Z][a-z]*)*$":
|
|
||||||
$ref: "#/$defs/PolymorphicPassThroughVariantProps"
|
|
||||||
PolymorphicPassThroughVariantProps:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
oneOf:
|
|
||||||
- $ref: "#/$defs/PolymorphicPassThroughVariantInner"
|
|
||||||
- $ref: "#/$defs/PolymorphicPassThroughVariantPassThrough"
|
|
||||||
PolymorphicPassThroughVariantInner:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
inner:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
kind:
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- kind
|
|
||||||
required:
|
|
||||||
- inner
|
|
||||||
PolymorphicPassThroughVariantPassThrough:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
pass_through:
|
|
||||||
type: object
|
|
||||||
additionalProperties: false
|
|
||||||
properties:
|
|
||||||
kind:
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- kind
|
|
||||||
required:
|
|
||||||
- pass_through
|
|
||||||
|
|
||||||
# Production
|
|
||||||
ProductionDefinition:
|
ProductionDefinition:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
production:
|
produce:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
kind:
|
kind:
|
||||||
@ -528,26 +229,28 @@ $defs:
|
|||||||
- string_inner
|
- string_inner
|
||||||
- whole_pair
|
- whole_pair
|
||||||
- parse_whole_pair
|
- parse_whole_pair
|
||||||
required:
|
|
||||||
- kind
|
|
||||||
required:
|
|
||||||
- production
|
|
||||||
|
|
||||||
# Node Production
|
# Common things to build
|
||||||
NodeProductionDefinition:
|
BuildNode:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
description: A definition of a single-type child to build.
|
||||||
properties:
|
properties:
|
||||||
node_production:
|
or_else:
|
||||||
type: object
|
type: string
|
||||||
additionalProperties: false
|
description: The method name to call upon the built-type if the rule is not found. Takes precedence over "or_else_default".
|
||||||
properties:
|
or_else_default:
|
||||||
kind:
|
type: boolean
|
||||||
type: string
|
description: Whether to call the default method on the built-type if the rule is not found.
|
||||||
with:
|
BuildBoolean:
|
||||||
type: string
|
type: object
|
||||||
required:
|
additionalProperties: false
|
||||||
- kind
|
description: A boolean member to be built.
|
||||||
- with
|
properties:
|
||||||
required:
|
kind:
|
||||||
- node_production
|
type: string
|
||||||
|
const: boolean
|
||||||
|
on:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- rule_present
|
||||||
1772
src/parser/ast.yaml
1772
src/parser/ast.yaml
File diff suppressed because it is too large
Load Diff
@ -620,7 +620,7 @@ OrExpression = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OrRhs = {
|
OrRhs = {
|
||||||
Or
|
Or
|
||||||
~ AndExpression
|
~ AndExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -641,7 +641,7 @@ ComparisonExpression = {
|
|||||||
|
|
||||||
ComparisonRhs = {
|
ComparisonRhs = {
|
||||||
ComparisonOperator
|
ComparisonOperator
|
||||||
~ ShiftExpression
|
~ Expression
|
||||||
}
|
}
|
||||||
|
|
||||||
ComparisonOperator = {
|
ComparisonOperator = {
|
||||||
@ -700,10 +700,14 @@ MultiplicativeOperator = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PrefixExpression = {
|
PrefixExpression = {
|
||||||
PrefixOperator*
|
PrefixOperators?
|
||||||
~ SuffixExpression
|
~ SuffixExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrefixOperators = {
|
||||||
|
PrefixOperator+
|
||||||
|
}
|
||||||
|
|
||||||
PrefixOperator = {
|
PrefixOperator = {
|
||||||
Spread
|
Spread
|
||||||
| Not
|
| Not
|
||||||
@ -712,7 +716,11 @@ PrefixOperator = {
|
|||||||
|
|
||||||
SuffixExpression = {
|
SuffixExpression = {
|
||||||
PrimaryExpression
|
PrimaryExpression
|
||||||
~ SuffixOperator*
|
~ SuffixOperators?
|
||||||
|
}
|
||||||
|
|
||||||
|
SuffixOperators = {
|
||||||
|
SuffixOperator+
|
||||||
}
|
}
|
||||||
|
|
||||||
SuffixOperator = {
|
SuffixOperator = {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// use crate::name_analysis::symbol::{FunctionSymbol, ParameterSymbol};
|
// use crate::name_analysis::symbol::{FunctionSymbol, ParameterSymbol};
|
||||||
// use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable};
|
// use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable};
|
||||||
//
|
//
|
||||||
// pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> {
|
// pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> {
|
||||||
// symbol_table.insert_function_symbol(
|
// symbol_table.insert_function_symbol(
|
||||||
// FunctionSymbol::new("std::core::println", "println", true, true, None)
|
// FunctionSymbol::new("std::core::println", "println", true, true, None)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user