Much work on ast gen, leaf enums and leaf structs.
This commit is contained in:
parent
42cc6720d1
commit
434df5642a
@ -1,9 +1,4 @@
|
|||||||
use crate::spec::{
|
use crate::spec::{BooleanBuild, BuildSpec, ChildSpec, EnumBuildSpec, EnumRule, LeafEnumBuildSpec, LeafEnumRule, LeafEnumRuleBuild, LeafEnumRuleBuildChild, LeafStructBuildSpec, LeafStructChild, LeafStructChildType, SingleBooleanChildToBuild, SingleChild, SingleChildToBuild, SingleLiteralChildToBuild, SingleTypeChildToBuild, SkipChild, StructBuildSpec, VecChild, VecChildToBuild, VecTypeChildToBuild};
|
||||||
BooleanBuild, BuildSpec, ChildSpec, EnumBuildSpec, EnumRule, LeafEnumBuildSpec, LeafEnumRule,
|
|
||||||
LeafEnumRuleBuild, SingleBooleanChildToBuild, SingleChild, SingleChildToBuild,
|
|
||||||
SingleLiteralChildToBuild, SingleTypeChildToBuild, SkipChild, StructBuildSpec, VecChild,
|
|
||||||
VecChildToBuild, VecTypeChildToBuild,
|
|
||||||
};
|
|
||||||
use crate::util::make_build_fn_name;
|
use crate::util::make_build_fn_name;
|
||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
use yaml_rust2::{Yaml, YamlLoader};
|
use yaml_rust2::{Yaml, YamlLoader};
|
||||||
@ -177,9 +172,13 @@ fn get_leaf_enum_rules(rules: &Yaml) -> Vec<LeafEnumRule> {
|
|||||||
if rule.is_hash() {
|
if rule.is_hash() {
|
||||||
let (rule_as_string, rule_hash) = unwrap_single_member_hash(rule);
|
let (rule_as_string, rule_hash) = unwrap_single_member_hash(rule);
|
||||||
if get_as_bool(&rule_hash["child"]) {
|
if get_as_bool(&rule_hash["child"]) {
|
||||||
let build = LeafEnumRuleBuild::Child {
|
let build = LeafEnumRuleBuild::new(
|
||||||
with: make_build_fn_name(&rule_as_string),
|
&rule_as_string,
|
||||||
};
|
Some(LeafEnumRuleBuildChild::new(
|
||||||
|
&rule_as_string,
|
||||||
|
&make_build_fn_name(&rule_as_string),
|
||||||
|
)),
|
||||||
|
);
|
||||||
LeafEnumRule::new(&rule_as_string, build)
|
LeafEnumRule::new(&rule_as_string, build)
|
||||||
} else {
|
} else {
|
||||||
panic!(
|
panic!(
|
||||||
@ -188,9 +187,7 @@ fn get_leaf_enum_rules(rules: &Yaml) -> Vec<LeafEnumRule> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let rule_as_str = rule.as_str().unwrap();
|
let rule_as_str = rule.as_str().unwrap();
|
||||||
let build = LeafEnumRuleBuild::EnumRule {
|
let build = LeafEnumRuleBuild::new(rule_as_str, None);
|
||||||
rule: rule_as_str.to_string(),
|
|
||||||
};
|
|
||||||
LeafEnumRule::new(rule_as_str, build)
|
LeafEnumRule::new(rule_as_str, build)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -220,6 +217,20 @@ fn get_enum_rules(rule_specs: &Yaml) -> Vec<EnumRule> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_leaf_struct_child_specs(children: &Yaml) -> Vec<LeafStructChild> {
|
||||||
|
children.as_vec()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|child_spec| {
|
||||||
|
let (name, hash) = unwrap_single_member_hash(child_spec);
|
||||||
|
LeafStructChild::new(
|
||||||
|
&name,
|
||||||
|
LeafStructChildType::String
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
|
||||||
fn yaml_is_string(yaml: &Yaml, test: &str) -> bool {
|
fn yaml_is_string(yaml: &Yaml, test: &str) -> bool {
|
||||||
match yaml.as_str() {
|
match yaml.as_str() {
|
||||||
Some(s) => s == test,
|
Some(s) => s == test,
|
||||||
@ -233,7 +244,14 @@ fn deserialize_build_spec(build_spec_name: &Yaml, build_spec: &Yaml) -> BuildSpe
|
|||||||
let children = &build_spec["children"];
|
let children = &build_spec["children"];
|
||||||
let rules = &build_spec["rules"];
|
let rules = &build_spec["rules"];
|
||||||
|
|
||||||
if yaml_is_string(node_type, "struct") || children.is_array() {
|
if yaml_is_string(node_type, "leaf_struct") && children.is_array() {
|
||||||
|
let child_specs = get_leaf_struct_child_specs(children);
|
||||||
|
BuildSpec::LeafStruct(LeafStructBuildSpec::new(
|
||||||
|
build_spec_name_pascal,
|
||||||
|
build_spec_name_pascal,
|
||||||
|
child_specs,
|
||||||
|
))
|
||||||
|
} else if children.is_array() {
|
||||||
let child_specs = get_child_specs(children);
|
let child_specs = get_child_specs(children);
|
||||||
BuildSpec::Struct(StructBuildSpec::from_name(
|
BuildSpec::Struct(StructBuildSpec::from_name(
|
||||||
build_spec_name_pascal,
|
build_spec_name_pascal,
|
||||||
@ -250,7 +268,7 @@ fn deserialize_build_spec(build_spec_name: &Yaml, build_spec: &Yaml) -> BuildSpe
|
|||||||
let enum_rules = get_enum_rules(rules);
|
let enum_rules = get_enum_rules(rules);
|
||||||
BuildSpec::Enum(EnumBuildSpec::from_name(build_spec_name_pascal, enum_rules))
|
BuildSpec::Enum(EnumBuildSpec::from_name(build_spec_name_pascal, enum_rules))
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected a node spec for either a struct, enum, or leaf_enum node type.");
|
panic!("Expected a node spec for either a struct, leaf_struct, enum, leaf_enum node type.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,31 @@
|
|||||||
use proc_macro2::TokenStream;
|
|
||||||
use crate::spec::EnumBuildSpec;
|
use crate::spec::EnumBuildSpec;
|
||||||
|
use crate::util::{make_build_fn_name, make_build_pair};
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
pub fn make_enum_build_fn(enum_build_spec: &EnumBuildSpec) -> TokenStream {
|
pub fn make_enum_build_fn(enum_build_spec: &EnumBuildSpec) -> TokenStream {
|
||||||
todo!()
|
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 return_type_ident = format_ident!("{}", enum_build_spec.build());
|
||||||
|
|
||||||
|
let rule_branches = enum_build_spec
|
||||||
|
.rules()
|
||||||
|
.iter()
|
||||||
|
.map(|enum_rule| {
|
||||||
|
let rule_ident = format_ident!("{}", enum_rule.rule());
|
||||||
|
let build_rule_ident = format_ident!("{}", enum_rule.with());
|
||||||
|
quote! {
|
||||||
|
Rule::#rule_ident => #build_rule_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() {
|
||||||
|
#(#rule_branches),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
36
ast-generator/src/leaf_enum_build_fn.rs
Normal file
36
ast-generator/src/leaf_enum_build_fn.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
use crate::spec::LeafEnumBuildSpec;
|
||||||
|
use crate::util::{make_build_fn_name, make_build_pair};
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
pub fn make_leaf_enum_build_fn(leaf_enum_build_spec: &LeafEnumBuildSpec) -> TokenStream {
|
||||||
|
let build_fn_ident = format_ident!("{}", make_build_fn_name(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 rule_branches = leaf_enum_build_spec.rules()
|
||||||
|
.iter()
|
||||||
|
.map(|leaf_enum_rule| {
|
||||||
|
let rule_ident = format_ident!("{}", leaf_enum_rule.rule());
|
||||||
|
if leaf_enum_rule.build().child().is_some() {
|
||||||
|
let child_build_fn_ident = format_ident!("{}", leaf_enum_rule.build().child().unwrap().with());
|
||||||
|
quote! {
|
||||||
|
Rule::#rule_ident => #return_type_ident::#rule_ident(#child_build_fn_ident(inner_pair))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
Rule::#rule_ident => #return_type_ident::#rule_ident
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.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() {
|
||||||
|
#(#rule_branches),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
ast-generator/src/leaf_struct_build_fn.rs
Normal file
40
ast-generator/src/leaf_struct_build_fn.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
use crate::spec::{LeafStructBuildSpec, LeafStructChildType};
|
||||||
|
use crate::util::{make_build_fn_name, make_build_pair};
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
pub fn make_leaf_struct_build_fn(build_spec: &LeafStructBuildSpec) -> 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_builders = build_spec
|
||||||
|
.children()
|
||||||
|
.iter()
|
||||||
|
.map(|leaf_struct_child| {
|
||||||
|
let child_ident = format_ident!("{}", leaf_struct_child.name());
|
||||||
|
match leaf_struct_child.r#type() {
|
||||||
|
LeafStructChildType::String => {
|
||||||
|
quote! {
|
||||||
|
let #child_ident = #pair_ident.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let child_args = build_spec
|
||||||
|
.children()
|
||||||
|
.iter()
|
||||||
|
.map(|leaf_struct_child| format_ident!("{}", leaf_struct_child.name()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||||
|
#(#child_builders;)*
|
||||||
|
#return_type_ident::new(
|
||||||
|
#(#child_args,)*
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,17 +1,21 @@
|
|||||||
pub mod deserialize;
|
pub mod deserialize;
|
||||||
mod enum_build_fn;
|
mod enum_build_fn;
|
||||||
|
mod leaf_enum_build_fn;
|
||||||
|
mod leaf_struct_build_fn;
|
||||||
mod spec;
|
mod spec;
|
||||||
mod struct_build_fn;
|
mod struct_build_fn;
|
||||||
mod type_gen;
|
mod type_gen;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
use crate::enum_build_fn::make_enum_build_fn;
|
||||||
|
use crate::leaf_enum_build_fn::make_leaf_enum_build_fn;
|
||||||
use crate::struct_build_fn::make_struct_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;
|
||||||
use spec::BuildSpec;
|
use spec::BuildSpec;
|
||||||
use syn::File;
|
use syn::File;
|
||||||
use crate::enum_build_fn::make_enum_build_fn;
|
use crate::leaf_struct_build_fn::make_leaf_struct_build_fn;
|
||||||
|
|
||||||
fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
|
fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
|
||||||
println!("*** BuildSpec ***");
|
println!("*** BuildSpec ***");
|
||||||
@ -25,6 +29,9 @@ fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
|
|||||||
BuildSpec::Struct(struct_build_spec) => {
|
BuildSpec::Struct(struct_build_spec) => {
|
||||||
println!("Spec name: {}", struct_build_spec.name());
|
println!("Spec name: {}", struct_build_spec.name());
|
||||||
}
|
}
|
||||||
|
BuildSpec::LeafStruct(leaf_struct_build_spec) => {
|
||||||
|
println!("Spec name: {}", leaf_struct_build_spec.name());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
println!("{:#?}", token_stream);
|
println!("{:#?}", token_stream);
|
||||||
let parsed: File = syn::parse2(token_stream.clone()).unwrap();
|
let parsed: File = syn::parse2(token_stream.clone()).unwrap();
|
||||||
@ -51,12 +58,19 @@ fn generate_build_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
|||||||
stream
|
stream
|
||||||
}
|
}
|
||||||
BuildSpec::LeafEnum(leaf_enum_build_spec) => {
|
BuildSpec::LeafEnum(leaf_enum_build_spec) => {
|
||||||
todo!()
|
let stream = make_leaf_enum_build_fn(leaf_enum_build_spec);
|
||||||
|
debug_built_spec(build_spec, &stream);
|
||||||
|
stream
|
||||||
}
|
}
|
||||||
BuildSpec::Struct(struct_build_spec) => {
|
BuildSpec::Struct(struct_build_spec) => {
|
||||||
let struct_build_fn_stream = make_struct_build_fn(struct_build_spec);
|
let stream = make_struct_build_fn(struct_build_spec);
|
||||||
debug_built_spec(build_spec, &struct_build_fn_stream);
|
debug_built_spec(build_spec, &stream);
|
||||||
struct_build_fn_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
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@ -109,6 +123,7 @@ pub fn test_dump() -> String {
|
|||||||
debug_built_spec(build_spec, &struct_build_fn_stream);
|
debug_built_spec(build_spec, &struct_build_fn_stream);
|
||||||
streams.push(struct_build_fn_stream);
|
streams.push(struct_build_fn_stream);
|
||||||
}
|
}
|
||||||
|
BuildSpec::LeafStruct(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ pub enum BuildSpec {
|
|||||||
Enum(EnumBuildSpec),
|
Enum(EnumBuildSpec),
|
||||||
LeafEnum(LeafEnumBuildSpec),
|
LeafEnum(LeafEnumBuildSpec),
|
||||||
Struct(StructBuildSpec),
|
Struct(StructBuildSpec),
|
||||||
|
LeafStruct(LeafStructBuildSpec),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EnumBuildSpec {
|
pub struct EnumBuildSpec {
|
||||||
@ -127,9 +128,48 @@ impl LeafEnumRule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum LeafEnumRuleBuild {
|
pub struct LeafEnumRuleBuild {
|
||||||
EnumRule { rule: String },
|
rule: String,
|
||||||
Child { with: String },
|
child: Option<LeafEnumRuleBuildChild>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LeafEnumRuleBuild {
|
||||||
|
pub fn new(rule: &str, child: Option<LeafEnumRuleBuildChild>) -> Self {
|
||||||
|
Self {
|
||||||
|
rule: rule.to_string(),
|
||||||
|
child,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rule(&self) -> &str {
|
||||||
|
&self.rule
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn child(&self) -> Option<&LeafEnumRuleBuildChild> {
|
||||||
|
self.child.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LeafEnumRuleBuildChild {
|
||||||
|
build: String,
|
||||||
|
with: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LeafEnumRuleBuildChild {
|
||||||
|
pub fn new(build: &str, with: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
build: build.to_string(),
|
||||||
|
with: with.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(&self) -> &str {
|
||||||
|
&self.build
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with(&self) -> &str {
|
||||||
|
&self.with
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StructBuildSpec {
|
pub struct StructBuildSpec {
|
||||||
@ -440,3 +480,57 @@ impl SingleLiteralChildToBuild {
|
|||||||
&self.var_name
|
&self.var_name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct LeafStructBuildSpec {
|
||||||
|
name: String,
|
||||||
|
build: String,
|
||||||
|
children: Vec<LeafStructChild>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LeafStructBuildSpec {
|
||||||
|
pub fn new(name: &str, build: &str, children: Vec<LeafStructChild>) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
build: build.to_string(),
|
||||||
|
children,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(&self) -> &str {
|
||||||
|
&self.build
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn children(&self) -> &[LeafStructChild] {
|
||||||
|
&self.children
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LeafStructChild {
|
||||||
|
name: String,
|
||||||
|
r#type: LeafStructChildType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LeafStructChild {
|
||||||
|
pub fn new(name: &str, r#type: LeafStructChildType) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
r#type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn r#type(&self) -> &LeafStructChildType {
|
||||||
|
&self.r#type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum LeafStructChildType {
|
||||||
|
String,
|
||||||
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ use crate::spec::{
|
|||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
use crate::util::make_build_pair;
|
||||||
|
|
||||||
fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream {
|
fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream {
|
||||||
let (child_ident, child_type_ident) = match vec_child.build() {
|
let (child_ident, child_type_ident) = match vec_child.build() {
|
||||||
@ -226,8 +227,8 @@ fn make_return_value_stream(build_spec: &StructBuildSpec) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_struct_build_fn(build_spec: &StructBuildSpec) -> TokenStream {
|
pub fn make_struct_build_fn(build_spec: &StructBuildSpec) -> TokenStream {
|
||||||
let build_fn_ident = format_ident!("{}", build_spec.with());
|
let build_fn_ident = format_ident!("{}", build_spec.with()); // TODO: get rid of with
|
||||||
let pair_ident = format_ident!("{}_pair", build_spec.build().to_case(Case::Snake));
|
let pair_ident = format_ident!("{}", make_build_pair(build_spec.var_name())); // TODO: get rid of var_name
|
||||||
let return_type_ident = format_ident!("{}", build_spec.build());
|
let return_type_ident = format_ident!("{}", build_spec.build());
|
||||||
|
|
||||||
let child_holders = build_spec
|
let child_holders = build_spec
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
use crate::spec::{
|
use crate::spec::{
|
||||||
BuildSpec, ChildSpec, EnumBuildSpec, SingleBooleanChildToBuild, SingleChildToBuild,
|
BuildSpec, ChildSpec, EnumBuildSpec, LeafEnumBuildSpec, LeafStructBuildSpec,
|
||||||
SingleTypeChildToBuild, StructBuildSpec, VecChild, VecChildToBuild,
|
LeafStructChildType, SingleBooleanChildToBuild, SingleChildToBuild, SingleTypeChildToBuild,
|
||||||
|
StructBuildSpec, VecChild, VecChildToBuild,
|
||||||
};
|
};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
@ -25,6 +26,34 @@ fn make_enum_type(build_spec: &EnumBuildSpec) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_leaf_enum_type(build_spec: &LeafEnumBuildSpec) -> TokenStream {
|
||||||
|
let type_name_ident = format_ident!("{}", build_spec.build());
|
||||||
|
let children = build_spec
|
||||||
|
.rules()
|
||||||
|
.iter()
|
||||||
|
.map(|leaf_enum_rule| {
|
||||||
|
let rule_name_ident = format_ident!("{}", leaf_enum_rule.rule());
|
||||||
|
if leaf_enum_rule.build().child().is_some() {
|
||||||
|
let child_type_ident =
|
||||||
|
format_ident!("{}", leaf_enum_rule.build().child().unwrap().build());
|
||||||
|
quote! {
|
||||||
|
#rule_name_ident(#child_type_ident)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
#rule_name_ident
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
pub enum #type_name_ident {
|
||||||
|
#(#children),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_vec_child(
|
fn handle_vec_child(
|
||||||
vec_child: &VecChild,
|
vec_child: &VecChild,
|
||||||
member_names: &mut Vec<Ident>,
|
member_names: &mut Vec<Ident>,
|
||||||
@ -161,10 +190,70 @@ fn make_struct_type(build_spec: &StructBuildSpec) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_leaf_struct_type(build_spec: &LeafStructBuildSpec) -> TokenStream {
|
||||||
|
let type_ident = format_ident!("{}", build_spec.build());
|
||||||
|
|
||||||
|
let annotated_members = build_spec
|
||||||
|
.children()
|
||||||
|
.iter()
|
||||||
|
.map(|leaf_struct_child| {
|
||||||
|
let name_ident = format_ident!("{}", leaf_struct_child.name());
|
||||||
|
let type_ident = match leaf_struct_child.r#type() {
|
||||||
|
LeafStructChildType::String => format_ident!("{}", "String"),
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
#name_ident: #type_ident
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let member_names = build_spec
|
||||||
|
.children()
|
||||||
|
.iter()
|
||||||
|
.map(|leaf_struct_child| format_ident!("{}", leaf_struct_child.name()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let accessors = build_spec
|
||||||
|
.children()
|
||||||
|
.iter()
|
||||||
|
.map(|leaf_struct_child| {
|
||||||
|
let name_ident = format_ident!("{}", leaf_struct_child.name());
|
||||||
|
match leaf_struct_child.r#type() {
|
||||||
|
LeafStructChildType::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(#(#annotated_members),*) -> Self {
|
||||||
|
Self {
|
||||||
|
#(#member_names),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#(#accessors)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn make_type(build_spec: &BuildSpec) -> TokenStream {
|
pub fn make_type(build_spec: &BuildSpec) -> TokenStream {
|
||||||
match build_spec {
|
match build_spec {
|
||||||
BuildSpec::Enum(enum_build_spec) => make_enum_type(enum_build_spec),
|
BuildSpec::Enum(enum_build_spec) => make_enum_type(enum_build_spec),
|
||||||
BuildSpec::LeafEnum(leaf_enum_build_spec) => todo!(),
|
BuildSpec::LeafEnum(leaf_enum_build_spec) => make_leaf_enum_type(leaf_enum_build_spec),
|
||||||
BuildSpec::Struct(struct_build_spec) => make_struct_type(struct_build_spec),
|
BuildSpec::Struct(struct_build_spec) => make_struct_type(struct_build_spec),
|
||||||
|
BuildSpec::LeafStruct(leaf_struct_build_spec) => {
|
||||||
|
make_leaf_struct_type(leaf_struct_build_spec)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,3 +3,7 @@ use convert_case::{Case, Casing};
|
|||||||
pub fn make_build_fn_name(s: &str) -> String {
|
pub fn make_build_fn_name(s: &str) -> String {
|
||||||
format!("build_{}", s.to_case(Case::Snake))
|
format!("build_{}", s.to_case(Case::Snake))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn make_build_pair(s: &str) -> String {
|
||||||
|
format!("{}_pair", s.to_case(Case::Snake))
|
||||||
|
}
|
||||||
@ -15,7 +15,7 @@ Operator:
|
|||||||
- Subtract
|
- Subtract
|
||||||
- Multiply
|
- Multiply
|
||||||
- Divide
|
- Divide
|
||||||
- Moduolo
|
- Modulo
|
||||||
- LeftShift
|
- LeftShift
|
||||||
- RightShift
|
- RightShift
|
||||||
- Spread
|
- Spread
|
||||||
@ -29,11 +29,11 @@ Operator:
|
|||||||
|
|
||||||
# Names
|
# Names
|
||||||
Identifier:
|
Identifier:
|
||||||
|
type: leaf_struct
|
||||||
children:
|
children:
|
||||||
- name:
|
- name:
|
||||||
build:
|
build:
|
||||||
type: string
|
type: string
|
||||||
from: parse_whole_pair
|
|
||||||
FullyQualifiedName:
|
FullyQualifiedName:
|
||||||
children:
|
children:
|
||||||
- identifiers:
|
- identifiers:
|
||||||
@ -174,11 +174,13 @@ UseStatementPrefix:
|
|||||||
children:
|
children:
|
||||||
- identifier
|
- identifier
|
||||||
UseStatementSuffix:
|
UseStatementSuffix:
|
||||||
|
type: leaf_enum
|
||||||
rules:
|
rules:
|
||||||
- Identifier
|
- Identifier:
|
||||||
- rule: Star
|
child: true
|
||||||
build: UseStatementStarSuffix
|
- Star
|
||||||
- UseList
|
- UseList:
|
||||||
|
child: true
|
||||||
UseList:
|
UseList:
|
||||||
children:
|
children:
|
||||||
- identifiers:
|
- identifiers:
|
||||||
@ -463,8 +465,7 @@ Statement:
|
|||||||
- AssignmentStatement
|
- AssignmentStatement
|
||||||
- ExpressionStatement
|
- ExpressionStatement
|
||||||
- UseStatement
|
- UseStatement
|
||||||
- IfElseStatement
|
- IfStatement
|
||||||
- IfStatementStatement
|
|
||||||
- WhileStatement
|
- WhileStatement
|
||||||
- ForStatement
|
- ForStatement
|
||||||
VariableDeclaration:
|
VariableDeclaration:
|
||||||
@ -560,7 +561,7 @@ ForStatement:
|
|||||||
vec: true
|
vec: true
|
||||||
- end_kw:
|
- end_kw:
|
||||||
rule: End
|
rule: End
|
||||||
vec: true
|
skip: true
|
||||||
|
|
||||||
# Expressions
|
# Expressions
|
||||||
Expression:
|
Expression:
|
||||||
@ -612,6 +613,7 @@ ComparisonExpression:
|
|||||||
rule: Expression
|
rule: Expression
|
||||||
optional: true
|
optional: true
|
||||||
ComparisonOperator:
|
ComparisonOperator:
|
||||||
|
type: leaf_enum
|
||||||
rules:
|
rules:
|
||||||
- Greater
|
- Greater
|
||||||
- Less
|
- Less
|
||||||
@ -629,6 +631,7 @@ ShiftExpression:
|
|||||||
- right:
|
- right:
|
||||||
rule: Expression
|
rule: Expression
|
||||||
ShiftOperator:
|
ShiftOperator:
|
||||||
|
type: leaf_enum
|
||||||
rules:
|
rules:
|
||||||
- LeftShift
|
- LeftShift
|
||||||
- RightShift
|
- RightShift
|
||||||
@ -642,6 +645,11 @@ AdditiveExpression:
|
|||||||
- right:
|
- right:
|
||||||
rule: Expression
|
rule: Expression
|
||||||
optional: true
|
optional: true
|
||||||
|
AdditiveOperator:
|
||||||
|
type: leaf_enum
|
||||||
|
rules:
|
||||||
|
- Add
|
||||||
|
- Subtract
|
||||||
MultiplicativeExpression:
|
MultiplicativeExpression:
|
||||||
children:
|
children:
|
||||||
- left:
|
- left:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user