Compare commits
12 Commits
2dd3bf5a06
...
fe2fff5882
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe2fff5882 | ||
|
|
e795664a09 | ||
|
|
49a96eba85 | ||
|
|
9e3d71d73b | ||
|
|
5ff14f9dea | ||
|
|
522869371e | ||
|
|
11f97a2174 | ||
|
|
26cb28307c | ||
|
|
cce927d964 | ||
|
|
7399a8748c | ||
|
|
a7eabae3e3 | ||
|
|
c94a698a52 |
@ -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::{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 convert_case::{Case, Casing};
|
||||||
use yaml_rust2::{Yaml, YamlLoader};
|
use yaml_rust2::{Yaml, YamlLoader};
|
||||||
|
|
||||||
@ -18,21 +18,132 @@ fn unwrap_single_member_hash(hash: &Yaml) -> (String, &Yaml) {
|
|||||||
(key_as_string, member_value)
|
(key_as_string, member_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
.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) -> PolymorphicTypeBuildSpec {
|
||||||
|
let enum_members = deserialize_polymorphic_enum_members(&spec_props["enum_members"]);
|
||||||
|
let build_kind = spec_props["build"]["kind"].as_str().unwrap();
|
||||||
|
PolymorphicTypeBuildSpec::new(name, enum_members, build_kind)
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_production_spec(rule: &str, production_yaml: &Yaml) -> ProductionBuildSpec {
|
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() {
|
||||||
"int" => ProductionKind::Int,
|
let node = production_yaml["kind"]["node"].as_str().unwrap();
|
||||||
"long" => ProductionKind::Long,
|
ProductionKind::Node(node.to_string())
|
||||||
"double" => ProductionKind::Double,
|
} else {
|
||||||
"boolean" => ProductionKind::Boolean,
|
match production_yaml["kind"].as_str().unwrap() {
|
||||||
"string" => {
|
"int" => ProductionKind::Int,
|
||||||
let from = match production_yaml["from"].as_str().unwrap() {
|
"long" => ProductionKind::Long,
|
||||||
"string_inner" => ProductionStringFrom::StringInner,
|
"double" => ProductionKind::Double,
|
||||||
"whole_pair" => ProductionStringFrom::WholePair,
|
"boolean" => ProductionKind::Boolean,
|
||||||
_ => panic!("invalid from: {}", production_yaml["from"].as_str().unwrap()),
|
"string" => {
|
||||||
};
|
let from = match production_yaml["from"].as_str().unwrap() {
|
||||||
ProductionKind::String(from)
|
"string_inner" => ProductionStringFrom::StringInner,
|
||||||
},
|
"whole_pair" => ProductionStringFrom::WholePair,
|
||||||
_ => panic!("invalid kind: {}", production_yaml["kind"].as_str().unwrap()),
|
_ => panic!(
|
||||||
|
"invalid from: {}",
|
||||||
|
production_yaml["from"].as_str().unwrap()
|
||||||
|
),
|
||||||
|
};
|
||||||
|
ProductionKind::String(from)
|
||||||
|
}
|
||||||
|
_ => panic!(
|
||||||
|
"invalid kind: {}",
|
||||||
|
production_yaml["kind"].as_str().unwrap()
|
||||||
|
),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
ProductionBuildSpec::new(rule, kind)
|
ProductionBuildSpec::new(rule, kind)
|
||||||
}
|
}
|
||||||
@ -46,9 +157,7 @@ fn deserialize_leaf_enum_rules(rules_yaml: &Yaml) -> Vec<Box<LeafEnumRule>> {
|
|||||||
.as_vec()
|
.as_vec()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|rule_yaml| {
|
.map(|rule_yaml| deserialize_leaf_enum_rule(rule_yaml))
|
||||||
deserialize_leaf_enum_rule(rule_yaml)
|
|
||||||
})
|
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,16 +172,19 @@ fn deserialize_enum_rule_custom_child(rule_props: &Yaml) -> Option<Box<EnumRuleC
|
|||||||
"usize" => EnumRuleChildKind::USize,
|
"usize" => EnumRuleChildKind::USize,
|
||||||
"string" => EnumRuleChildKind::String,
|
"string" => EnumRuleChildKind::String,
|
||||||
"boolean" => EnumRuleChildKind::Boolean,
|
"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))))
|
Some(Box::new(EnumRuleChild::new(Box::new(kind))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_enum_rule_node_child(rule: &str) -> Box<EnumRuleChild> {
|
fn deserialize_enum_rule_node_child(rule: &str) -> Box<EnumRuleChild> {
|
||||||
Box::new(EnumRuleChild::new(Box::new(
|
Box::new(EnumRuleChild::new(Box::new(EnumRuleChildKind::Node(
|
||||||
EnumRuleChildKind::Node(EnumRuleNodeChild::new(rule)),
|
EnumRuleNodeChild::new(rule),
|
||||||
)))
|
))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_enum_rule(rule_yaml: &Yaml) -> Box<EnumRule> {
|
fn deserialize_enum_rule(rule_yaml: &Yaml) -> Box<EnumRule> {
|
||||||
@ -80,7 +192,7 @@ fn deserialize_enum_rule(rule_yaml: &Yaml) -> Box<EnumRule> {
|
|||||||
let (rule, rule_props) = unwrap_single_member_hash(rule_yaml);
|
let (rule, rule_props) = unwrap_single_member_hash(rule_yaml);
|
||||||
Box::new(EnumRule::new(
|
Box::new(EnumRule::new(
|
||||||
&rule,
|
&rule,
|
||||||
deserialize_enum_rule_custom_child(rule_props)
|
deserialize_enum_rule_custom_child(rule_props),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
let rule_as_str = rule_yaml.as_str().unwrap();
|
let rule_as_str = rule_yaml.as_str().unwrap();
|
||||||
@ -164,7 +276,9 @@ fn deserialize_member_child_to_build(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let optional = get_as_bool(&props["optional"]);
|
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,
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,9 +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"]);
|
let leaf_rules = deserialize_leaf_enum_rules(&build_spec["leaf_rules"]);
|
||||||
BuildSpec::LeafEnum(LeafEnumBuildSpec::new(build_spec_name, leaf_rules))
|
BuildSpec::LeafEnum(LeafEnumBuildSpec::new(build_spec_name, leaf_rules))
|
||||||
} else if build_spec["produce"].is_hash() {
|
} 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"],
|
||||||
|
))
|
||||||
|
} 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 {
|
} 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,6 +2,10 @@ pub mod deserialize;
|
|||||||
mod enum_build_fn;
|
mod enum_build_fn;
|
||||||
mod leaf_enum_build_fn;
|
mod leaf_enum_build_fn;
|
||||||
mod leaf_struct_build_fn;
|
mod leaf_struct_build_fn;
|
||||||
|
mod polymorphic_build_build_fn;
|
||||||
|
mod polymorphic_build_fn;
|
||||||
|
mod polymorphic_enum_build_fn;
|
||||||
|
mod pretty_print;
|
||||||
mod production_build_fn;
|
mod production_build_fn;
|
||||||
mod spec;
|
mod spec;
|
||||||
mod struct_build_fn;
|
mod struct_build_fn;
|
||||||
@ -11,6 +15,10 @@ mod util;
|
|||||||
use crate::enum_build_fn::make_enum_build_fn;
|
use crate::enum_build_fn::make_enum_build_fn;
|
||||||
use crate::leaf_enum_build_fn::make_leaf_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::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::pretty_print::make_pretty_print_impl;
|
||||||
use crate::production_build_fn::make_production_build_fn;
|
use crate::production_build_fn::make_production_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;
|
||||||
@ -38,7 +46,25 @@ fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
BuildSpec::Production(production_build_spec) => {
|
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 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);
|
println!("{:#?}", token_stream);
|
||||||
@ -85,9 +111,31 @@ fn generate_build_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
|||||||
debug_built_spec(build_spec, &stream);
|
debug_built_spec(build_spec, &stream);
|
||||||
stream
|
stream
|
||||||
}
|
}
|
||||||
|
BuildSpec::Polymorphic(polymorphic_build_spec) => {
|
||||||
|
let stream = make_polymorphic_build_fn(polymorphic_build_spec);
|
||||||
|
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<_>>();
|
.collect::<Vec<_>>();
|
||||||
let combined = quote! {
|
let combined = quote! {
|
||||||
|
//noinspection RsUnusedImport
|
||||||
|
use crate::parser::Rule;
|
||||||
|
//noinspection RsUnusedImport
|
||||||
|
use pest::iterators::Pair;
|
||||||
|
//noinspection RsUnusedImport
|
||||||
|
use crate::ast::node::*;
|
||||||
|
|
||||||
#(#build_fns)*
|
#(#build_fns)*
|
||||||
};
|
};
|
||||||
AstGeneratedFile {
|
AstGeneratedFile {
|
||||||
@ -111,9 +159,30 @@ fn generate_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_pretty_print_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
||||||
|
let impls = build_specs
|
||||||
|
.iter()
|
||||||
|
.map(|build_spec| {
|
||||||
|
let stream = make_pretty_print_impl(build_spec);
|
||||||
|
debug_built_spec(build_spec, &stream);
|
||||||
|
stream
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let combined = quote! {
|
||||||
|
use crate::ast::node::*;
|
||||||
|
#(#impls)*
|
||||||
|
};
|
||||||
|
AstGeneratedFile {
|
||||||
|
name: String::from("pretty_print.rs"),
|
||||||
|
contents: token_stream_to_string(combined),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn generate_files(build_specs: &[BuildSpec]) -> Vec<AstGeneratedFile> {
|
pub fn generate_files(build_specs: &[BuildSpec]) -> Vec<AstGeneratedFile> {
|
||||||
vec![
|
vec![
|
||||||
generate_build_file(build_specs),
|
generate_build_file(build_specs),
|
||||||
generate_node_file(build_specs),
|
generate_node_file(build_specs),
|
||||||
|
generate_pretty_print_file(build_specs),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
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!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
ast-generator/src/polymorphic_build_fn.rs
Normal file
18
ast-generator/src/polymorphic_build_fn.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
use crate::spec::PolymorphicTypeBuildSpec;
|
||||||
|
use crate::util::{make_build_fn_name, make_build_pair};
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
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());
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
256
ast-generator/src/pretty_print.rs
Normal file
256
ast-generator/src/pretty_print.rs
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
use crate::spec::{
|
||||||
|
AlternativeChild, BuildSpec, EnumBuildSpec, EnumRuleChildKind, LeafEnumBuildSpec,
|
||||||
|
LeafStructBuildSpec, LeafStructMemberKind, MemberChildToBuild, PolymorphicBuildBuildSpec,
|
||||||
|
PolymorphicEnumBuildSpec, PolymorphicTypeBuildSpec, ProductionBuildSpec, StructBuildSpec,
|
||||||
|
StructChildSpec, VecChildToBuild,
|
||||||
|
};
|
||||||
|
use convert_case::{Case, Casing};
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
fn make_production_p2_impl(_spec: &ProductionBuildSpec) -> TokenStream {
|
||||||
|
quote! {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_polymorphic_enum_p2_impl(_spec: &PolymorphicEnumBuildSpec) -> TokenStream {
|
||||||
|
quote! {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_polymorphic_build_p2_impl(spec: &PolymorphicBuildBuildSpec) -> TokenStream {
|
||||||
|
let (_, build) = spec.primary_alternative();
|
||||||
|
let type_ident = format_ident!("{}", spec.name());
|
||||||
|
let name_str = spec.name();
|
||||||
|
|
||||||
|
let child_statements = build
|
||||||
|
.children()
|
||||||
|
.map(|child| match child {
|
||||||
|
AlternativeChild::Skip => None,
|
||||||
|
AlternativeChild::Build(build) => {
|
||||||
|
let child_ident = format_ident!("{}", build.name());
|
||||||
|
Some(quote! {
|
||||||
|
self.#child_ident().pretty_print(writer)?
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.collect::<Vec<TokenStream>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
impl PrettyPrint for #type_ident {
|
||||||
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||||
|
writer.writeln_indented(#name_str);
|
||||||
|
writer.increase_indent();
|
||||||
|
#(#child_statements;)*
|
||||||
|
writer.decrease_indent();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_polymorphic_type_p2_impl(spec: &PolymorphicTypeBuildSpec) -> TokenStream {
|
||||||
|
let type_ident = format_ident!("{}", spec.name());
|
||||||
|
let child_matchers = spec
|
||||||
|
.enum_members()
|
||||||
|
.map(|member| {
|
||||||
|
let enum_member_ident = format_ident!("{}", member.name());
|
||||||
|
let inner_name = format_ident!("{}", member.inner_kind().to_case(Case::Snake));
|
||||||
|
quote! {
|
||||||
|
#type_ident::#enum_member_ident(#inner_name) => #inner_name.pretty_print(writer)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
impl PrettyPrint for #type_ident {
|
||||||
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||||
|
match self {
|
||||||
|
#(#child_matchers,)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_leaf_enum_p2_impl(spec: &LeafEnumBuildSpec) -> TokenStream {
|
||||||
|
let type_ident = format_ident!("{}", spec.build());
|
||||||
|
let child_matchers = spec
|
||||||
|
.rules()
|
||||||
|
.map(|rule| {
|
||||||
|
let enum_variant_ident = format_ident!("{}", rule.rule());
|
||||||
|
let name_str = rule.rule();
|
||||||
|
quote! {
|
||||||
|
#type_ident::#enum_variant_ident => writer.writeln_indented(#name_str)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
impl PrettyPrint for #type_ident {
|
||||||
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||||
|
match self {
|
||||||
|
#(#child_matchers,)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_enum_p2_impl(spec: &EnumBuildSpec) -> TokenStream {
|
||||||
|
let type_ident = format_ident!("{}", spec.build());
|
||||||
|
let type_str = spec.build();
|
||||||
|
|
||||||
|
let child_matchers = spec
|
||||||
|
.rules()
|
||||||
|
.map(|rule| {
|
||||||
|
let enum_variant_ident = format_ident!("{}", rule.rule());
|
||||||
|
if let Some(child) = rule.child() {
|
||||||
|
match child.kind() {
|
||||||
|
EnumRuleChildKind::Node(node_child) => {
|
||||||
|
let child_name_ident =
|
||||||
|
format_ident!("{}", node_child.build().to_case(Case::Snake));
|
||||||
|
Some(quote! {
|
||||||
|
#type_ident::#enum_variant_ident(#child_name_ident) => {
|
||||||
|
#child_name_ident.pretty_print(writer)?;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let variant_str = rule.rule();
|
||||||
|
Some(quote! {
|
||||||
|
#type_ident::#enum_variant_ident => writer.writeln_indented(#variant_str)?
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
impl PrettyPrint for #type_ident {
|
||||||
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||||
|
writer.writeln_indented(#type_str)?;
|
||||||
|
writer.increase_indent();
|
||||||
|
match self {
|
||||||
|
#(#child_matchers,)*
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
writer.decrease_indent();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_leaf_struct_p2_impl(leaf_struct_build_spec: &LeafStructBuildSpec) -> TokenStream {
|
||||||
|
let type_ident = format_ident!("{}", leaf_struct_build_spec.build());
|
||||||
|
let member_formatters = leaf_struct_build_spec
|
||||||
|
.members()
|
||||||
|
.map(|member| match member.kind() {
|
||||||
|
LeafStructMemberKind::String => Some("{}"),
|
||||||
|
})
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ");
|
||||||
|
|
||||||
|
let format_string = format!("{}({})", leaf_struct_build_spec.build(), member_formatters);
|
||||||
|
|
||||||
|
let members = leaf_struct_build_spec
|
||||||
|
.members()
|
||||||
|
.map(|member| {
|
||||||
|
let member_ident = format_ident!("{}", member.name());
|
||||||
|
quote! {
|
||||||
|
self.#member_ident()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
impl PrettyPrint for #type_ident {
|
||||||
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||||
|
writer.writeln_indented(&format!(#format_string, #(#members),*))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_struct_p2_impl(struct_build_spec: &StructBuildSpec) -> TokenStream {
|
||||||
|
let child_print_statements = struct_build_spec
|
||||||
|
.children()
|
||||||
|
.map(|child| match child {
|
||||||
|
StructChildSpec::SkipChild(_) => None,
|
||||||
|
StructChildSpec::VecChild(vec_child) => match vec_child.build() {
|
||||||
|
VecChildToBuild::Node(_) => {
|
||||||
|
let child_ident = format_ident!("{}", vec_child.name());
|
||||||
|
Some(quote! {
|
||||||
|
for child in self.#child_ident() {
|
||||||
|
child.pretty_print(writer)?;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
VecChildToBuild::String => None,
|
||||||
|
},
|
||||||
|
StructChildSpec::MemberChild(member_child) => match member_child.build() {
|
||||||
|
MemberChildToBuild::Node(node_member_child) => {
|
||||||
|
let child_ident = format_ident!("{}", member_child.name());
|
||||||
|
if node_member_child.optional() {
|
||||||
|
Some(quote! {
|
||||||
|
if let Some(child) = self.#child_ident() {
|
||||||
|
child.pretty_print(writer)?;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Some(quote! {
|
||||||
|
self.#child_ident().pretty_print(writer)?;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MemberChildToBuild::Boolean(boolean_member_child) => {
|
||||||
|
let format_string = format!("{}({})", boolean_member_child.name(), "{}");
|
||||||
|
let child_ident = format_ident!("{}", boolean_member_child.name());
|
||||||
|
Some(quote! {
|
||||||
|
writer.writeln_indented(&format!(#format_string, self.#child_ident()))?;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let type_ident = format_ident!("{}", struct_build_spec.build());
|
||||||
|
let type_string = struct_build_spec.build();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
impl PrettyPrint for #type_ident {
|
||||||
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||||
|
writer.writeln_indented(#type_string)?;
|
||||||
|
writer.increase_indent();
|
||||||
|
#(#child_print_statements)*
|
||||||
|
writer.decrease_indent();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_pretty_print_impl(build_spec: &BuildSpec) -> TokenStream {
|
||||||
|
match build_spec {
|
||||||
|
BuildSpec::Struct(struct_spec) => make_struct_p2_impl(struct_spec),
|
||||||
|
BuildSpec::LeafStruct(leaf_struct) => make_leaf_struct_p2_impl(leaf_struct),
|
||||||
|
BuildSpec::Enum(enum_spec) => make_enum_p2_impl(enum_spec),
|
||||||
|
BuildSpec::LeafEnum(leaf_enum) => make_leaf_enum_p2_impl(leaf_enum),
|
||||||
|
BuildSpec::Polymorphic(polymorphic) => make_polymorphic_type_p2_impl(polymorphic),
|
||||||
|
BuildSpec::PolymorphicBuild(polymorphic_build) => {
|
||||||
|
make_polymorphic_build_p2_impl(polymorphic_build)
|
||||||
|
}
|
||||||
|
BuildSpec::PolymorphicEnum(polymorphic_enum) => {
|
||||||
|
make_polymorphic_enum_p2_impl(polymorphic_enum)
|
||||||
|
}
|
||||||
|
BuildSpec::Production(production) => make_production_p2_impl(production),
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,6 +11,7 @@ pub fn make_production_build_fn(production_build_spec: &ProductionBuildSpec) ->
|
|||||||
ProductionKind::Double => format_ident!("f64"),
|
ProductionKind::Double => format_ident!("f64"),
|
||||||
ProductionKind::String(_) => format_ident!("String"),
|
ProductionKind::String(_) => format_ident!("String"),
|
||||||
ProductionKind::Boolean => format_ident!("bool"),
|
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()));
|
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! {
|
ProductionKind::Boolean => quote! {
|
||||||
#pair_ident.as_str().parse::<bool>().unwrap()
|
#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! {
|
quote! {
|
||||||
|
|||||||
@ -4,6 +4,9 @@ pub enum BuildSpec {
|
|||||||
Struct(StructBuildSpec),
|
Struct(StructBuildSpec),
|
||||||
LeafStruct(LeafStructBuildSpec),
|
LeafStruct(LeafStructBuildSpec),
|
||||||
Production(ProductionBuildSpec),
|
Production(ProductionBuildSpec),
|
||||||
|
Polymorphic(PolymorphicTypeBuildSpec),
|
||||||
|
PolymorphicBuild(PolymorphicBuildBuildSpec),
|
||||||
|
PolymorphicEnum(PolymorphicEnumBuildSpec),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enum build spec
|
// Enum build spec
|
||||||
@ -34,14 +37,14 @@ impl EnumBuildSpec {
|
|||||||
|
|
||||||
pub struct EnumRule {
|
pub struct EnumRule {
|
||||||
rule: String,
|
rule: String,
|
||||||
child: Option<Box<EnumRuleChild>>
|
child: Option<Box<EnumRuleChild>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnumRule {
|
impl EnumRule {
|
||||||
pub fn new(rule: &str, child: Option<Box<EnumRuleChild>>) -> Self {
|
pub fn new(rule: &str, child: Option<Box<EnumRuleChild>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
rule: rule.to_string(),
|
rule: rule.to_string(),
|
||||||
child
|
child,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +52,7 @@ impl EnumRule {
|
|||||||
pub fn rule(&self) -> &str {
|
pub fn rule(&self) -> &str {
|
||||||
&self.rule
|
&self.rule
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn child(&self) -> Option<&EnumRuleChild> {
|
pub fn child(&self) -> Option<&EnumRuleChild> {
|
||||||
if let Some(child) = &self.child {
|
if let Some(child) = &self.child {
|
||||||
Some(child.as_ref())
|
Some(child.as_ref())
|
||||||
@ -60,14 +63,14 @@ impl EnumRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct EnumRuleChild {
|
pub struct EnumRuleChild {
|
||||||
kind: Box<EnumRuleChildKind>
|
kind: Box<EnumRuleChildKind>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnumRuleChild {
|
impl EnumRuleChild {
|
||||||
pub fn new(kind: Box<EnumRuleChildKind>) -> Self {
|
pub fn new(kind: Box<EnumRuleChildKind>) -> Self {
|
||||||
Self { kind }
|
Self { kind }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kind(&self) -> &EnumRuleChildKind {
|
pub fn kind(&self) -> &EnumRuleChildKind {
|
||||||
&self.kind
|
&self.kind
|
||||||
}
|
}
|
||||||
@ -80,11 +83,11 @@ pub enum EnumRuleChildKind {
|
|||||||
Double,
|
Double,
|
||||||
USize,
|
USize,
|
||||||
String,
|
String,
|
||||||
Boolean
|
Boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EnumRuleNodeChild {
|
pub struct EnumRuleNodeChild {
|
||||||
build: String
|
build: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnumRuleNodeChild {
|
impl EnumRuleNodeChild {
|
||||||
@ -93,7 +96,7 @@ impl EnumRuleNodeChild {
|
|||||||
build: build.to_string(),
|
build: build.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(&self) -> &str {
|
pub fn build(&self) -> &str {
|
||||||
&self.build
|
&self.build
|
||||||
}
|
}
|
||||||
@ -110,7 +113,7 @@ impl LeafEnumBuildSpec {
|
|||||||
pub fn new(build: &str, rules: Vec<Box<LeafEnumRule>>) -> Self {
|
pub fn new(build: &str, rules: Vec<Box<LeafEnumRule>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
build: build.to_string(),
|
build: build.to_string(),
|
||||||
rules
|
rules,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +153,7 @@ impl StructBuildSpec {
|
|||||||
pub fn new(build: &str, children: Vec<Box<StructChildSpec>>) -> Self {
|
pub fn new(build: &str, children: Vec<Box<StructChildSpec>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
build: build.to_string(),
|
build: build.to_string(),
|
||||||
children
|
children,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +161,7 @@ impl StructBuildSpec {
|
|||||||
pub fn build(&self) -> &str {
|
pub fn build(&self) -> &str {
|
||||||
&self.build
|
&self.build
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The children for this build spec.
|
/// The children for this build spec.
|
||||||
pub fn children(&self) -> impl Iterator<Item = &StructChildSpec> {
|
pub fn children(&self) -> impl Iterator<Item = &StructChildSpec> {
|
||||||
self.children.iter().map(Box::as_ref)
|
self.children.iter().map(Box::as_ref)
|
||||||
@ -229,7 +232,7 @@ impl VecChild {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum VecChildToBuild {
|
pub enum VecChildToBuild {
|
||||||
Node(VecNodeChildToBuild),
|
Node(VecNodeChildToBuild),
|
||||||
String
|
String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -239,7 +242,9 @@ pub struct VecNodeChildToBuild {
|
|||||||
|
|
||||||
impl VecNodeChildToBuild {
|
impl VecNodeChildToBuild {
|
||||||
pub fn new(build: &str) -> Self {
|
pub fn new(build: &str) -> Self {
|
||||||
Self { build: build.to_string() }
|
Self {
|
||||||
|
build: build.to_string(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The type to build, in Pascal case.
|
/// The type to build, in Pascal case.
|
||||||
@ -294,11 +299,7 @@ pub struct NodeChildToBuild {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NodeChildToBuild {
|
impl NodeChildToBuild {
|
||||||
pub fn new(
|
pub fn new(build: &str, or_else: Option<String>, optional: bool) -> Self {
|
||||||
build: &str,
|
|
||||||
or_else: Option<String>,
|
|
||||||
optional: bool,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
build: build.to_string(),
|
build: build.to_string(),
|
||||||
or_else,
|
or_else,
|
||||||
@ -324,13 +325,13 @@ impl NodeChildToBuild {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BooleanChildToBuild {
|
pub struct BooleanChildToBuild {
|
||||||
name: String
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BooleanChildToBuild {
|
impl BooleanChildToBuild {
|
||||||
pub fn new(name: &str) -> Self {
|
pub fn new(name: &str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: name.to_string()
|
name: name.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,11 +402,11 @@ impl ProductionBuildSpec {
|
|||||||
kind,
|
kind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rule(&self) -> &str {
|
pub fn rule(&self) -> &str {
|
||||||
&self.rule
|
&self.rule
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kind(&self) -> &ProductionKind {
|
pub fn kind(&self) -> &ProductionKind {
|
||||||
&self.kind
|
&self.kind
|
||||||
}
|
}
|
||||||
@ -416,10 +417,256 @@ pub enum ProductionKind {
|
|||||||
Long,
|
Long,
|
||||||
Double,
|
Double,
|
||||||
String(ProductionStringFrom),
|
String(ProductionStringFrom),
|
||||||
Boolean
|
Boolean,
|
||||||
|
Node(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ProductionStringFrom {
|
pub enum ProductionStringFrom {
|
||||||
StringInner,
|
StringInner,
|
||||||
WholePair
|
WholePair,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Polymorphic build spec
|
||||||
|
|
||||||
|
pub struct PolymorphicTypeBuildSpec {
|
||||||
|
name: String,
|
||||||
|
enum_members: Vec<Box<PolymorphicEnumMember>>,
|
||||||
|
build_kind: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 fn primary_alternative(&self) -> (&AlternativeTest, &AlternativeBuild) {
|
||||||
|
let primary_build_alternative = self
|
||||||
|
.alternatives
|
||||||
|
.iter()
|
||||||
|
.find(|alternative| match alternative.action {
|
||||||
|
AlternativeAction::Build(_) => true,
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
.map(Box::as_ref)
|
||||||
|
.unwrap();
|
||||||
|
let alternative_build =
|
||||||
|
if let AlternativeAction::Build(build) = &primary_build_alternative.action {
|
||||||
|
build
|
||||||
|
} else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
(primary_build_alternative.test(), alternative_build)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,11 +1,116 @@
|
|||||||
use crate::spec::{
|
use crate::spec::{
|
||||||
BooleanChildToBuild, BuildSpec, EnumBuildSpec, EnumRuleChildKind, LeafEnumBuildSpec,
|
AlternativeAction, AlternativeChild, BooleanChildToBuild, BuildSpec, EnumBuildSpec,
|
||||||
LeafStructBuildSpec, LeafStructMemberKind, MemberChildToBuild, NodeChildToBuild,
|
EnumRuleChildKind, LeafEnumBuildSpec, LeafStructBuildSpec, LeafStructMemberKind,
|
||||||
|
MemberChildToBuild, NodeChildToBuild, PolymorphicBuildBuildSpec, PolymorphicTypeBuildSpec,
|
||||||
StructBuildSpec, StructChildSpec, VecChild, VecChildToBuild,
|
StructBuildSpec, StructChildSpec, VecChild, VecChildToBuild,
|
||||||
};
|
};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
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(|child| match child {
|
||||||
|
AlternativeChild::Skip => None,
|
||||||
|
AlternativeChild::Build(build_child) => Some(format_ident!("{}", build_child.name())),
|
||||||
|
})
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let accessors = alternative_build
|
||||||
|
.children()
|
||||||
|
.map(|child| match child {
|
||||||
|
AlternativeChild::Skip => None,
|
||||||
|
AlternativeChild::Build(build_child) => {
|
||||||
|
let child_ident = format_ident!("{}", build_child.name());
|
||||||
|
let child_ident_mut = format_ident!("{}_mut", build_child.name());
|
||||||
|
let child_type_ident = format_ident!("{}", build_child.kind());
|
||||||
|
Some(quote! {
|
||||||
|
pub fn #child_ident(&self) -> &#child_type_ident {
|
||||||
|
&self.#child_ident
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn #child_ident_mut(&mut self) -> &mut #child_type_ident {
|
||||||
|
&mut self.#child_ident
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.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),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#(#accessors)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_polymorphic_type_type(build_spec: &PolymorphicTypeBuildSpec) -> 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 {
|
fn make_enum_type(build_spec: &EnumBuildSpec) -> TokenStream {
|
||||||
let children: Vec<TokenStream> = build_spec
|
let children: Vec<TokenStream> = build_spec
|
||||||
.rules()
|
.rules()
|
||||||
@ -348,5 +453,12 @@ pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> {
|
|||||||
Some(make_leaf_struct_type(leaf_struct_build_spec))
|
Some(make_leaf_struct_type(leaf_struct_build_spec))
|
||||||
}
|
}
|
||||||
BuildSpec::Production(_) => None,
|
BuildSpec::Production(_) => None,
|
||||||
|
BuildSpec::Polymorphic(polymorphic_build_spec) => {
|
||||||
|
Some(make_polymorphic_type_type(polymorphic_build_spec))
|
||||||
|
}
|
||||||
|
BuildSpec::PolymorphicBuild(polymorphic_build_build_spec) => {
|
||||||
|
Some(make_polymorphic_build_type(polymorphic_build_build_spec))
|
||||||
|
}
|
||||||
|
BuildSpec::PolymorphicEnum(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3
examples/forty_two.dm
Normal file
3
examples/forty_two.dm
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fn main()
|
||||||
|
println 42
|
||||||
|
end
|
||||||
19
examples/worlds.dm
Normal file
19
examples/worlds.dm
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
class World(pub name: String, pub color: String) end
|
||||||
|
|
||||||
|
fn getWorlds() -> List<World> = [
|
||||||
|
World('Mercury', 'Red'),
|
||||||
|
World('Earth', 'Blue'),
|
||||||
|
World('Jupiter', 'Orange')
|
||||||
|
]
|
||||||
|
|
||||||
|
fn findWorldByColor(worlds: List<World>, color: String) -> String
|
||||||
|
worlds.find { it.color == color }
|
||||||
|
.map { it.name }
|
||||||
|
.expect "No world has the given color ${color}"
|
||||||
|
end
|
||||||
|
|
||||||
|
fn main()
|
||||||
|
let worlds = getWorlds()
|
||||||
|
let blueWorld = findWorldByColor(worlds, 'Blue')
|
||||||
|
println "Hello, ${blueWorld}!"
|
||||||
|
end
|
||||||
@ -45,14 +45,14 @@ pub mod node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub mod build {
|
pub mod build {
|
||||||
//noinspection RsUnusedImport
|
use pest::iterators::Pairs;
|
||||||
use crate::parser::Rule;
|
|
||||||
//noinspection RsUnusedImport
|
|
||||||
use pest::iterators::Pair;
|
|
||||||
//noinspection RsUnusedImport
|
|
||||||
use crate::ast::node::*;
|
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/src/ast/build.rs"));
|
include!(concat!(env!("OUT_DIR"), "/src/ast/build.rs"));
|
||||||
|
|
||||||
|
pub fn build_ast(parsed_pairs: &mut Pairs<Rule>) -> Box<CompilationUnit> {
|
||||||
|
let compilation_unit_pair = parsed_pairs.next().unwrap();
|
||||||
|
Box::new(build_compilation_unit(compilation_unit_pair))
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod build_tests {
|
mod build_tests {
|
||||||
@ -102,5 +102,42 @@ pub mod build {
|
|||||||
assert_eq!(backtick_string.inners().count(), 2);
|
assert_eq!(backtick_string.inners().count(), 2);
|
||||||
assert_eq!(backtick_string.expressions().count(), 1);
|
assert_eq!(backtick_string.expressions().count(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn d_string_expression_simple() {
|
||||||
|
let pair = parse(Rule::DStringExpression, "${thing}");
|
||||||
|
let d_string_expression = build_d_string_expression(pair);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn d_string_inner() {
|
||||||
|
let pair = parse(Rule::DStringInner, "Hello!");
|
||||||
|
let d_string_inner = build_d_string_inner(pair);
|
||||||
|
assert_eq!("Hello!", d_string_inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn d_string_mixed() {
|
||||||
|
let pair = parse(Rule::DString, "\"Hello, ${world}!\"");
|
||||||
|
let d_string = build_d_string(pair);
|
||||||
|
assert_eq!(d_string.inners().count(), 2);
|
||||||
|
assert_eq!(d_string.expressions().count(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn expression_simple_call() {
|
||||||
|
let pair = parse(Rule::Expression, "hello(42)");
|
||||||
|
let expression = build_expression(pair);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod pretty_print {
|
||||||
|
use crate::util::indent_writer::IndentWriter;
|
||||||
|
|
||||||
|
pub trait PrettyPrint {
|
||||||
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/src/ast/pretty_print.rs"));
|
||||||
|
}
|
||||||
|
|||||||
@ -1,58 +1,55 @@
|
|||||||
// mod name_analysis;
|
// mod name_analysis;
|
||||||
// mod p3;
|
mod p3;
|
||||||
// mod unparse;
|
// mod unparse;
|
||||||
//
|
|
||||||
// use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
//
|
|
||||||
// use crate::name_analysis::name_analysis;
|
// use crate::name_analysis::name_analysis;
|
||||||
// use crate::p3::pretty_print_parse;
|
use crate::p3::pretty_print_parse;
|
||||||
// use crate::unparse::unparse;
|
// use crate::unparse::unparse;
|
||||||
// use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
//
|
|
||||||
// #[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
// #[command(name = "dmc")]
|
#[command(name = "dmc")]
|
||||||
// #[command(about = "Deimos Compiler", long_about = None)]
|
#[command(about = "Deimos Compiler", long_about = None)]
|
||||||
// struct Cli {
|
struct Cli {
|
||||||
// #[command(subcommand)]
|
#[command(subcommand)]
|
||||||
// command: Commands,
|
command: Commands,
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// #[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
// enum Commands {
|
enum Commands {
|
||||||
// #[command(arg_required_else_help = true)]
|
#[command(arg_required_else_help = true)]
|
||||||
// Unparse {
|
Unparse {
|
||||||
// paths: Vec<PathBuf>,
|
paths: Vec<PathBuf>,
|
||||||
// },
|
},
|
||||||
// P3 {
|
P3 {
|
||||||
// paths: Vec<PathBuf>,
|
paths: Vec<PathBuf>,
|
||||||
// },
|
},
|
||||||
// NameAnalysis {
|
NameAnalysis {
|
||||||
// paths: Vec<PathBuf>,
|
paths: Vec<PathBuf>,
|
||||||
// },
|
},
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// fn main() {
|
|
||||||
// let args = Cli::parse();
|
|
||||||
// match args.command {
|
|
||||||
// Commands::Unparse { paths } => {
|
|
||||||
// for path in paths {
|
|
||||||
// unparse(&path);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Commands::P3 { paths } => {
|
|
||||||
// for path in paths {
|
|
||||||
// pretty_print_parse(&path)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Commands::NameAnalysis { paths } => {
|
|
||||||
// let result = name_analysis(&paths);
|
|
||||||
// if let Err(e) = result {
|
|
||||||
// eprintln!("{}", e)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
panic!("TODO")
|
let args = Cli::parse();
|
||||||
|
match args.command {
|
||||||
|
// Commands::Unparse { paths } => {
|
||||||
|
// for path in paths {
|
||||||
|
// unparse(&path);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
Commands::P3 { paths } => {
|
||||||
|
for path in paths {
|
||||||
|
pretty_print_parse(&path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Commands::NameAnalysis { paths } => {
|
||||||
|
// let result = name_analysis(&paths);
|
||||||
|
// if let Err(e) = result {
|
||||||
|
// eprintln!("{}", e)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
_ => todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,8 +10,7 @@ pub fn pretty_print_parse(path: &PathBuf) {
|
|||||||
let parse_result = DeimosParser::parse(Rule::CompilationUnit, &src);
|
let parse_result = DeimosParser::parse(Rule::CompilationUnit, &src);
|
||||||
match parse_result {
|
match parse_result {
|
||||||
Ok(mut pairs) => {
|
Ok(mut pairs) => {
|
||||||
let compilation_unit_pair = pairs.next().unwrap();
|
let compilation_unit = build_ast(&mut pairs);
|
||||||
let compilation_unit = build_ast(&path.display().to_string(), 0, compilation_unit_pair);
|
|
||||||
let mut indent_writer = IndentWriter::new(0, " ", Box::new(std::io::stdout()));
|
let mut indent_writer = IndentWriter::new(0, " ", Box::new(std::io::stdout()));
|
||||||
compilation_unit
|
compilation_unit
|
||||||
.pretty_print(&mut indent_writer)
|
.pretty_print(&mut indent_writer)
|
||||||
@ -291,6 +291,9 @@ Class:
|
|||||||
- class_level_declarations:
|
- class_level_declarations:
|
||||||
rule: ClassLevelDeclaration
|
rule: ClassLevelDeclaration
|
||||||
vec: true
|
vec: true
|
||||||
|
- end_kw:
|
||||||
|
rule: End
|
||||||
|
skip: true
|
||||||
|
|
||||||
# Function constructs
|
# Function constructs
|
||||||
Function:
|
Function:
|
||||||
@ -305,6 +308,8 @@ Function:
|
|||||||
skip: true
|
skip: true
|
||||||
- generics:
|
- generics:
|
||||||
rule: GenericParameters
|
rule: GenericParameters
|
||||||
|
build:
|
||||||
|
or_else_default: true
|
||||||
- identifier
|
- identifier
|
||||||
- parameters
|
- parameters
|
||||||
- return_type:
|
- return_type:
|
||||||
@ -564,53 +569,153 @@ ForStatement:
|
|||||||
|
|
||||||
# Expressions
|
# Expressions
|
||||||
Expression:
|
Expression:
|
||||||
children:
|
polymorphic_type:
|
||||||
- ternary_expression
|
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
|
||||||
|
- List:
|
||||||
|
inner:
|
||||||
|
kind: ListExpression
|
||||||
|
build:
|
||||||
|
kind: TernaryExpression
|
||||||
TernaryExpression:
|
TernaryExpression:
|
||||||
children:
|
polymorphic_build:
|
||||||
- or_expression
|
return_type: Expression
|
||||||
- ternary_alternatives:
|
alternatives:
|
||||||
optional: true
|
- test:
|
||||||
TernaryAlternatives:
|
number_of_pairs: 1
|
||||||
children:
|
action:
|
||||||
- ternary_true_alternative
|
return_build:
|
||||||
- ternary_false_alternative
|
kind: OrExpression
|
||||||
|
- test:
|
||||||
|
number_of_pairs: 3
|
||||||
|
action:
|
||||||
|
build:
|
||||||
|
enum_variant: Ternary
|
||||||
|
children:
|
||||||
|
- test:
|
||||||
|
kind: Expression
|
||||||
|
rule: OrExpression
|
||||||
|
- on_true:
|
||||||
|
kind: Expression
|
||||||
|
rule: TernaryTrueAlternative
|
||||||
|
- on_false:
|
||||||
|
kind: Expression
|
||||||
|
rule: TernaryFalseAlternative
|
||||||
TernaryTrueAlternative:
|
TernaryTrueAlternative:
|
||||||
children:
|
produce:
|
||||||
- expression
|
kind:
|
||||||
|
node: Expression
|
||||||
TernaryFalseAlternative:
|
TernaryFalseAlternative:
|
||||||
children:
|
produce:
|
||||||
- expression
|
kind:
|
||||||
|
node: Expression
|
||||||
OrExpression:
|
OrExpression:
|
||||||
children:
|
polymorphic_build:
|
||||||
- left:
|
return_type: Expression
|
||||||
rule: AndExpression
|
alternatives:
|
||||||
- or_sym:
|
- test:
|
||||||
rule: Or
|
number_of_pairs: 1
|
||||||
skip: true
|
action:
|
||||||
- right:
|
return_build:
|
||||||
rule: Expression
|
kind: AndExpression
|
||||||
optional: true
|
- 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
|
||||||
AndExpression:
|
AndExpression:
|
||||||
children:
|
polymorphic_build:
|
||||||
- left:
|
return_type: Expression
|
||||||
rule: ComparisonExpression
|
alternatives:
|
||||||
- and_sym:
|
- test:
|
||||||
rule: And
|
number_of_pairs: 1
|
||||||
skip: true
|
action:
|
||||||
- right:
|
return_build:
|
||||||
rule: Expression
|
kind: ComparisonExpression
|
||||||
optional: true
|
- 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
|
||||||
ComparisonExpression:
|
ComparisonExpression:
|
||||||
children:
|
polymorphic_build:
|
||||||
- left:
|
return_type: Expression
|
||||||
rule: ShiftExpression
|
alternatives:
|
||||||
- operator:
|
- test:
|
||||||
rule: ComparisonOperator
|
number_of_pairs: 1
|
||||||
optional: true
|
action:
|
||||||
- right:
|
return_build:
|
||||||
rule: Expression
|
kind: ShiftExpression
|
||||||
optional: true
|
- test:
|
||||||
|
number_of_pairs: 3
|
||||||
|
action:
|
||||||
|
build:
|
||||||
|
enum_variant: Comparison
|
||||||
|
children:
|
||||||
|
- left:
|
||||||
|
kind: Expression
|
||||||
|
rule: ShiftExpression
|
||||||
|
- operator:
|
||||||
|
kind: ComparisonOperator
|
||||||
|
rule: ComparisonOperator
|
||||||
|
- right:
|
||||||
|
kind: Expression
|
||||||
|
rule: Expression
|
||||||
ComparisonOperator:
|
ComparisonOperator:
|
||||||
leaf_rules:
|
leaf_rules:
|
||||||
- Greater
|
- Greater
|
||||||
@ -620,64 +725,144 @@ ComparisonOperator:
|
|||||||
- EqualTo
|
- EqualTo
|
||||||
- NotEqualTo
|
- NotEqualTo
|
||||||
ShiftExpression:
|
ShiftExpression:
|
||||||
children:
|
polymorphic_build:
|
||||||
- left:
|
return_type: Expression
|
||||||
rule: AdditiveExpression
|
alternatives:
|
||||||
- operator:
|
- test:
|
||||||
rule: ShiftOperator
|
number_of_pairs: 1
|
||||||
optional: true
|
action:
|
||||||
- right:
|
return_build:
|
||||||
rule: Expression
|
kind: AdditiveExpression
|
||||||
optional: true
|
- test:
|
||||||
|
number_of_pairs: 3
|
||||||
|
action:
|
||||||
|
build:
|
||||||
|
enum_variant: Shift
|
||||||
|
children:
|
||||||
|
- left:
|
||||||
|
kind: Expression
|
||||||
|
rule: AdditiveExpression
|
||||||
|
- operator:
|
||||||
|
kind: ShiftOperator
|
||||||
|
rule: ShiftOperator
|
||||||
|
- right:
|
||||||
|
kind: Expression
|
||||||
|
rule: Expression
|
||||||
ShiftOperator:
|
ShiftOperator:
|
||||||
leaf_rules:
|
leaf_rules:
|
||||||
- LeftShift
|
- LeftShift
|
||||||
- RightShift
|
- RightShift
|
||||||
AdditiveExpression:
|
AdditiveExpression:
|
||||||
children:
|
polymorphic_build:
|
||||||
- left:
|
return_type: Expression
|
||||||
rule: MultiplicativeExpression
|
alternatives:
|
||||||
- operator:
|
- test:
|
||||||
rule: AdditiveOperator
|
number_of_pairs: 1
|
||||||
optional: true
|
action:
|
||||||
- right:
|
return_build:
|
||||||
rule: Expression
|
kind: MultiplicativeExpression
|
||||||
optional: true
|
- test:
|
||||||
|
number_of_pairs: 3
|
||||||
|
action:
|
||||||
|
build:
|
||||||
|
enum_variant: Additive
|
||||||
|
children:
|
||||||
|
- left:
|
||||||
|
kind: Expression
|
||||||
|
rule: MultiplicativeExpression
|
||||||
|
- operator:
|
||||||
|
kind: AdditiveOperator
|
||||||
|
rule: AdditiveOperator
|
||||||
|
- right:
|
||||||
|
kind: Expression
|
||||||
|
rule: Expression
|
||||||
AdditiveOperator:
|
AdditiveOperator:
|
||||||
leaf_rules:
|
leaf_rules:
|
||||||
- Add
|
- Add
|
||||||
- Subtract
|
- Subtract
|
||||||
MultiplicativeExpression:
|
MultiplicativeExpression:
|
||||||
children:
|
polymorphic_build:
|
||||||
- left:
|
return_type: Expression
|
||||||
rule: PrefixExpression
|
alternatives:
|
||||||
- operator:
|
- test:
|
||||||
rule: MultiplicativeOperator
|
number_of_pairs: 1
|
||||||
optional: true
|
action:
|
||||||
- right:
|
return_build:
|
||||||
rule: Expression
|
kind: PrefixExpression
|
||||||
optional: true
|
- test:
|
||||||
|
number_of_pairs: 3
|
||||||
|
action:
|
||||||
|
build:
|
||||||
|
enum_variant: Multiplicative
|
||||||
|
children:
|
||||||
|
- left:
|
||||||
|
kind: Expression
|
||||||
|
rule: PrefixExpression
|
||||||
|
- operator:
|
||||||
|
kind: MultiplicativeOperator
|
||||||
|
rule: MultiplicativeOperator
|
||||||
|
- right:
|
||||||
|
kind: Expression
|
||||||
|
rule: Expression
|
||||||
MultiplicativeOperator:
|
MultiplicativeOperator:
|
||||||
leaf_rules:
|
leaf_rules:
|
||||||
- Multiply
|
- Multiply
|
||||||
- Divide
|
- Divide
|
||||||
- Modulo
|
- Modulo
|
||||||
PrefixExpression:
|
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:
|
children:
|
||||||
- operators:
|
- operators:
|
||||||
rule: PrefixOperator
|
rule: PrefixOperator
|
||||||
vec: true
|
vec: true
|
||||||
- right:
|
|
||||||
rule: SuffixExpression
|
|
||||||
PrefixOperator:
|
PrefixOperator:
|
||||||
leaf_rules:
|
leaf_rules:
|
||||||
- Spread
|
- Spread
|
||||||
- Not
|
- Not
|
||||||
- Negative
|
- Negative
|
||||||
SuffixExpression:
|
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:
|
children:
|
||||||
- left:
|
|
||||||
rule: PrimaryExpression
|
|
||||||
- operators:
|
- operators:
|
||||||
rule: SuffixOperator
|
rule: SuffixOperator
|
||||||
vec: true
|
vec: true
|
||||||
@ -697,11 +882,27 @@ ObjectIndex:
|
|||||||
children:
|
children:
|
||||||
- expression
|
- expression
|
||||||
PrimaryExpression:
|
PrimaryExpression:
|
||||||
rules:
|
polymorphic_enum:
|
||||||
- Literal
|
return_type: Expression
|
||||||
- FullyQualifiedName
|
rules:
|
||||||
- Closure
|
- Literal:
|
||||||
- ParenthesizedExpression
|
wrap:
|
||||||
|
enum_variant: Literal
|
||||||
|
- FullyQualifiedName:
|
||||||
|
wrap:
|
||||||
|
enum_variant: Fqn
|
||||||
|
- Closure:
|
||||||
|
wrap:
|
||||||
|
enum_variant: Closure
|
||||||
|
- ListExpression:
|
||||||
|
wrap:
|
||||||
|
enum_variant: List
|
||||||
|
- ParenthesizedExpression:
|
||||||
|
return_build:
|
||||||
|
kind: Expression
|
||||||
|
ListExpression:
|
||||||
|
children:
|
||||||
|
- expression_list
|
||||||
ParenthesizedExpression:
|
ParenthesizedExpression:
|
||||||
children:
|
children:
|
||||||
- expression
|
- expression
|
||||||
|
|||||||
@ -596,40 +596,52 @@ Expression = {
|
|||||||
|
|
||||||
TernaryExpression = {
|
TernaryExpression = {
|
||||||
OrExpression
|
OrExpression
|
||||||
~ ( TernaryAlternatives )?
|
~ TernaryRhs*
|
||||||
}
|
}
|
||||||
|
|
||||||
TernaryAlternatives = {
|
TernaryRhs = {
|
||||||
TernaryTrueAlternative
|
TernaryTrueAlternative
|
||||||
~ TernaryFalseAlternative
|
~ TernaryFalseAlternative
|
||||||
}
|
}
|
||||||
|
|
||||||
TernaryTrueAlternative = {
|
TernaryTrueAlternative = {
|
||||||
"?"
|
"?"
|
||||||
~ Expression
|
~ OrExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
TernaryFalseAlternative = {
|
TernaryFalseAlternative = {
|
||||||
":"
|
":"
|
||||||
~ Expression
|
~ OrExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
OrExpression = {
|
OrExpression = {
|
||||||
AndExpression
|
AndExpression
|
||||||
~ ( Or ~ Expression )?
|
~ OrRhs*
|
||||||
|
}
|
||||||
|
|
||||||
|
OrRhs = {
|
||||||
|
Or
|
||||||
|
~ AndExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
AndExpression = {
|
AndExpression = {
|
||||||
ComparisonExpression
|
ComparisonExpression
|
||||||
~ ( And ~ Expression )?
|
~ AndRhs*
|
||||||
|
}
|
||||||
|
|
||||||
|
AndRhs = {
|
||||||
|
And
|
||||||
|
~ ComparisonExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
ComparisonExpression = {
|
ComparisonExpression = {
|
||||||
ShiftExpression
|
ShiftExpression
|
||||||
~ (
|
~ ComparisonRhs*
|
||||||
ComparisonOperator
|
}
|
||||||
~ Expression
|
|
||||||
)?
|
ComparisonRhs = {
|
||||||
|
ComparisonOperator
|
||||||
|
~ Expression
|
||||||
}
|
}
|
||||||
|
|
||||||
ComparisonOperator = {
|
ComparisonOperator = {
|
||||||
@ -643,10 +655,12 @@ ComparisonOperator = {
|
|||||||
|
|
||||||
ShiftExpression = {
|
ShiftExpression = {
|
||||||
AdditiveExpression
|
AdditiveExpression
|
||||||
~ (
|
~ ShiftRhs*
|
||||||
ShiftOperator
|
}
|
||||||
~ Expression
|
|
||||||
)?
|
ShiftRhs = {
|
||||||
|
ShiftOperator
|
||||||
|
~ AdditiveExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
ShiftOperator = {
|
ShiftOperator = {
|
||||||
@ -656,10 +670,12 @@ ShiftOperator = {
|
|||||||
|
|
||||||
AdditiveExpression = {
|
AdditiveExpression = {
|
||||||
MultiplicativeExpression
|
MultiplicativeExpression
|
||||||
~ (
|
~ AdditiveRhs*
|
||||||
AdditiveOperator
|
}
|
||||||
~ Expression
|
|
||||||
)?
|
AdditiveRhs = {
|
||||||
|
AdditiveOperator
|
||||||
|
~ MultiplicativeExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
AdditiveOperator = {
|
AdditiveOperator = {
|
||||||
@ -669,10 +685,12 @@ AdditiveOperator = {
|
|||||||
|
|
||||||
MultiplicativeExpression = {
|
MultiplicativeExpression = {
|
||||||
PrefixExpression
|
PrefixExpression
|
||||||
~ (
|
~ MultiplicativeRhs*
|
||||||
MultiplicativeOperator
|
}
|
||||||
~ Expression
|
|
||||||
)?
|
MultiplicativeRhs = {
|
||||||
|
MultiplicativeOperator
|
||||||
|
~ PrefixExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiplicativeOperator = {
|
MultiplicativeOperator = {
|
||||||
@ -682,10 +700,14 @@ MultiplicativeOperator = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PrefixExpression = {
|
PrefixExpression = {
|
||||||
PrefixOperator*
|
PrefixOperators?
|
||||||
~ SuffixExpression
|
~ SuffixExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrefixOperators = {
|
||||||
|
PrefixOperator+
|
||||||
|
}
|
||||||
|
|
||||||
PrefixOperator = {
|
PrefixOperator = {
|
||||||
Spread
|
Spread
|
||||||
| Not
|
| Not
|
||||||
@ -694,7 +716,11 @@ PrefixOperator = {
|
|||||||
|
|
||||||
SuffixExpression = {
|
SuffixExpression = {
|
||||||
PrimaryExpression
|
PrimaryExpression
|
||||||
~ SuffixOperator*
|
~ SuffixOperators?
|
||||||
|
}
|
||||||
|
|
||||||
|
SuffixOperators = {
|
||||||
|
SuffixOperator+
|
||||||
}
|
}
|
||||||
|
|
||||||
SuffixOperator = {
|
SuffixOperator = {
|
||||||
@ -720,9 +746,16 @@ PrimaryExpression = {
|
|||||||
Literal
|
Literal
|
||||||
| FullyQualifiedName
|
| FullyQualifiedName
|
||||||
| Closure
|
| Closure
|
||||||
|
| ListExpression
|
||||||
| ParenthesizedExpression
|
| ParenthesizedExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ListExpression = {
|
||||||
|
"["
|
||||||
|
~ ExpressionList?
|
||||||
|
~ "]"
|
||||||
|
}
|
||||||
|
|
||||||
ParenthesizedExpression = {
|
ParenthesizedExpression = {
|
||||||
"("
|
"("
|
||||||
~ Expression
|
~ Expression
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user