WIP polymorphic building.
This commit is contained in:
parent
c94a698a52
commit
a7eabae3e3
@ -1,4 +1,4 @@
|
||||
use crate::spec::{BooleanChildToBuild, BuildSpec, EnumBuildSpec, EnumRule, EnumRuleChild, EnumRuleChildKind, EnumRuleNodeChild, LeafEnumBuildSpec, LeafEnumRule, LeafStructBuildSpec, LeafStructMember, LeafStructMemberKind, MemberChild, MemberChildToBuild, NodeChildToBuild, ProductionBuildSpec, ProductionKind, ProductionStringFrom, SkipChild, StructBuildSpec, StructChildSpec, VecChild, VecChildToBuild, VecNodeChildToBuild};
|
||||
use crate::spec::{BooleanChildToBuild, BuildSpec, EnumBuildSpec, EnumRule, EnumRuleChild, EnumRuleChildKind, EnumRuleNodeChild, LeafEnumBuildSpec, LeafEnumRule, LeafStructBuildSpec, LeafStructMember, LeafStructMemberKind, MemberChild, MemberChildToBuild, NodeChildToBuild, PolymorphicBuildSpec, PolymorphicEnumMember, ProductionBuildSpec, ProductionKind, ProductionStringFrom, SkipChild, StructBuildSpec, StructChildSpec, VecChild, VecChildToBuild, VecNodeChildToBuild};
|
||||
use convert_case::{Case, Casing};
|
||||
use yaml_rust2::{Yaml, YamlLoader};
|
||||
|
||||
@ -18,6 +18,26 @@ fn unwrap_single_member_hash(hash: &Yaml) -> (String, &Yaml) {
|
||||
(key_as_string, member_value)
|
||||
}
|
||||
|
||||
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) -> PolymorphicBuildSpec {
|
||||
let enum_members = deserialize_polymorphic_enum_members(&spec_props["enum_members"]);
|
||||
let build_kind = spec_props["build"]["kind"].as_str().unwrap();
|
||||
PolymorphicBuildSpec::new(name, enum_members, build_kind)
|
||||
}
|
||||
|
||||
fn deserialize_production_spec(rule: &str, production_yaml: &Yaml) -> ProductionBuildSpec {
|
||||
let kind = match production_yaml["kind"].as_str().unwrap() {
|
||||
"int" => ProductionKind::Int,
|
||||
@ -278,6 +298,8 @@ fn deserialize_build_spec(build_spec_name: &str, build_spec: &Yaml) -> BuildSpec
|
||||
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 {
|
||||
panic!("Expected a node spec for either a struct, leaf_struct, enum, leaf_enum node type, or a production type.");
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ pub mod deserialize;
|
||||
mod enum_build_fn;
|
||||
mod leaf_enum_build_fn;
|
||||
mod leaf_struct_build_fn;
|
||||
mod polymorphic_build_fn;
|
||||
mod production_build_fn;
|
||||
mod spec;
|
||||
mod struct_build_fn;
|
||||
@ -18,6 +19,7 @@ use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use spec::BuildSpec;
|
||||
use syn::File;
|
||||
use crate::polymorphic_build_fn::make_polymorphic_build_fn;
|
||||
|
||||
fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
|
||||
println!("*** BuildSpec ***");
|
||||
@ -38,7 +40,10 @@ fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
|
||||
);
|
||||
}
|
||||
BuildSpec::Production(production_build_spec) => {
|
||||
println!("Production Spec - rule: {}", production_build_spec.rule())
|
||||
println!("Production Spec - rule: {}", production_build_spec.rule());
|
||||
}
|
||||
BuildSpec::Polymorphic(polymorphic_build_spec) => {
|
||||
println!("Polymorphic Spec - name: {}", polymorphic_build_spec.name());
|
||||
}
|
||||
}
|
||||
println!("{:#?}", token_stream);
|
||||
@ -85,6 +90,11 @@ fn generate_build_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
||||
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
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let combined = quote! {
|
||||
|
||||
19
ast-generator/src/polymorphic_build_fn.rs
Normal file
19
ast-generator/src/polymorphic_build_fn.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use crate::spec::PolymorphicBuildSpec;
|
||||
use crate::token_stream_to_string;
|
||||
use crate::util::{make_build_fn_name, make_build_pair};
|
||||
|
||||
pub fn make_polymorphic_build_fn(build_spec: &PolymorphicBuildSpec) -> TokenStream {
|
||||
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 return_type_ident = format_ident!("{}", build_spec.name());
|
||||
let inner_build_fn_ident = format_ident!("{}", make_build_fn_name(build_spec.build_kind()));
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,7 @@ pub enum BuildSpec {
|
||||
Struct(StructBuildSpec),
|
||||
LeafStruct(LeafStructBuildSpec),
|
||||
Production(ProductionBuildSpec),
|
||||
Polymorphic(PolymorphicBuildSpec),
|
||||
}
|
||||
|
||||
// Enum build spec
|
||||
@ -423,3 +424,55 @@ pub enum ProductionStringFrom {
|
||||
StringInner,
|
||||
WholePair
|
||||
}
|
||||
|
||||
// Polymorphic build spec
|
||||
|
||||
pub struct PolymorphicBuildSpec {
|
||||
name: String,
|
||||
enum_members: Vec<Box<PolymorphicEnumMember>>,
|
||||
build_kind: String
|
||||
}
|
||||
|
||||
impl PolymorphicBuildSpec {
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,30 @@
|
||||
use crate::spec::{
|
||||
BooleanChildToBuild, BuildSpec, EnumBuildSpec, EnumRuleChildKind, LeafEnumBuildSpec,
|
||||
LeafStructBuildSpec, LeafStructMemberKind, MemberChildToBuild, NodeChildToBuild,
|
||||
StructBuildSpec, StructChildSpec, VecChild, VecChildToBuild,
|
||||
PolymorphicBuildSpec, StructBuildSpec, StructChildSpec, VecChild, VecChildToBuild,
|
||||
};
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
fn make_polymorphic_type(build_spec: &PolymorphicBuildSpec) -> 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()
|
||||
@ -348,5 +367,8 @@ pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||
Some(make_leaf_struct_type(leaf_struct_build_spec))
|
||||
}
|
||||
BuildSpec::Production(_) => None,
|
||||
BuildSpec::Polymorphic(polymorphic_build_spec) => {
|
||||
Some(make_polymorphic_type(polymorphic_build_spec))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,31 +42,6 @@ pub mod node {
|
||||
Self::new(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
pub fn unwrap_identifier(&self) -> &Identifier {
|
||||
let primary = self.ternary_expression()
|
||||
.or_expression()
|
||||
.left()
|
||||
.left()
|
||||
.left()
|
||||
.left()
|
||||
.left()
|
||||
.left()
|
||||
.right()
|
||||
.left();
|
||||
match primary {
|
||||
PrimaryExpression::FullyQualifiedName(fqn) => {
|
||||
if fqn.identifiers().count() == 1 {
|
||||
fqn.identifiers().next().unwrap()
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod build {
|
||||
@ -133,8 +108,6 @@ pub mod build {
|
||||
fn d_string_expression_simple() {
|
||||
let pair = parse(Rule::DStringExpression, "${thing}");
|
||||
let d_string_expression = build_d_string_expression(pair);
|
||||
let identifier = d_string_expression.expression().unwrap_identifier();
|
||||
assert_eq!("thing", identifier.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -564,8 +564,46 @@ ForStatement:
|
||||
|
||||
# Expressions
|
||||
Expression:
|
||||
children:
|
||||
- ternary_expression
|
||||
polymorphic_type:
|
||||
enum_members:
|
||||
- Ternary:
|
||||
inner:
|
||||
kind: TernaryExpression
|
||||
- Or:
|
||||
inner:
|
||||
kind: OrExpression
|
||||
- And:
|
||||
inner:
|
||||
kind: AndExpression
|
||||
- Comparison:
|
||||
inner:
|
||||
kind: ComparisonExpression
|
||||
- Shift:
|
||||
inner:
|
||||
kind: ShiftExpression
|
||||
- Additive:
|
||||
inner:
|
||||
kind: AdditiveExpression
|
||||
- Multiplicative:
|
||||
inner:
|
||||
kind: MultiplicativeExpression
|
||||
- Prefix:
|
||||
inner:
|
||||
kind: PrefixExpression
|
||||
- Suffix:
|
||||
inner:
|
||||
kind: SuffixExpression
|
||||
- Literal:
|
||||
inner:
|
||||
kind: Literal
|
||||
- Fqn:
|
||||
inner:
|
||||
kind: FullyQualifiedName
|
||||
- Closure:
|
||||
inner:
|
||||
kind: Closure
|
||||
build:
|
||||
kind: TernaryExpression
|
||||
TernaryExpression:
|
||||
children:
|
||||
- or_expression
|
||||
|
||||
Loading…
Reference in New Issue
Block a user