Add polymorphic build types gen.
This commit is contained in:
parent
a7eabae3e3
commit
7399a8748c
@ -1,4 +1,4 @@
|
||||
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 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};
|
||||
|
||||
@ -18,7 +18,87 @@ 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>> {
|
||||
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()
|
||||
@ -32,14 +112,18 @@ fn deserialize_polymorphic_enum_members(enum_members_yaml: &Yaml) -> Vec<Box<Pol
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn deserialize_polymorphic_spec(name: &str, spec_props: &Yaml) -> PolymorphicBuildSpec {
|
||||
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();
|
||||
PolymorphicBuildSpec::new(name, enum_members, build_kind)
|
||||
PolymorphicTypeBuildSpec::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() {
|
||||
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,
|
||||
@ -48,11 +132,18 @@ fn deserialize_production_spec(rule: &str, production_yaml: &Yaml) -> Production
|
||||
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()),
|
||||
_ => panic!(
|
||||
"invalid from: {}",
|
||||
production_yaml["from"].as_str().unwrap()
|
||||
),
|
||||
};
|
||||
ProductionKind::String(from)
|
||||
},
|
||||
_ => panic!("invalid kind: {}", production_yaml["kind"].as_str().unwrap()),
|
||||
}
|
||||
_ => panic!(
|
||||
"invalid kind: {}",
|
||||
production_yaml["kind"].as_str().unwrap()
|
||||
),
|
||||
}
|
||||
};
|
||||
ProductionBuildSpec::new(rule, kind)
|
||||
}
|
||||
@ -66,9 +157,7 @@ fn deserialize_leaf_enum_rules(rules_yaml: &Yaml) -> Vec<Box<LeafEnumRule>> {
|
||||
.as_vec()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|rule_yaml| {
|
||||
deserialize_leaf_enum_rule(rule_yaml)
|
||||
})
|
||||
.map(|rule_yaml| deserialize_leaf_enum_rule(rule_yaml))
|
||||
.collect()
|
||||
}
|
||||
|
||||
@ -83,16 +172,19 @@ fn deserialize_enum_rule_custom_child(rule_props: &Yaml) -> Option<Box<EnumRuleC
|
||||
"usize" => EnumRuleChildKind::USize,
|
||||
"string" => EnumRuleChildKind::String,
|
||||
"boolean" => EnumRuleChildKind::Boolean,
|
||||
_ => panic!("unsupported enum rule kind: {}", rule_props["kind"].as_str().unwrap()),
|
||||
_ => 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)),
|
||||
)))
|
||||
Box::new(EnumRuleChild::new(Box::new(EnumRuleChildKind::Node(
|
||||
EnumRuleNodeChild::new(rule),
|
||||
))))
|
||||
}
|
||||
|
||||
fn deserialize_enum_rule(rule_yaml: &Yaml) -> Box<EnumRule> {
|
||||
@ -100,7 +192,7 @@ fn deserialize_enum_rule(rule_yaml: &Yaml) -> Box<EnumRule> {
|
||||
let (rule, rule_props) = unwrap_single_member_hash(rule_yaml);
|
||||
Box::new(EnumRule::new(
|
||||
&rule,
|
||||
deserialize_enum_rule_custom_child(rule_props)
|
||||
deserialize_enum_rule_custom_child(rule_props),
|
||||
))
|
||||
} else {
|
||||
let rule_as_str = rule_yaml.as_str().unwrap();
|
||||
@ -184,7 +276,9 @@ fn deserialize_member_child_to_build(
|
||||
}
|
||||
} else {
|
||||
let optional = get_as_bool(&props["optional"]);
|
||||
Box::new(MemberChildToBuild::Node(NodeChildToBuild::new(rule, None, optional)))
|
||||
Box::new(MemberChildToBuild::Node(NodeChildToBuild::new(
|
||||
rule, None, optional,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -297,11 +391,29 @@ fn deserialize_build_spec(build_spec_name: &str, build_spec: &Yaml) -> BuildSpec
|
||||
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"]))
|
||||
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"]))
|
||||
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, or a production type.");
|
||||
panic!(
|
||||
"Expected a node spec for either a struct, leaf_struct, enum, leaf_enum node type, production, polymorphic type, or polymorphic build type."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,9 @@ pub 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 production_build_fn;
|
||||
mod spec;
|
||||
mod struct_build_fn;
|
||||
@ -12,6 +14,9 @@ mod util;
|
||||
use crate::enum_build_fn::make_enum_build_fn;
|
||||
use crate::leaf_enum_build_fn::make_leaf_enum_build_fn;
|
||||
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::production_build_fn::make_production_build_fn;
|
||||
use crate::struct_build_fn::make_struct_build_fn;
|
||||
use crate::type_gen::make_type;
|
||||
@ -19,7 +24,6 @@ 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 ***");
|
||||
@ -43,7 +47,22 @@ fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
|
||||
println!("Production Spec - rule: {}", production_build_spec.rule());
|
||||
}
|
||||
BuildSpec::Polymorphic(polymorphic_build_spec) => {
|
||||
println!("Polymorphic Spec - name: {}", polymorphic_build_spec.name());
|
||||
println!(
|
||||
"Polymorphic Type Spec - name: {}",
|
||||
polymorphic_build_spec.name()
|
||||
);
|
||||
}
|
||||
BuildSpec::PolymorphicBuild(polymorphic_build_build_spec) => {
|
||||
println!(
|
||||
"Polymorphic Build Spec - name: {}",
|
||||
polymorphic_build_build_spec.name()
|
||||
);
|
||||
}
|
||||
BuildSpec::PolymorphicEnum(polymorphic_enum_build_spec) => {
|
||||
println!(
|
||||
"Polymorphic Enum Spec - name: {}",
|
||||
polymorphic_enum_build_spec.name()
|
||||
);
|
||||
}
|
||||
}
|
||||
println!("{:#?}", token_stream);
|
||||
@ -95,6 +114,16 @@ fn generate_build_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
||||
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<_>>();
|
||||
let combined = quote! {
|
||||
|
||||
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,10 +1,9 @@
|
||||
use crate::spec::PolymorphicTypeBuildSpec;
|
||||
use crate::util::{make_build_fn_name, make_build_pair};
|
||||
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 {
|
||||
pub fn make_polymorphic_build_fn(build_spec: &PolymorphicTypeBuildSpec) -> 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());
|
||||
|
||||
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!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,7 @@ pub fn make_production_build_fn(production_build_spec: &ProductionBuildSpec) ->
|
||||
ProductionKind::Double => format_ident!("f64"),
|
||||
ProductionKind::String(_) => format_ident!("String"),
|
||||
ProductionKind::Boolean => format_ident!("bool"),
|
||||
ProductionKind::Node(node_type) => format_ident!("{}", node_type),
|
||||
};
|
||||
let pair_ident = format_ident!("{}", make_build_pair(production_build_spec.rule()));
|
||||
|
||||
@ -77,6 +78,13 @@ pub fn make_production_build_fn(production_build_spec: &ProductionBuildSpec) ->
|
||||
ProductionKind::Boolean => quote! {
|
||||
#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! {
|
||||
|
||||
@ -4,7 +4,9 @@ pub enum BuildSpec {
|
||||
Struct(StructBuildSpec),
|
||||
LeafStruct(LeafStructBuildSpec),
|
||||
Production(ProductionBuildSpec),
|
||||
Polymorphic(PolymorphicBuildSpec),
|
||||
Polymorphic(PolymorphicTypeBuildSpec),
|
||||
PolymorphicBuild(PolymorphicBuildBuildSpec),
|
||||
PolymorphicEnum(PolymorphicEnumBuildSpec),
|
||||
}
|
||||
|
||||
// Enum build spec
|
||||
@ -35,14 +37,14 @@ impl EnumBuildSpec {
|
||||
|
||||
pub struct EnumRule {
|
||||
rule: String,
|
||||
child: Option<Box<EnumRuleChild>>
|
||||
child: Option<Box<EnumRuleChild>>,
|
||||
}
|
||||
|
||||
impl EnumRule {
|
||||
pub fn new(rule: &str, child: Option<Box<EnumRuleChild>>) -> Self {
|
||||
Self {
|
||||
rule: rule.to_string(),
|
||||
child
|
||||
child,
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,7 +63,7 @@ impl EnumRule {
|
||||
}
|
||||
|
||||
pub struct EnumRuleChild {
|
||||
kind: Box<EnumRuleChildKind>
|
||||
kind: Box<EnumRuleChildKind>,
|
||||
}
|
||||
|
||||
impl EnumRuleChild {
|
||||
@ -81,11 +83,11 @@ pub enum EnumRuleChildKind {
|
||||
Double,
|
||||
USize,
|
||||
String,
|
||||
Boolean
|
||||
Boolean,
|
||||
}
|
||||
|
||||
pub struct EnumRuleNodeChild {
|
||||
build: String
|
||||
build: String,
|
||||
}
|
||||
|
||||
impl EnumRuleNodeChild {
|
||||
@ -111,7 +113,7 @@ impl LeafEnumBuildSpec {
|
||||
pub fn new(build: &str, rules: Vec<Box<LeafEnumRule>>) -> Self {
|
||||
Self {
|
||||
build: build.to_string(),
|
||||
rules
|
||||
rules,
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,7 +153,7 @@ impl StructBuildSpec {
|
||||
pub fn new(build: &str, children: Vec<Box<StructChildSpec>>) -> Self {
|
||||
Self {
|
||||
build: build.to_string(),
|
||||
children
|
||||
children,
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,7 +232,7 @@ impl VecChild {
|
||||
#[derive(Debug)]
|
||||
pub enum VecChildToBuild {
|
||||
Node(VecNodeChildToBuild),
|
||||
String
|
||||
String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -240,7 +242,9 @@ pub struct VecNodeChildToBuild {
|
||||
|
||||
impl VecNodeChildToBuild {
|
||||
pub fn new(build: &str) -> Self {
|
||||
Self { build: build.to_string() }
|
||||
Self {
|
||||
build: build.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// The type to build, in Pascal case.
|
||||
@ -295,11 +299,7 @@ pub struct NodeChildToBuild {
|
||||
}
|
||||
|
||||
impl NodeChildToBuild {
|
||||
pub fn new(
|
||||
build: &str,
|
||||
or_else: Option<String>,
|
||||
optional: bool,
|
||||
) -> Self {
|
||||
pub fn new(build: &str, or_else: Option<String>, optional: bool) -> Self {
|
||||
Self {
|
||||
build: build.to_string(),
|
||||
or_else,
|
||||
@ -325,13 +325,13 @@ impl NodeChildToBuild {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BooleanChildToBuild {
|
||||
name: String
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl BooleanChildToBuild {
|
||||
pub fn new(name: &str) -> Self {
|
||||
Self {
|
||||
name: name.to_string()
|
||||
name: name.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -417,28 +417,33 @@ pub enum ProductionKind {
|
||||
Long,
|
||||
Double,
|
||||
String(ProductionStringFrom),
|
||||
Boolean
|
||||
Boolean,
|
||||
Node(String),
|
||||
}
|
||||
|
||||
pub enum ProductionStringFrom {
|
||||
StringInner,
|
||||
WholePair
|
||||
WholePair,
|
||||
}
|
||||
|
||||
// Polymorphic build spec
|
||||
|
||||
pub struct PolymorphicBuildSpec {
|
||||
pub struct PolymorphicTypeBuildSpec {
|
||||
name: String,
|
||||
enum_members: Vec<Box<PolymorphicEnumMember>>,
|
||||
build_kind: String
|
||||
build_kind: String,
|
||||
}
|
||||
|
||||
impl PolymorphicBuildSpec {
|
||||
pub fn new(name: &str, enum_members: Vec<Box<PolymorphicEnumMember>>, build_kind: &str) -> Self {
|
||||
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()
|
||||
build_kind: build_kind.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -457,14 +462,14 @@ impl PolymorphicBuildSpec {
|
||||
|
||||
pub struct PolymorphicEnumMember {
|
||||
name: String,
|
||||
inner_kind: 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()
|
||||
inner_kind: inner_kind.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -476,3 +481,173 @@ impl PolymorphicEnumMember {
|
||||
&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 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,12 +1,75 @@
|
||||
use crate::spec::{
|
||||
BooleanChildToBuild, BuildSpec, EnumBuildSpec, EnumRuleChildKind, LeafEnumBuildSpec,
|
||||
LeafStructBuildSpec, LeafStructMemberKind, MemberChildToBuild, NodeChildToBuild,
|
||||
PolymorphicBuildSpec, StructBuildSpec, StructChildSpec, VecChild, VecChildToBuild,
|
||||
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_type(build_spec: &PolymorphicBuildSpec) -> TokenStream {
|
||||
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(|build_child| match build_child {
|
||||
AlternativeChild::Skip => None,
|
||||
AlternativeChild::Build(build_child) => Some(format_ident!("{}", build_child.name())),
|
||||
})
|
||||
.filter(Option::is_some)
|
||||
.map(Option::unwrap)
|
||||
.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),*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_polymorphic_type(build_spec: &PolymorphicTypeBuildSpec) -> TokenStream {
|
||||
let members = build_spec
|
||||
.enum_members()
|
||||
.map(|enum_member| {
|
||||
@ -370,5 +433,9 @@ pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||
BuildSpec::Polymorphic(polymorphic_build_spec) => {
|
||||
Some(make_polymorphic_type(polymorphic_build_spec))
|
||||
}
|
||||
BuildSpec::PolymorphicBuild(polymorphic_build_build_spec) => {
|
||||
Some(make_polymorphic_build_type(polymorphic_build_build_spec))
|
||||
}
|
||||
BuildSpec::PolymorphicEnum(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -605,50 +605,109 @@ Expression:
|
||||
build:
|
||||
kind: TernaryExpression
|
||||
TernaryExpression:
|
||||
polymorphic_build:
|
||||
return_type: Expression
|
||||
alternatives:
|
||||
- test:
|
||||
number_of_pairs: 1
|
||||
action:
|
||||
return_build:
|
||||
kind: OrExpression
|
||||
- test:
|
||||
number_of_pairs: 3
|
||||
action:
|
||||
build:
|
||||
enum_variant: Ternary
|
||||
children:
|
||||
- or_expression
|
||||
- ternary_alternatives:
|
||||
optional: true
|
||||
TernaryAlternatives:
|
||||
children:
|
||||
- ternary_true_alternative
|
||||
- ternary_false_alternative
|
||||
- test:
|
||||
kind: Expression
|
||||
rule: OrExpression
|
||||
- on_true:
|
||||
kind: Expression
|
||||
rule: TernaryTrueAlternative
|
||||
- on_false:
|
||||
kind: Expression
|
||||
rule: TernaryFalseAlternative
|
||||
TernaryTrueAlternative:
|
||||
children:
|
||||
- expression
|
||||
produce:
|
||||
kind:
|
||||
node: Expression
|
||||
TernaryFalseAlternative:
|
||||
children:
|
||||
- expression
|
||||
produce:
|
||||
kind:
|
||||
node: Expression
|
||||
OrExpression:
|
||||
polymorphic_build:
|
||||
return_type: Expression
|
||||
alternatives:
|
||||
- test:
|
||||
number_of_pairs: 1
|
||||
action:
|
||||
return_build:
|
||||
kind: AndExpression
|
||||
- test:
|
||||
number_of_pairs: 3
|
||||
action:
|
||||
build:
|
||||
enum_variant: Or
|
||||
children:
|
||||
- left:
|
||||
kind: Expression
|
||||
rule: AndExpression
|
||||
- or_sym:
|
||||
rule: Or
|
||||
skip: true
|
||||
- right:
|
||||
kind: Expression
|
||||
rule: Expression
|
||||
optional: true
|
||||
AndExpression:
|
||||
polymorphic_build:
|
||||
return_type: Expression
|
||||
alternatives:
|
||||
- test:
|
||||
number_of_pairs: 1
|
||||
action:
|
||||
return_build:
|
||||
kind: ComparisonExpression
|
||||
- test:
|
||||
number_of_pairs: 3
|
||||
action:
|
||||
build:
|
||||
enum_variant: And
|
||||
children:
|
||||
- left:
|
||||
kind: Expression
|
||||
rule: ComparisonExpression
|
||||
- and_sym:
|
||||
rule: And
|
||||
skip: true
|
||||
- right:
|
||||
kind: Expression
|
||||
rule: Expression
|
||||
optional: true
|
||||
ComparisonExpression:
|
||||
polymorphic_build:
|
||||
return_type: Expression
|
||||
alternatives:
|
||||
- test:
|
||||
number_of_pairs: 1
|
||||
action:
|
||||
return_build:
|
||||
kind: ShiftExpression
|
||||
- test:
|
||||
number_of_pairs: 3
|
||||
action:
|
||||
build:
|
||||
enum_variant: Comparison
|
||||
children:
|
||||
- left:
|
||||
kind: Expression
|
||||
rule: ShiftExpression
|
||||
- operator:
|
||||
kind: ComparisonOperator
|
||||
rule: ComparisonOperator
|
||||
optional: true
|
||||
- right:
|
||||
kind: Expression
|
||||
rule: Expression
|
||||
optional: true
|
||||
ComparisonOperator:
|
||||
leaf_rules:
|
||||
- Greater
|
||||
@ -658,64 +717,144 @@ ComparisonOperator:
|
||||
- EqualTo
|
||||
- NotEqualTo
|
||||
ShiftExpression:
|
||||
polymorphic_build:
|
||||
return_type: Expression
|
||||
alternatives:
|
||||
- test:
|
||||
number_of_pairs: 1
|
||||
action:
|
||||
return_build:
|
||||
kind: AdditiveExpression
|
||||
- test:
|
||||
number_of_pairs: 3
|
||||
action:
|
||||
build:
|
||||
enum_variant: Shift
|
||||
children:
|
||||
- left:
|
||||
kind: Expression
|
||||
rule: AdditiveExpression
|
||||
- operator:
|
||||
kind: ShiftOperator
|
||||
rule: ShiftOperator
|
||||
optional: true
|
||||
- right:
|
||||
kind: Expression
|
||||
rule: Expression
|
||||
optional: true
|
||||
ShiftOperator:
|
||||
leaf_rules:
|
||||
- LeftShift
|
||||
- RightShift
|
||||
AdditiveExpression:
|
||||
polymorphic_build:
|
||||
return_type: Expression
|
||||
alternatives:
|
||||
- test:
|
||||
number_of_pairs: 1
|
||||
action:
|
||||
return_build:
|
||||
kind: MultiplicativeExpression
|
||||
- test:
|
||||
number_of_pairs: 3
|
||||
action:
|
||||
build:
|
||||
enum_variant: Additive
|
||||
children:
|
||||
- left:
|
||||
kind: Expression
|
||||
rule: MultiplicativeExpression
|
||||
- operator:
|
||||
kind: AdditiveOperator
|
||||
rule: AdditiveOperator
|
||||
optional: true
|
||||
- right:
|
||||
kind: Expression
|
||||
rule: Expression
|
||||
optional: true
|
||||
AdditiveOperator:
|
||||
leaf_rules:
|
||||
- Add
|
||||
- Subtract
|
||||
MultiplicativeExpression:
|
||||
polymorphic_build:
|
||||
return_type: Expression
|
||||
alternatives:
|
||||
- test:
|
||||
number_of_pairs: 1
|
||||
action:
|
||||
return_build:
|
||||
kind: PrefixExpression
|
||||
- test:
|
||||
number_of_pairs: 3
|
||||
action:
|
||||
build:
|
||||
enum_variant: Multiplicative
|
||||
children:
|
||||
- left:
|
||||
kind: Expression
|
||||
rule: PrefixExpression
|
||||
- operator:
|
||||
kind: MultiplicativeOperator
|
||||
rule: MultiplicativeOperator
|
||||
optional: true
|
||||
- right:
|
||||
kind: Expression
|
||||
rule: Expression
|
||||
optional: true
|
||||
MultiplicativeOperator:
|
||||
leaf_rules:
|
||||
- Multiply
|
||||
- Divide
|
||||
- Modulo
|
||||
PrefixExpression:
|
||||
polymorphic_build:
|
||||
return_type: Expression
|
||||
alternatives:
|
||||
- test:
|
||||
number_of_pairs: 1
|
||||
action:
|
||||
return_build:
|
||||
kind: SuffixExpression
|
||||
- test:
|
||||
number_of_pairs: 2
|
||||
action:
|
||||
build:
|
||||
enum_variant: Prefix
|
||||
children:
|
||||
- prefix_operators:
|
||||
kind: PrefixOperators
|
||||
rule: PrefixOperators
|
||||
- right:
|
||||
kind: Expression
|
||||
rule: SuffixExpression
|
||||
PrefixOperators:
|
||||
children:
|
||||
- operators:
|
||||
rule: PrefixOperator
|
||||
vec: true
|
||||
- right:
|
||||
rule: SuffixExpression
|
||||
PrefixOperator:
|
||||
leaf_rules:
|
||||
- Spread
|
||||
- Not
|
||||
- Negative
|
||||
SuffixExpression:
|
||||
polymorphic_build:
|
||||
return_type: Expression
|
||||
alternatives:
|
||||
- test:
|
||||
number_of_pairs: 1
|
||||
action:
|
||||
return_build:
|
||||
kind: PrimaryExpression
|
||||
- test:
|
||||
number_of_pairs: 2
|
||||
action:
|
||||
build:
|
||||
enum_variant: Suffix
|
||||
children:
|
||||
- left:
|
||||
kind: Expression
|
||||
rule: PrimaryExpression
|
||||
- suffix_operators:
|
||||
kind: SuffixOperators
|
||||
rule: SuffixOperators
|
||||
SuffixOperators:
|
||||
children:
|
||||
- operators:
|
||||
rule: SuffixOperator
|
||||
vec: true
|
||||
@ -735,11 +874,21 @@ ObjectIndex:
|
||||
children:
|
||||
- expression
|
||||
PrimaryExpression:
|
||||
polymorphic_enum:
|
||||
return_type: Expression
|
||||
rules:
|
||||
- Literal
|
||||
- FullyQualifiedName
|
||||
- Closure
|
||||
- ParenthesizedExpression
|
||||
- Literal:
|
||||
wrap:
|
||||
enum_variant: Literal
|
||||
- FullyQualifiedName:
|
||||
wrap:
|
||||
enum_variant: Fqn
|
||||
- Closure:
|
||||
wrap:
|
||||
enum_variant: Closure
|
||||
- ParenthesizedExpression:
|
||||
return_build:
|
||||
kind: Expression
|
||||
ParenthesizedExpression:
|
||||
children:
|
||||
- expression
|
||||
|
||||
@ -596,12 +596,10 @@ Expression = {
|
||||
|
||||
TernaryExpression = {
|
||||
OrExpression
|
||||
~ ( TernaryAlternatives )?
|
||||
}
|
||||
|
||||
TernaryAlternatives = {
|
||||
~ (
|
||||
TernaryTrueAlternative
|
||||
~ TernaryFalseAlternative
|
||||
)?
|
||||
}
|
||||
|
||||
TernaryTrueAlternative = {
|
||||
@ -682,10 +680,14 @@ MultiplicativeOperator = {
|
||||
}
|
||||
|
||||
PrefixExpression = {
|
||||
PrefixOperator*
|
||||
PrefixOperators?
|
||||
~ SuffixExpression
|
||||
}
|
||||
|
||||
PrefixOperators = {
|
||||
PrefixOperator+
|
||||
}
|
||||
|
||||
PrefixOperator = {
|
||||
Spread
|
||||
| Not
|
||||
@ -694,7 +696,11 @@ PrefixOperator = {
|
||||
|
||||
SuffixExpression = {
|
||||
PrimaryExpression
|
||||
~ SuffixOperator*
|
||||
~ SuffixOperators?
|
||||
}
|
||||
|
||||
SuffixOperators = {
|
||||
SuffixOperator+
|
||||
}
|
||||
|
||||
SuffixOperator = {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user