Fill out build-fn generation for ast nodes.
This commit is contained in:
parent
968b950436
commit
b75e51ee41
@ -1,9 +1,9 @@
|
|||||||
use crate::spec::{
|
use crate::spec::{
|
||||||
BuildBooleanOn, ChildSpec, SingleBooleanChildToBuild, SingleChildToBuild,
|
BooleanBuild, ChildSpec, SingleBooleanChildToBuild, SingleChildToBuild,
|
||||||
SingleTypeChildToBuild, StructBuildSpec, VecChild, VecChildToBuild,
|
SingleLiteralChildToBuild, SingleTypeChildToBuild, StructBuildSpec, VecChild, VecChildToBuild,
|
||||||
};
|
};
|
||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
pub fn make_build_fn_name(s: &str) -> String {
|
pub fn make_build_fn_name(s: &str) -> String {
|
||||||
@ -39,6 +39,16 @@ fn make_single_boolean_child_holder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_literal_child_holder(
|
||||||
|
literal_child: &SingleLiteralChildToBuild,
|
||||||
|
literal_type_ident: Ident,
|
||||||
|
) -> TokenStream {
|
||||||
|
let child_ident = format_ident!("{}", literal_child.var_name());
|
||||||
|
quote! {
|
||||||
|
let mut #child_ident: Option<#literal_type_ident> = None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn make_child_holder(child_spec: &ChildSpec) -> Option<TokenStream> {
|
fn make_child_holder(child_spec: &ChildSpec) -> Option<TokenStream> {
|
||||||
match child_spec {
|
match child_spec {
|
||||||
ChildSpec::SkipChild(_) => None,
|
ChildSpec::SkipChild(_) => None,
|
||||||
@ -50,10 +60,30 @@ fn make_child_holder(child_spec: &ChildSpec) -> Option<TokenStream> {
|
|||||||
SingleChildToBuild::Boolean(boolean_child) => {
|
SingleChildToBuild::Boolean(boolean_child) => {
|
||||||
Some(make_single_boolean_child_holder(boolean_child))
|
Some(make_single_boolean_child_holder(boolean_child))
|
||||||
}
|
}
|
||||||
|
SingleChildToBuild::Int(literal_child) => Some(make_literal_child_holder(
|
||||||
|
literal_child,
|
||||||
|
format_ident!("i32"),
|
||||||
|
)),
|
||||||
|
SingleChildToBuild::Long(literal_child) => Some(make_literal_child_holder(
|
||||||
|
literal_child,
|
||||||
|
format_ident!("i64"),
|
||||||
|
)),
|
||||||
|
SingleChildToBuild::Double(literal_child) => Some(make_literal_child_holder(
|
||||||
|
literal_child,
|
||||||
|
format_ident!("f64"),
|
||||||
|
)),
|
||||||
|
SingleChildToBuild::String(literal_child) => Some(make_literal_child_holder(
|
||||||
|
literal_child,
|
||||||
|
format_ident!("String"),
|
||||||
|
)),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_literal_child_ident(literal_child: &SingleLiteralChildToBuild) -> Ident {
|
||||||
|
format_ident!("{}", literal_child.var_name())
|
||||||
|
}
|
||||||
|
|
||||||
fn make_match_action(child_spec: &ChildSpec) -> TokenStream {
|
fn make_match_action(child_spec: &ChildSpec) -> TokenStream {
|
||||||
match child_spec {
|
match child_spec {
|
||||||
ChildSpec::SkipChild(_) => quote! {},
|
ChildSpec::SkipChild(_) => quote! {},
|
||||||
@ -78,10 +108,39 @@ fn make_match_action(child_spec: &ChildSpec) -> TokenStream {
|
|||||||
}
|
}
|
||||||
SingleChildToBuild::Boolean(single_boolean_child) => {
|
SingleChildToBuild::Boolean(single_boolean_child) => {
|
||||||
let child_name_ident = format_ident!("{}", single_boolean_child.var_name());
|
let child_name_ident = format_ident!("{}", single_boolean_child.var_name());
|
||||||
match single_boolean_child.on() {
|
match single_boolean_child.build() {
|
||||||
BuildBooleanOn::RulePresent => quote! {
|
BooleanBuild::RulePresent => quote! {
|
||||||
#child_name_ident = true
|
#child_name_ident = true
|
||||||
},
|
},
|
||||||
|
BooleanBuild::ParseWholePair => quote! {
|
||||||
|
#child_name_ident = Some(inner_pair.as_str().parse().unwrap())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SingleChildToBuild::Int(literal_child) => {
|
||||||
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
|
quote! {
|
||||||
|
#child_ident = Some(inner_pair.as_str().parse().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SingleChildToBuild::Long(literal_child) => {
|
||||||
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
|
quote! {
|
||||||
|
let as_string = inner_pair.as_str();
|
||||||
|
let without_el = &as_string[0..(as_string.len() - 1)];
|
||||||
|
#child_ident = Some(without_el.parse().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SingleChildToBuild::Double(literal_child) => {
|
||||||
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
|
quote! {
|
||||||
|
#child_ident = Some(inner_pair.as_str().parse().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SingleChildToBuild::String(literal_child) => {
|
||||||
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
|
quote! {
|
||||||
|
#child_ident = Some(inner_pair.as_str().to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -133,6 +192,22 @@ fn make_child_arg(child_spec: &ChildSpec) -> Option<TokenStream> {
|
|||||||
let child_ident = format_ident!("{}", single_boolean_child.var_name());
|
let child_ident = format_ident!("{}", single_boolean_child.var_name());
|
||||||
Some(quote! { #child_ident })
|
Some(quote! { #child_ident })
|
||||||
}
|
}
|
||||||
|
SingleChildToBuild::Int(literal_child) => {
|
||||||
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
|
Some(quote! { #child_ident.unwrap() })
|
||||||
|
}
|
||||||
|
SingleChildToBuild::Long(literal_child) => {
|
||||||
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
|
Some(quote! { #child_ident.unwrap() })
|
||||||
|
},
|
||||||
|
SingleChildToBuild::Double(literal_child) => {
|
||||||
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
|
Some(quote! { #child_ident.unwrap() })
|
||||||
|
}
|
||||||
|
SingleChildToBuild::String(literal_child) => {
|
||||||
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
|
Some(quote! { #child_ident.unwrap() })
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,7 +309,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn single_boolean_child_holder() {
|
fn single_boolean_child_holder() {
|
||||||
let single_boolean_child =
|
let single_boolean_child =
|
||||||
SingleBooleanChildToBuild::new("test_child", BuildBooleanOn::RulePresent);
|
SingleBooleanChildToBuild::new("test_child", BooleanBuild::RulePresent);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
make_single_boolean_child_holder(&single_boolean_child).to_string(),
|
make_single_boolean_child_holder(&single_boolean_child).to_string(),
|
||||||
quote! {
|
quote! {
|
||||||
|
|||||||
@ -1,5 +1,10 @@
|
|||||||
use crate::build_fn_gen::make_build_fn_name;
|
use crate::build_fn_gen::make_build_fn_name;
|
||||||
use crate::spec::{BuildBooleanOn, BuildSpec, ChildSpec, EnumBuildSpec, EnumRule, LeafEnumBuildSpec, LeafEnumRule, LeafEnumRuleBuild, SingleBooleanChildToBuild, SingleChild, SingleChildToBuild, SingleTypeChildToBuild, SkipChild, StructBuildSpec, VecChild, VecChildToBuild, VecTypeChildToBuild};
|
use crate::spec::{
|
||||||
|
BooleanBuild, BuildSpec, ChildSpec, EnumBuildSpec, EnumRule, LeafEnumBuildSpec, LeafEnumRule,
|
||||||
|
LeafEnumRuleBuild, SingleBooleanChildToBuild, SingleChild, SingleChildToBuild,
|
||||||
|
SingleLiteralChildToBuild, SingleTypeChildToBuild, SkipChild, StructBuildSpec, VecChild,
|
||||||
|
VecChildToBuild, VecTypeChildToBuild,
|
||||||
|
};
|
||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
use yaml_rust2::{Yaml, YamlLoader};
|
use yaml_rust2::{Yaml, YamlLoader};
|
||||||
|
|
||||||
@ -51,14 +56,29 @@ fn get_single_child_to_build(
|
|||||||
.as_str()
|
.as_str()
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.unwrap_or(name.to_string());
|
.unwrap_or(name.to_string());
|
||||||
let on = build["on"].as_str().unwrap();
|
match r#type {
|
||||||
if r#type.eq("boolean") && on.eq("rule_present") {
|
"boolean" => {
|
||||||
SingleChildToBuild::Boolean(SingleBooleanChildToBuild::new(
|
if yaml_is_string(&build["on"], "rule_present") {
|
||||||
&var_name,
|
SingleChildToBuild::Boolean(SingleBooleanChildToBuild::new(
|
||||||
BuildBooleanOn::RulePresent,
|
&var_name,
|
||||||
))
|
BooleanBuild::RulePresent,
|
||||||
} else {
|
))
|
||||||
todo!("currently on boolean types with on: rule_present are supported")
|
} else if yaml_is_string(&build["from"], "parse_whole_pair") {
|
||||||
|
SingleChildToBuild::Boolean(SingleBooleanChildToBuild::new(
|
||||||
|
&var_name,
|
||||||
|
BooleanBuild::ParseWholePair,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
panic!("invalid build on/from with type boolean");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"i32" => SingleChildToBuild::Int(SingleLiteralChildToBuild::new(&var_name)),
|
||||||
|
"i64" => SingleChildToBuild::Long(SingleLiteralChildToBuild::new(&var_name)),
|
||||||
|
"f64" => SingleChildToBuild::Double(SingleLiteralChildToBuild::new(&var_name)),
|
||||||
|
"string" => {
|
||||||
|
SingleChildToBuild::String(SingleLiteralChildToBuild::new(&var_name))
|
||||||
|
}
|
||||||
|
_ => panic!("unsupported build type: {}", r#type),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@ -160,11 +180,13 @@ fn get_leaf_enum_rules(rules: &Yaml) -> Vec<LeafEnumRule> {
|
|||||||
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::Child {
|
||||||
with: make_build_fn_name(&rule_as_string)
|
with: make_build_fn_name(&rule_as_string),
|
||||||
};
|
};
|
||||||
LeafEnumRule::new(&rule_as_string, build)
|
LeafEnumRule::new(&rule_as_string, build)
|
||||||
} else {
|
} else {
|
||||||
panic!("if a leaf_enum rule is a hash, its child prop must be present and true");
|
panic!(
|
||||||
|
"if a leaf_enum rule is a hash, its child prop must be present and true"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let rule_as_str = rule.as_str().unwrap();
|
let rule_as_str = rule.as_str().unwrap();
|
||||||
@ -221,7 +243,10 @@ fn deserialize_build_spec(build_spec_name: &Yaml, build_spec: &Yaml) -> BuildSpe
|
|||||||
))
|
))
|
||||||
} else if yaml_is_string(node_type, "leaf_enum") && rules.is_array() {
|
} else if yaml_is_string(node_type, "leaf_enum") && rules.is_array() {
|
||||||
let leaf_enum_rules = get_leaf_enum_rules(rules);
|
let leaf_enum_rules = get_leaf_enum_rules(rules);
|
||||||
BuildSpec::LeafEnum(LeafEnumBuildSpec::from_name(build_spec_name_pascal, leaf_enum_rules))
|
BuildSpec::LeafEnum(LeafEnumBuildSpec::from_name(
|
||||||
|
build_spec_name_pascal,
|
||||||
|
leaf_enum_rules,
|
||||||
|
))
|
||||||
} else if rules.is_array() {
|
} else if rules.is_array() {
|
||||||
// enum node
|
// enum node
|
||||||
let enum_rules = get_enum_rules(rules);
|
let enum_rules = get_enum_rules(rules);
|
||||||
|
|||||||
@ -88,7 +88,7 @@ impl LeafEnumBuildSpec {
|
|||||||
Self {
|
Self {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
build: name.to_string(),
|
build: name.to_string(),
|
||||||
rules
|
rules,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,14 +107,14 @@ impl LeafEnumBuildSpec {
|
|||||||
|
|
||||||
pub struct LeafEnumRule {
|
pub struct LeafEnumRule {
|
||||||
rule: String,
|
rule: String,
|
||||||
build: LeafEnumRuleBuild
|
build: LeafEnumRuleBuild,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LeafEnumRule {
|
impl LeafEnumRule {
|
||||||
pub fn new(rule: &str, build: LeafEnumRuleBuild) -> Self {
|
pub fn new(rule: &str, build: LeafEnumRuleBuild) -> Self {
|
||||||
Self {
|
Self {
|
||||||
rule: rule.to_string(),
|
rule: rule.to_string(),
|
||||||
build
|
build,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,12 +128,8 @@ impl LeafEnumRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub enum LeafEnumRuleBuild {
|
pub enum LeafEnumRuleBuild {
|
||||||
EnumRule {
|
EnumRule { rule: String },
|
||||||
rule: String,
|
Child { with: String },
|
||||||
},
|
|
||||||
Child {
|
|
||||||
with: String
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StructBuildSpec {
|
pub struct StructBuildSpec {
|
||||||
@ -327,6 +323,10 @@ impl SingleChild {
|
|||||||
pub enum SingleChildToBuild {
|
pub enum SingleChildToBuild {
|
||||||
Type(SingleTypeChildToBuild),
|
Type(SingleTypeChildToBuild),
|
||||||
Boolean(SingleBooleanChildToBuild),
|
Boolean(SingleBooleanChildToBuild),
|
||||||
|
Int(SingleLiteralChildToBuild),
|
||||||
|
Long(SingleLiteralChildToBuild),
|
||||||
|
Double(SingleLiteralChildToBuild),
|
||||||
|
String(SingleLiteralChildToBuild),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -382,14 +382,14 @@ impl SingleTypeChildToBuild {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SingleBooleanChildToBuild {
|
pub struct SingleBooleanChildToBuild {
|
||||||
var_name: String,
|
var_name: String,
|
||||||
on: BuildBooleanOn,
|
build: BooleanBuild,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SingleBooleanChildToBuild {
|
impl SingleBooleanChildToBuild {
|
||||||
pub fn new(var_name: &str, on: BuildBooleanOn) -> Self {
|
pub fn new(var_name: &str, build: BooleanBuild) -> Self {
|
||||||
Self {
|
Self {
|
||||||
var_name: var_name.to_string(),
|
var_name: var_name.to_string(),
|
||||||
on,
|
build,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,12 +397,30 @@ impl SingleBooleanChildToBuild {
|
|||||||
&self.var_name
|
&self.var_name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on(&self) -> &BuildBooleanOn {
|
pub fn build(&self) -> &BooleanBuild {
|
||||||
&self.on
|
&self.build
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum BuildBooleanOn {
|
pub enum BooleanBuild {
|
||||||
RulePresent,
|
RulePresent,
|
||||||
|
ParseWholePair,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SingleLiteralChildToBuild {
|
||||||
|
var_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SingleLiteralChildToBuild {
|
||||||
|
pub fn new(var_name: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
var_name: var_name.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn var_name(&self) -> &str {
|
||||||
|
&self.var_name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -136,6 +136,7 @@ fn make_struct_type(build_spec: &StructBuildSpec) -> TokenStream {
|
|||||||
&mut accessors,
|
&mut accessors,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
_ => todo!()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
include!(concat!(env!("OUT_DIR"), "/src/ast/build.rs"));
|
|
||||||
@ -1,4 +1,10 @@
|
|||||||
pub mod build;
|
pub mod build {
|
||||||
|
//noinspection RsUnusedImport
|
||||||
|
use crate::parser::Rule;
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/src/ast/build.rs"));
|
||||||
|
}
|
||||||
|
|
||||||
pub mod children;
|
pub mod children;
|
||||||
pub mod node;
|
pub mod node;
|
||||||
pub mod pretty_print;
|
pub mod pretty_print;
|
||||||
|
|||||||
@ -625,20 +625,17 @@ IntLiteral:
|
|||||||
- literal:
|
- literal:
|
||||||
build:
|
build:
|
||||||
type: i32
|
type: i32
|
||||||
from: parse_number_base
|
|
||||||
LongLiteral:
|
LongLiteral:
|
||||||
children:
|
children:
|
||||||
- number_base
|
- number_base
|
||||||
- literal:
|
- literal:
|
||||||
build:
|
build:
|
||||||
type: i64
|
type: i64
|
||||||
from: parse_number_base
|
|
||||||
DoubleLiteral:
|
DoubleLiteral:
|
||||||
children:
|
children:
|
||||||
- literal:
|
- literal:
|
||||||
build:
|
build:
|
||||||
type: f64
|
type: f64
|
||||||
from: parse_whole_pair
|
|
||||||
NumberBase:
|
NumberBase:
|
||||||
rules:
|
rules:
|
||||||
- BinaryBase
|
- BinaryBase
|
||||||
@ -649,7 +646,6 @@ DecimalBase:
|
|||||||
- literal:
|
- literal:
|
||||||
build:
|
build:
|
||||||
type: string
|
type: string
|
||||||
from: whole_pair
|
|
||||||
BinaryBase:
|
BinaryBase:
|
||||||
children:
|
children:
|
||||||
- binary_digits
|
- binary_digits
|
||||||
@ -658,7 +654,6 @@ BinaryDigits:
|
|||||||
- literal:
|
- literal:
|
||||||
build:
|
build:
|
||||||
type: string
|
type: string
|
||||||
from: whole_pair
|
|
||||||
HexadecimalBase:
|
HexadecimalBase:
|
||||||
children:
|
children:
|
||||||
- hexadecimal_digits
|
- hexadecimal_digits
|
||||||
@ -667,7 +662,6 @@ HexadecimalDigits:
|
|||||||
- literal:
|
- literal:
|
||||||
build:
|
build:
|
||||||
type: string
|
type: string
|
||||||
from: whole_pair
|
|
||||||
StringLiteral:
|
StringLiteral:
|
||||||
rules:
|
rules:
|
||||||
- SingleQuoteString
|
- SingleQuoteString
|
||||||
@ -690,13 +684,11 @@ StringInner:
|
|||||||
- literal:
|
- literal:
|
||||||
build:
|
build:
|
||||||
type: string
|
type: string
|
||||||
from: whole_pair
|
|
||||||
DStringInner:
|
DStringInner:
|
||||||
children:
|
children:
|
||||||
- literal:
|
- literal:
|
||||||
build:
|
build:
|
||||||
type: string
|
type: string
|
||||||
from: whole_pair
|
|
||||||
DStringExpression:
|
DStringExpression:
|
||||||
children:
|
children:
|
||||||
- expression
|
- expression
|
||||||
@ -713,7 +705,6 @@ BacktickInner:
|
|||||||
- literal:
|
- literal:
|
||||||
build:
|
build:
|
||||||
type: string
|
type: string
|
||||||
from: whole_pair
|
|
||||||
BooleanLiteral:
|
BooleanLiteral:
|
||||||
children:
|
children:
|
||||||
- literal:
|
- literal:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user