Fill out build-fn generation for ast nodes.
This commit is contained in:
parent
968b950436
commit
b75e51ee41
@ -1,9 +1,9 @@
|
||||
use crate::spec::{
|
||||
BuildBooleanOn, ChildSpec, SingleBooleanChildToBuild, SingleChildToBuild,
|
||||
SingleTypeChildToBuild, StructBuildSpec, VecChild, VecChildToBuild,
|
||||
BooleanBuild, ChildSpec, SingleBooleanChildToBuild, SingleChildToBuild,
|
||||
SingleLiteralChildToBuild, SingleTypeChildToBuild, StructBuildSpec, VecChild, VecChildToBuild,
|
||||
};
|
||||
use convert_case::{Case, Casing};
|
||||
use proc_macro2::TokenStream;
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
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> {
|
||||
match child_spec {
|
||||
ChildSpec::SkipChild(_) => None,
|
||||
@ -50,10 +60,30 @@ fn make_child_holder(child_spec: &ChildSpec) -> Option<TokenStream> {
|
||||
SingleChildToBuild::Boolean(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 {
|
||||
match child_spec {
|
||||
ChildSpec::SkipChild(_) => quote! {},
|
||||
@ -78,10 +108,39 @@ fn make_match_action(child_spec: &ChildSpec) -> TokenStream {
|
||||
}
|
||||
SingleChildToBuild::Boolean(single_boolean_child) => {
|
||||
let child_name_ident = format_ident!("{}", single_boolean_child.var_name());
|
||||
match single_boolean_child.on() {
|
||||
BuildBooleanOn::RulePresent => quote! {
|
||||
match single_boolean_child.build() {
|
||||
BooleanBuild::RulePresent => quote! {
|
||||
#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());
|
||||
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]
|
||||
fn single_boolean_child_holder() {
|
||||
let single_boolean_child =
|
||||
SingleBooleanChildToBuild::new("test_child", BuildBooleanOn::RulePresent);
|
||||
SingleBooleanChildToBuild::new("test_child", BooleanBuild::RulePresent);
|
||||
assert_eq!(
|
||||
make_single_boolean_child_holder(&single_boolean_child).to_string(),
|
||||
quote! {
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
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 yaml_rust2::{Yaml, YamlLoader};
|
||||
|
||||
@ -51,14 +56,29 @@ fn get_single_child_to_build(
|
||||
.as_str()
|
||||
.map(|s| s.to_string())
|
||||
.unwrap_or(name.to_string());
|
||||
let on = build["on"].as_str().unwrap();
|
||||
if r#type.eq("boolean") && on.eq("rule_present") {
|
||||
match r#type {
|
||||
"boolean" => {
|
||||
if yaml_is_string(&build["on"], "rule_present") {
|
||||
SingleChildToBuild::Boolean(SingleBooleanChildToBuild::new(
|
||||
&var_name,
|
||||
BuildBooleanOn::RulePresent,
|
||||
BooleanBuild::RulePresent,
|
||||
))
|
||||
} else if yaml_is_string(&build["from"], "parse_whole_pair") {
|
||||
SingleChildToBuild::Boolean(SingleBooleanChildToBuild::new(
|
||||
&var_name,
|
||||
BooleanBuild::ParseWholePair,
|
||||
))
|
||||
} else {
|
||||
todo!("currently on boolean types with on: rule_present are supported")
|
||||
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 => {
|
||||
@ -160,11 +180,13 @@ fn get_leaf_enum_rules(rules: &Yaml) -> Vec<LeafEnumRule> {
|
||||
let (rule_as_string, rule_hash) = unwrap_single_member_hash(rule);
|
||||
if get_as_bool(&rule_hash["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)
|
||||
} 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 {
|
||||
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() {
|
||||
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() {
|
||||
// enum node
|
||||
let enum_rules = get_enum_rules(rules);
|
||||
|
||||
@ -88,7 +88,7 @@ impl LeafEnumBuildSpec {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
build: name.to_string(),
|
||||
rules
|
||||
rules,
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,14 +107,14 @@ impl LeafEnumBuildSpec {
|
||||
|
||||
pub struct LeafEnumRule {
|
||||
rule: String,
|
||||
build: LeafEnumRuleBuild
|
||||
build: LeafEnumRuleBuild,
|
||||
}
|
||||
|
||||
impl LeafEnumRule {
|
||||
pub fn new(rule: &str, build: LeafEnumRuleBuild) -> Self {
|
||||
Self {
|
||||
rule: rule.to_string(),
|
||||
build
|
||||
build,
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,12 +128,8 @@ impl LeafEnumRule {
|
||||
}
|
||||
|
||||
pub enum LeafEnumRuleBuild {
|
||||
EnumRule {
|
||||
rule: String,
|
||||
},
|
||||
Child {
|
||||
with: String
|
||||
}
|
||||
EnumRule { rule: String },
|
||||
Child { with: String },
|
||||
}
|
||||
|
||||
pub struct StructBuildSpec {
|
||||
@ -327,6 +323,10 @@ impl SingleChild {
|
||||
pub enum SingleChildToBuild {
|
||||
Type(SingleTypeChildToBuild),
|
||||
Boolean(SingleBooleanChildToBuild),
|
||||
Int(SingleLiteralChildToBuild),
|
||||
Long(SingleLiteralChildToBuild),
|
||||
Double(SingleLiteralChildToBuild),
|
||||
String(SingleLiteralChildToBuild),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -382,14 +382,14 @@ impl SingleTypeChildToBuild {
|
||||
#[derive(Debug)]
|
||||
pub struct SingleBooleanChildToBuild {
|
||||
var_name: String,
|
||||
on: BuildBooleanOn,
|
||||
build: BooleanBuild,
|
||||
}
|
||||
|
||||
impl SingleBooleanChildToBuild {
|
||||
pub fn new(var_name: &str, on: BuildBooleanOn) -> Self {
|
||||
pub fn new(var_name: &str, build: BooleanBuild) -> Self {
|
||||
Self {
|
||||
var_name: var_name.to_string(),
|
||||
on,
|
||||
build,
|
||||
}
|
||||
}
|
||||
|
||||
@ -397,12 +397,30 @@ impl SingleBooleanChildToBuild {
|
||||
&self.var_name
|
||||
}
|
||||
|
||||
pub fn on(&self) -> &BuildBooleanOn {
|
||||
&self.on
|
||||
pub fn build(&self) -> &BooleanBuild {
|
||||
&self.build
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BuildBooleanOn {
|
||||
pub enum BooleanBuild {
|
||||
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,
|
||||
);
|
||||
}
|
||||
_ => 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 node;
|
||||
pub mod pretty_print;
|
||||
|
||||
@ -625,20 +625,17 @@ IntLiteral:
|
||||
- literal:
|
||||
build:
|
||||
type: i32
|
||||
from: parse_number_base
|
||||
LongLiteral:
|
||||
children:
|
||||
- number_base
|
||||
- literal:
|
||||
build:
|
||||
type: i64
|
||||
from: parse_number_base
|
||||
DoubleLiteral:
|
||||
children:
|
||||
- literal:
|
||||
build:
|
||||
type: f64
|
||||
from: parse_whole_pair
|
||||
NumberBase:
|
||||
rules:
|
||||
- BinaryBase
|
||||
@ -649,7 +646,6 @@ DecimalBase:
|
||||
- literal:
|
||||
build:
|
||||
type: string
|
||||
from: whole_pair
|
||||
BinaryBase:
|
||||
children:
|
||||
- binary_digits
|
||||
@ -658,7 +654,6 @@ BinaryDigits:
|
||||
- literal:
|
||||
build:
|
||||
type: string
|
||||
from: whole_pair
|
||||
HexadecimalBase:
|
||||
children:
|
||||
- hexadecimal_digits
|
||||
@ -667,7 +662,6 @@ HexadecimalDigits:
|
||||
- literal:
|
||||
build:
|
||||
type: string
|
||||
from: whole_pair
|
||||
StringLiteral:
|
||||
rules:
|
||||
- SingleQuoteString
|
||||
@ -690,13 +684,11 @@ StringInner:
|
||||
- literal:
|
||||
build:
|
||||
type: string
|
||||
from: whole_pair
|
||||
DStringInner:
|
||||
children:
|
||||
- literal:
|
||||
build:
|
||||
type: string
|
||||
from: whole_pair
|
||||
DStringExpression:
|
||||
children:
|
||||
- expression
|
||||
@ -713,7 +705,6 @@ BacktickInner:
|
||||
- literal:
|
||||
build:
|
||||
type: string
|
||||
from: whole_pair
|
||||
BooleanLiteral:
|
||||
children:
|
||||
- literal:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user