WIP refactor of deserialization and ast code generation.
This commit is contained in:
parent
2aee2cdd4e
commit
b5cdb8dd29
@ -1,11 +1,4 @@
|
|||||||
use crate::spec::{
|
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};
|
||||||
BooleanBuild, BuildSpec, ChildSpec, EnumBuildSpec, EnumRule, LeafEnumBuildSpec, LeafEnumRule,
|
|
||||||
LeafEnumRuleBuild, LeafEnumRuleBuildChild, LeafStructBuildSpec, LeafStructChild,
|
|
||||||
LeafStructChildType, SingleBooleanChildToBuild, SingleChild, SingleChildToBuild,
|
|
||||||
SingleLiteralChildToBuild, SingleTypeChildToBuild, SkipChild, StructBuildSpec, VecChild,
|
|
||||||
VecChildToBuild, VecTypeChildToBuild,
|
|
||||||
};
|
|
||||||
use crate::util::make_build_fn_name;
|
|
||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
use yaml_rust2::{Yaml, YamlLoader};
|
use yaml_rust2::{Yaml, YamlLoader};
|
||||||
|
|
||||||
@ -13,150 +6,6 @@ fn get_as_bool(yaml: &Yaml) -> bool {
|
|||||||
yaml.as_bool().unwrap_or_else(|| false)
|
yaml.as_bool().unwrap_or_else(|| false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_vec_child_to_build(build: &Yaml, name: &str, rule: &str) -> VecChildToBuild {
|
|
||||||
if build.is_hash() {
|
|
||||||
let build_type = build["build"].as_str().unwrap();
|
|
||||||
let var_name = build["var"]
|
|
||||||
.as_str()
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.unwrap_or_else(|| build_type.to_case(Case::Snake));
|
|
||||||
let with = build["with"]
|
|
||||||
.as_str()
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.unwrap_or_else(|| make_build_fn_name(build_type));
|
|
||||||
|
|
||||||
VecChildToBuild::Type(VecTypeChildToBuild::new(build_type, &var_name, &with))
|
|
||||||
} else {
|
|
||||||
let build_as_str = build.as_str().unwrap_or(rule);
|
|
||||||
VecChildToBuild::Type(VecTypeChildToBuild::new(
|
|
||||||
build_as_str,
|
|
||||||
name,
|
|
||||||
make_build_fn_name(build_as_str).as_str(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_vec_child(name: &str, rule: &str, build: &Yaml) -> ChildSpec {
|
|
||||||
ChildSpec::VecChild(VecChild::new(
|
|
||||||
name,
|
|
||||||
rule,
|
|
||||||
get_vec_child_to_build(build, name, rule),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_single_child_to_build(
|
|
||||||
name: &str,
|
|
||||||
rule: &str,
|
|
||||||
optional: bool,
|
|
||||||
build: &Yaml,
|
|
||||||
) -> SingleChildToBuild {
|
|
||||||
if build.is_hash() {
|
|
||||||
match build["type"].as_str() {
|
|
||||||
Some(r#type) => {
|
|
||||||
let var_name = build["var"]
|
|
||||||
.as_str()
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.unwrap_or(name.to_string());
|
|
||||||
match r#type {
|
|
||||||
"boolean" => {
|
|
||||||
if yaml_is_string(&build["on"], "rule_present") {
|
|
||||||
SingleChildToBuild::Boolean(SingleBooleanChildToBuild::new(
|
|
||||||
&var_name,
|
|
||||||
BooleanBuild::RulePresent,
|
|
||||||
))
|
|
||||||
} else if yaml_is_string(&build["from"], "parse_whole_pair") {
|
|
||||||
SingleChildToBuild::Boolean(SingleBooleanChildToBuild::new(
|
|
||||||
&var_name,
|
|
||||||
BooleanBuild::ParseWholePair,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
panic!("invalid build on/from with type boolean");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"i32" => SingleChildToBuild::Int(SingleLiteralChildToBuild::new(&var_name)),
|
|
||||||
"i64" => SingleChildToBuild::Long(SingleLiteralChildToBuild::new(&var_name)),
|
|
||||||
"f64" => SingleChildToBuild::Double(SingleLiteralChildToBuild::new(&var_name)),
|
|
||||||
"string" => {
|
|
||||||
SingleChildToBuild::String(SingleLiteralChildToBuild::new(&var_name))
|
|
||||||
}
|
|
||||||
_ => panic!("unsupported build type: {}", r#type),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
let or_else = build["or_else"]
|
|
||||||
.as_str()
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.or_else(|| {
|
|
||||||
let or_else_default =
|
|
||||||
build["or_else_default"].as_bool().unwrap_or_else(|| false);
|
|
||||||
if or_else_default {
|
|
||||||
Some(String::from("default"))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
});
|
|
||||||
SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(
|
|
||||||
rule, or_else, optional,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
match build.as_str() {
|
|
||||||
Some(s) => SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(
|
|
||||||
s, None, optional,
|
|
||||||
)),
|
|
||||||
None => SingleChildToBuild::Type(SingleTypeChildToBuild::new(
|
|
||||||
&rule,
|
|
||||||
&name,
|
|
||||||
&make_build_fn_name(&rule),
|
|
||||||
None,
|
|
||||||
optional,
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_single_child(name: &str, rule: &str, optional: bool, build: &Yaml) -> ChildSpec {
|
|
||||||
ChildSpec::SingleChild(SingleChild::new(
|
|
||||||
name,
|
|
||||||
rule,
|
|
||||||
get_single_child_to_build(name, rule, optional, build),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_child_specs(children: &Yaml) -> Vec<ChildSpec> {
|
|
||||||
children
|
|
||||||
.as_vec()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.map(|child_spec| {
|
|
||||||
if child_spec.is_hash() {
|
|
||||||
let (name, props) = unwrap_single_member_hash(child_spec);
|
|
||||||
|
|
||||||
let rule = props["rule"]
|
|
||||||
.as_str()
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.unwrap_or(name.to_case(Case::Pascal));
|
|
||||||
|
|
||||||
if get_as_bool(&props["skip"]) {
|
|
||||||
return ChildSpec::SkipChild(SkipChild::new(&name, &rule));
|
|
||||||
}
|
|
||||||
|
|
||||||
let build = &props["build"];
|
|
||||||
|
|
||||||
if get_as_bool(&props["vec"]) {
|
|
||||||
get_vec_child(&name, &rule, build)
|
|
||||||
} else {
|
|
||||||
let optional = get_as_bool(&props["optional"]);
|
|
||||||
get_single_child(&name, &rule, optional, build)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ChildSpec::SingleChild(SingleChild::from_name_snake(child_spec.as_str().unwrap()))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unwrap_single_member_hash(hash: &Yaml) -> (String, &Yaml) {
|
fn unwrap_single_member_hash(hash: &Yaml) -> (String, &Yaml) {
|
||||||
let as_hash = hash.as_hash().unwrap();
|
let as_hash = hash.as_hash().unwrap();
|
||||||
if as_hash.is_empty() {
|
if as_hash.is_empty() {
|
||||||
@ -169,110 +18,267 @@ fn unwrap_single_member_hash(hash: &Yaml) -> (String, &Yaml) {
|
|||||||
(key_as_string, member_value)
|
(key_as_string, member_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_leaf_enum_rules(rules: &Yaml) -> Vec<LeafEnumRule> {
|
fn deserialize_production_spec(rule: &str, production_yaml: &Yaml) -> ProductionBuildSpec {
|
||||||
rules
|
let kind = match production_yaml["kind"].as_str().unwrap() {
|
||||||
.as_vec()
|
"int" => ProductionKind::Int,
|
||||||
.unwrap()
|
"long" => ProductionKind::Long,
|
||||||
.iter()
|
"double" => ProductionKind::Double,
|
||||||
.map(|rule| {
|
"boolean" => ProductionKind::Boolean,
|
||||||
if rule.is_hash() {
|
"string" => {
|
||||||
let (rule_as_string, rule_hash) = unwrap_single_member_hash(rule);
|
let from = match production_yaml["from"].as_str().unwrap() {
|
||||||
if get_as_bool(&rule_hash["child"]) {
|
"string_inner" => ProductionStringFrom::StringInner,
|
||||||
let build = LeafEnumRuleBuild::new(
|
"whole_pair" => ProductionStringFrom::WholePair,
|
||||||
&rule_as_string,
|
_ => panic!("invalid from: {}", production_yaml["from"].as_str().unwrap()),
|
||||||
Some(LeafEnumRuleBuildChild::new(
|
|
||||||
&rule_as_string,
|
|
||||||
&make_build_fn_name(&rule_as_string),
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
LeafEnumRule::new(&rule_as_string, build)
|
|
||||||
} else {
|
|
||||||
panic!(
|
|
||||||
"if a leaf_enum rule is a hash, its child prop must be present and true"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let rule_as_str = rule.as_str().unwrap();
|
|
||||||
let build = LeafEnumRuleBuild::new(rule_as_str, None);
|
|
||||||
LeafEnumRule::new(rule_as_str, build)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_enum_rules(rule_specs: &Yaml) -> Vec<EnumRule> {
|
|
||||||
rule_specs
|
|
||||||
.as_vec()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.map(|rule_spec| {
|
|
||||||
if rule_spec.is_hash() {
|
|
||||||
let rule = rule_spec["rule"].as_str().unwrap();
|
|
||||||
let build = rule_spec["build"].as_str().unwrap();
|
|
||||||
let with = if !rule_spec["with"].is_badvalue() {
|
|
||||||
rule_spec.as_str().unwrap().to_string()
|
|
||||||
} else {
|
|
||||||
make_build_fn_name(build)
|
|
||||||
};
|
};
|
||||||
|
ProductionKind::String(from)
|
||||||
EnumRule::new(rule, build, &with)
|
},
|
||||||
} else {
|
_ => panic!("invalid kind: {}", production_yaml["kind"].as_str().unwrap()),
|
||||||
EnumRule::from_rule(rule_spec.as_str().unwrap())
|
};
|
||||||
|
ProductionBuildSpec::new(rule, kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_leaf_enum_rule(rule_yaml: &Yaml) -> Box<LeafEnumRule> {
|
||||||
|
Box::new(LeafEnumRule::new(rule_yaml.as_str().unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_leaf_enum_rules(rules_yaml: &Yaml) -> Vec<Box<LeafEnumRule>> {
|
||||||
|
rules_yaml
|
||||||
|
.as_vec()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|rule_yaml| {
|
||||||
|
deserialize_leaf_enum_rule(rule_yaml)
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_leaf_struct_child_specs(children: &Yaml) -> Vec<LeafStructChild> {
|
fn deserialize_enum_rule_custom_child(rule_props: &Yaml) -> Option<Box<EnumRuleChild>> {
|
||||||
|
if !rule_props["child"].as_bool().unwrap() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let kind = match rule_props["kind"].as_str().unwrap() {
|
||||||
|
"int" => EnumRuleChildKind::Int,
|
||||||
|
"long" => EnumRuleChildKind::Long,
|
||||||
|
"double" => EnumRuleChildKind::Double,
|
||||||
|
"usize" => EnumRuleChildKind::USize,
|
||||||
|
"string" => EnumRuleChildKind::String,
|
||||||
|
"boolean" => EnumRuleChildKind::Boolean,
|
||||||
|
_ => 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)),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_enum_rule(rule_yaml: &Yaml) -> Box<EnumRule> {
|
||||||
|
if rule_yaml.is_hash() {
|
||||||
|
let (rule, rule_props) = unwrap_single_member_hash(rule_yaml);
|
||||||
|
Box::new(EnumRule::new(
|
||||||
|
&rule,
|
||||||
|
deserialize_enum_rule_custom_child(rule_props)
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
let rule_as_str = rule_yaml.as_str().unwrap();
|
||||||
|
Box::new(EnumRule::new(
|
||||||
|
rule_as_str,
|
||||||
|
Some(deserialize_enum_rule_node_child(rule_as_str)),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_enum_rules(rules_yaml: &Yaml) -> Vec<Box<EnumRule>> {
|
||||||
|
rules_yaml
|
||||||
|
.as_vec()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|rule_yaml| deserialize_enum_rule(rule_yaml))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_leaf_struct_member(name: &str, props: &Yaml) -> Box<LeafStructMember> {
|
||||||
|
let kind = props["kind"].as_str().unwrap();
|
||||||
|
if kind == "string" {
|
||||||
|
Box::new(LeafStructMember::new(name, LeafStructMemberKind::String))
|
||||||
|
} else {
|
||||||
|
panic!("invalid member kind: {}", kind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_leaf_struct_members(members_yaml: &Yaml) -> Vec<Box<LeafStructMember>> {
|
||||||
|
members_yaml
|
||||||
|
.as_vec()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|member| {
|
||||||
|
let (member_name, member_props) = unwrap_single_member_hash(member);
|
||||||
|
deserialize_leaf_struct_member(&member_name, member_props)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_member_node_to_build(
|
||||||
|
rule: &str,
|
||||||
|
build_props: &Yaml,
|
||||||
|
optional: bool,
|
||||||
|
) -> Box<MemberChildToBuild> {
|
||||||
|
let or_else = build_props["or_else"]
|
||||||
|
.as_str()
|
||||||
|
.or_else(|| {
|
||||||
|
if get_as_bool(&build_props["or_else_default"]) {
|
||||||
|
Some("default")
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(ToString::to_string);
|
||||||
|
|
||||||
|
Box::new(MemberChildToBuild::Node(NodeChildToBuild::new(
|
||||||
|
rule, or_else, optional,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_member_boolean_to_build(name: &str) -> Box<MemberChildToBuild> {
|
||||||
|
Box::new(MemberChildToBuild::Boolean(BooleanChildToBuild::new(name)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_member_child_to_build(
|
||||||
|
name: &str,
|
||||||
|
rule: &str,
|
||||||
|
props: &Yaml,
|
||||||
|
optional: bool,
|
||||||
|
) -> Box<MemberChildToBuild> {
|
||||||
|
if props["build"].is_hash() {
|
||||||
|
let build_props = &props["build"];
|
||||||
|
let kind = build_props["kind"].as_str().or(Some("node")).unwrap();
|
||||||
|
if kind == "node" {
|
||||||
|
deserialize_member_node_to_build(rule, build_props, optional)
|
||||||
|
} else if kind == "boolean" {
|
||||||
|
deserialize_member_boolean_to_build(name)
|
||||||
|
} else {
|
||||||
|
panic!("unsupported kind: {}", kind)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("build is required for a member child")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_member_child(
|
||||||
|
name: &str,
|
||||||
|
rule: &str,
|
||||||
|
optional: bool,
|
||||||
|
props: &Yaml,
|
||||||
|
) -> Box<StructChildSpec> {
|
||||||
|
Box::new(StructChildSpec::MemberChild(MemberChild::new(
|
||||||
|
name,
|
||||||
|
rule,
|
||||||
|
deserialize_member_child_to_build(name, rule, props, optional),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_vec_node_child(name: &str, props: &Yaml) -> Box<StructChildSpec> {
|
||||||
|
let rule = props["rule"].as_str().unwrap();
|
||||||
|
Box::new(StructChildSpec::VecChild(VecChild::new(
|
||||||
|
name,
|
||||||
|
rule,
|
||||||
|
Box::new(VecChildToBuild::Node(VecNodeChildToBuild::new(rule))),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_vec_string_child(name: &str, props: &Yaml) -> Box<StructChildSpec> {
|
||||||
|
let rule = props["rule"].as_str().unwrap();
|
||||||
|
Box::new(StructChildSpec::VecChild(VecChild::new(
|
||||||
|
name,
|
||||||
|
rule,
|
||||||
|
Box::new(VecChildToBuild::String),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_vec_child(name: &str, props: &Yaml) -> Box<StructChildSpec> {
|
||||||
|
let kind = props["kind"].as_str().or_else(|| Some("node")).unwrap();
|
||||||
|
if kind == "node" {
|
||||||
|
deserialize_vec_node_child(name, props)
|
||||||
|
} else if kind == "string" {
|
||||||
|
deserialize_vec_string_child(name, props)
|
||||||
|
} else {
|
||||||
|
panic!("invalid kind: {}", kind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_skip_child(name: &str, rule: &str) -> Box<StructChildSpec> {
|
||||||
|
Box::new(StructChildSpec::SkipChild(SkipChild::new(name, rule)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_struct_hash_child(child: &Yaml) -> Box<StructChildSpec> {
|
||||||
|
let (name, props) = unwrap_single_member_hash(child);
|
||||||
|
|
||||||
|
let rule = props["rule"]
|
||||||
|
.as_str()
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.unwrap_or(name.to_case(Case::Pascal));
|
||||||
|
|
||||||
|
if get_as_bool(&props["skip"]) {
|
||||||
|
deserialize_skip_child(&name, &rule)
|
||||||
|
} else {
|
||||||
|
if get_as_bool(&props["vec"]) {
|
||||||
|
deserialize_vec_child(&name, props)
|
||||||
|
} else {
|
||||||
|
let optional = get_as_bool(&props["optional"]);
|
||||||
|
deserialize_member_child(&name, &rule, optional, props)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_struct_string_child(child: &Yaml) -> Box<StructChildSpec> {
|
||||||
|
let child_as_str = child.as_str().unwrap();
|
||||||
|
let child_name_pascal = child_as_str.to_case(Case::Pascal);
|
||||||
|
Box::new(StructChildSpec::MemberChild(MemberChild::new(
|
||||||
|
child_as_str,
|
||||||
|
&child_name_pascal,
|
||||||
|
Box::new(MemberChildToBuild::Node(NodeChildToBuild::new(
|
||||||
|
&child_name_pascal,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
))),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_struct_children(children: &Yaml) -> Vec<Box<StructChildSpec>> {
|
||||||
children
|
children
|
||||||
.as_vec()
|
.as_vec()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|child_spec| {
|
.map(|child_spec| {
|
||||||
let (name, hash) = unwrap_single_member_hash(child_spec);
|
if child_spec.is_hash() {
|
||||||
LeafStructChild::new(&name, LeafStructChildType::String)
|
deserialize_struct_hash_child(child_spec)
|
||||||
})
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn yaml_is_string(yaml: &Yaml, test: &str) -> bool {
|
|
||||||
match yaml.as_str() {
|
|
||||||
Some(s) => s == test,
|
|
||||||
None => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_build_spec(build_spec_name: &Yaml, build_spec: &Yaml) -> BuildSpec {
|
|
||||||
let build_spec_name_pascal = build_spec_name.as_str().unwrap();
|
|
||||||
let node_type = &build_spec["type"];
|
|
||||||
let children = &build_spec["children"];
|
|
||||||
let rules = &build_spec["rules"];
|
|
||||||
|
|
||||||
if yaml_is_string(node_type, "leaf_struct") && children.is_array() {
|
|
||||||
let child_specs = get_leaf_struct_child_specs(children);
|
|
||||||
BuildSpec::LeafStruct(LeafStructBuildSpec::new(
|
|
||||||
build_spec_name_pascal,
|
|
||||||
build_spec_name_pascal,
|
|
||||||
child_specs,
|
|
||||||
))
|
|
||||||
} else if children.is_array() {
|
|
||||||
let child_specs = get_child_specs(children);
|
|
||||||
BuildSpec::Struct(StructBuildSpec::from_name(
|
|
||||||
build_spec_name_pascal,
|
|
||||||
child_specs,
|
|
||||||
))
|
|
||||||
} else if yaml_is_string(node_type, "leaf_enum") && rules.is_array() {
|
|
||||||
let leaf_enum_rules = get_leaf_enum_rules(rules);
|
|
||||||
BuildSpec::LeafEnum(LeafEnumBuildSpec::from_name(
|
|
||||||
build_spec_name_pascal,
|
|
||||||
leaf_enum_rules,
|
|
||||||
))
|
|
||||||
} else if rules.is_array() {
|
|
||||||
// enum node
|
|
||||||
let enum_rules = get_enum_rules(rules);
|
|
||||||
BuildSpec::Enum(EnumBuildSpec::from_name(build_spec_name_pascal, enum_rules))
|
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected a node spec for either a struct, leaf_struct, enum, leaf_enum node type.");
|
deserialize_struct_string_child(child_spec)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_build_spec(build_spec_name: &str, build_spec: &Yaml) -> BuildSpec {
|
||||||
|
if build_spec["children"].is_array() {
|
||||||
|
let children = deserialize_struct_children(&build_spec["children"]);
|
||||||
|
BuildSpec::Struct(StructBuildSpec::new(build_spec_name, children))
|
||||||
|
} else if build_spec["members"].is_array() {
|
||||||
|
let members = deserialize_leaf_struct_members(&build_spec["members"]);
|
||||||
|
BuildSpec::LeafStruct(LeafStructBuildSpec::new(build_spec_name, members))
|
||||||
|
} else if build_spec["rules"].is_array() {
|
||||||
|
let rules = deserialize_enum_rules(&build_spec["rules"]);
|
||||||
|
BuildSpec::Enum(EnumBuildSpec::new(build_spec_name, rules))
|
||||||
|
} else if build_spec["leaf_rules"].is_array() {
|
||||||
|
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"]))
|
||||||
|
} else {
|
||||||
|
panic!("Expected a node spec for either a struct, leaf_struct, enum, leaf_enum node type, or a production type.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,6 +289,9 @@ pub fn deserialize_yaml_spec(yaml: &str) -> Vec<BuildSpec> {
|
|||||||
doc.as_hash()
|
doc.as_hash()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(build_spec_name, build_spec)| deserialize_build_spec(build_spec_name, build_spec))
|
.map(|(build_spec_name, build_spec)| {
|
||||||
|
let name_as_str = build_spec_name.as_str().unwrap();
|
||||||
|
deserialize_build_spec(name_as_str, build_spec)
|
||||||
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::spec::{LeafStructBuildSpec, LeafStructChildType};
|
use crate::spec::{LeafStructBuildSpec, LeafStructMemberKind};
|
||||||
use crate::util::{make_build_fn_name, make_build_pair};
|
use crate::util::{make_build_fn_name, make_build_pair};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
@ -9,12 +9,12 @@ pub fn make_leaf_struct_build_fn(build_spec: &LeafStructBuildSpec) -> TokenStrea
|
|||||||
let return_type_ident = format_ident!("{}", build_spec.build());
|
let return_type_ident = format_ident!("{}", build_spec.build());
|
||||||
|
|
||||||
let child_builders = build_spec
|
let child_builders = build_spec
|
||||||
.children()
|
.members()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|leaf_struct_child| {
|
.map(|leaf_struct_child| {
|
||||||
let child_ident = format_ident!("{}", leaf_struct_child.name());
|
let child_ident = format_ident!("{}", leaf_struct_child.name());
|
||||||
match leaf_struct_child.r#type() {
|
match leaf_struct_child.r#type() {
|
||||||
LeafStructChildType::String => {
|
LeafStructMemberKind::String => {
|
||||||
quote! {
|
quote! {
|
||||||
let #child_ident = #pair_ident.as_str()
|
let #child_ident = #pair_ident.as_str()
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ pub fn make_leaf_struct_build_fn(build_spec: &LeafStructBuildSpec) -> TokenStrea
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let child_args = build_spec
|
let child_args = build_spec
|
||||||
.children()
|
.members()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|leaf_struct_child| format_ident!("{}", leaf_struct_child.name()))
|
.map(|leaf_struct_child| format_ident!("{}", leaf_struct_child.name()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|||||||
@ -2,6 +2,7 @@ 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 production_build_fn;
|
||||||
mod spec;
|
mod spec;
|
||||||
mod struct_build_fn;
|
mod struct_build_fn;
|
||||||
mod type_gen;
|
mod type_gen;
|
||||||
@ -10,6 +11,7 @@ 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::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;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
@ -21,16 +23,22 @@ fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
|
|||||||
println!("*** BuildSpec ***");
|
println!("*** BuildSpec ***");
|
||||||
match build_spec {
|
match build_spec {
|
||||||
BuildSpec::Enum(enum_build_spec) => {
|
BuildSpec::Enum(enum_build_spec) => {
|
||||||
println!("Spec name: {}", enum_build_spec.name());
|
println!("Enum Spec - build: {}", enum_build_spec.build());
|
||||||
}
|
}
|
||||||
BuildSpec::LeafEnum(leaf_enum_build_spec) => {
|
BuildSpec::LeafEnum(leaf_enum_build_spec) => {
|
||||||
println!("Spec name: {}", leaf_enum_build_spec.name());
|
println!("Leaf Enum Spec - build: {}", leaf_enum_build_spec.build());
|
||||||
}
|
}
|
||||||
BuildSpec::Struct(struct_build_spec) => {
|
BuildSpec::Struct(struct_build_spec) => {
|
||||||
println!("Spec name: {}", struct_build_spec.name());
|
println!("Struct Spec - build: {}", struct_build_spec.build());
|
||||||
}
|
}
|
||||||
BuildSpec::LeafStruct(leaf_struct_build_spec) => {
|
BuildSpec::LeafStruct(leaf_struct_build_spec) => {
|
||||||
println!("Spec name: {}", leaf_struct_build_spec.name());
|
println!(
|
||||||
|
"Leaf Struct Spec - build: {}",
|
||||||
|
leaf_struct_build_spec.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
BuildSpec::Production(production_build_spec) => {
|
||||||
|
println!("Production Spec - rule: {}", production_build_spec.rule())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("{:#?}", token_stream);
|
println!("{:#?}", token_stream);
|
||||||
@ -72,6 +80,11 @@ fn generate_build_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
|||||||
debug_built_spec(build_spec, &stream);
|
debug_built_spec(build_spec, &stream);
|
||||||
stream
|
stream
|
||||||
}
|
}
|
||||||
|
BuildSpec::Production(production_build_spec) => {
|
||||||
|
let stream = make_production_build_fn(production_build_spec);
|
||||||
|
debug_built_spec(build_spec, &stream);
|
||||||
|
stream
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let combined = quote! {
|
let combined = quote! {
|
||||||
@ -103,33 +116,3 @@ pub fn generate_files(build_specs: &[BuildSpec]) -> Vec<AstGeneratedFile> {
|
|||||||
generate_node_file(build_specs),
|
generate_node_file(build_specs),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test_dump() -> String {
|
|
||||||
let build_specs = deserialize::deserialize_yaml_spec(include_str!("../../src/parser/ast.yaml"));
|
|
||||||
let mut streams: Vec<TokenStream> = vec![];
|
|
||||||
|
|
||||||
for build_spec in &build_specs {
|
|
||||||
let type_stream = make_type(build_spec);
|
|
||||||
debug_built_spec(build_spec, &type_stream);
|
|
||||||
streams.push(type_stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
for build_spec in &build_specs {
|
|
||||||
match build_spec {
|
|
||||||
BuildSpec::Enum(_) => {}
|
|
||||||
BuildSpec::LeafEnum(_) => {}
|
|
||||||
BuildSpec::Struct(struct_spec) => {
|
|
||||||
let struct_build_fn_stream = make_struct_build_fn(struct_spec);
|
|
||||||
debug_built_spec(build_spec, &struct_build_fn_stream);
|
|
||||||
streams.push(struct_build_fn_stream);
|
|
||||||
}
|
|
||||||
BuildSpec::LeafStruct(_) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let combined = quote! {
|
|
||||||
#(#streams)*
|
|
||||||
};
|
|
||||||
let file: File = syn::parse2(combined).unwrap();
|
|
||||||
prettyplease::unparse(&file)
|
|
||||||
}
|
|
||||||
|
|||||||
90
ast-generator/src/production_build_fn.rs
Normal file
90
ast-generator/src/production_build_fn.rs
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
use crate::spec::{ProductionBuildSpec, ProductionKind, ProductionStringFrom};
|
||||||
|
use crate::util::{make_build_fn_name, make_build_pair};
|
||||||
|
|
||||||
|
pub fn make_production_build_fn(production_build_spec: &ProductionBuildSpec) -> TokenStream {
|
||||||
|
let build_fn_ident = format_ident!("{}", make_build_fn_name(production_build_spec.rule()));
|
||||||
|
let return_type_ident = match production_build_spec.kind() {
|
||||||
|
ProductionKind::Int => format_ident!("i32"),
|
||||||
|
ProductionKind::Long => format_ident!("i64"),
|
||||||
|
ProductionKind::Double => format_ident!("f64"),
|
||||||
|
ProductionKind::String(_) => format_ident!("String"),
|
||||||
|
ProductionKind::Boolean => format_ident!("bool"),
|
||||||
|
};
|
||||||
|
let pair_ident = format_ident!("{}", make_build_pair(production_build_spec.rule()));
|
||||||
|
|
||||||
|
let pair_mapper = match production_build_spec.kind() {
|
||||||
|
ProductionKind::Int => quote! {
|
||||||
|
let number_base_pair = #pair_ident.to_inner()
|
||||||
|
.next()
|
||||||
|
.unwrap();
|
||||||
|
let inner_number_base_pair = number_base_pair.to_inner()
|
||||||
|
.next()
|
||||||
|
.unwrap();
|
||||||
|
match inner_number_base_pair.as_rule() {
|
||||||
|
Rule::BinaryBase => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Rule::HexadecimalBase => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Rule::DecimalBase => {
|
||||||
|
inner_number_base_pair.as_str().parse::<i32>().unwrap()
|
||||||
|
}
|
||||||
|
_ => panic!()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ProductionKind::Long => quote! {
|
||||||
|
let number_base_pair = #pair_ident.to_inner()
|
||||||
|
.next()
|
||||||
|
.unwrap();
|
||||||
|
let inner_number_base_pair = number_base_pair.to_inner()
|
||||||
|
.next()
|
||||||
|
.unwrap();
|
||||||
|
match inner_number_base_pair.as_rule() {
|
||||||
|
Rule::BinaryBase => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Rule::HexadecimalBase => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Rule::DecimalBase => {
|
||||||
|
inner_number_base_pair.as_str().parse::<i64>().unwrap()
|
||||||
|
}
|
||||||
|
_ => panic!()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ProductionKind::Double => quote! {
|
||||||
|
#pair_ident.as_str().parse::<f64>().unwrap()
|
||||||
|
},
|
||||||
|
ProductionKind::String(from) => {
|
||||||
|
match from {
|
||||||
|
ProductionStringFrom::StringInner => {
|
||||||
|
quote! {
|
||||||
|
#pair_ident.to_inner()
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ProductionStringFrom::WholePair => {
|
||||||
|
quote! {
|
||||||
|
#pair_ident.as_string().to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ProductionKind::Boolean => quote! {
|
||||||
|
#pair_ident.as_str().parse::<bool>().unwrap()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||||
|
#pair_mapper
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,59 +6,45 @@ pub enum BuildSpec {
|
|||||||
LeafEnum(LeafEnumBuildSpec),
|
LeafEnum(LeafEnumBuildSpec),
|
||||||
Struct(StructBuildSpec),
|
Struct(StructBuildSpec),
|
||||||
LeafStruct(LeafStructBuildSpec),
|
LeafStruct(LeafStructBuildSpec),
|
||||||
|
Production(ProductionBuildSpec),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enum build spec
|
||||||
|
|
||||||
pub struct EnumBuildSpec {
|
pub struct EnumBuildSpec {
|
||||||
name: String,
|
|
||||||
build: String,
|
build: String,
|
||||||
rules: Vec<EnumRule>,
|
rules: Vec<Box<EnumRule>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnumBuildSpec {
|
impl EnumBuildSpec {
|
||||||
pub fn from_name(name: &str, rules: Vec<EnumRule>) -> Self {
|
pub fn new(build: &str, rules: Vec<Box<EnumRule>>) -> Self {
|
||||||
EnumBuildSpec {
|
EnumBuildSpec {
|
||||||
name: name.to_string(),
|
build: build.to_string(),
|
||||||
build: name.to_string(),
|
|
||||||
rules,
|
rules,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The top-level key for the build spec in the yaml file.
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The enum type to be built, in Pascal case.
|
/// The enum type to be built, in Pascal case.
|
||||||
pub fn build(&self) -> &str {
|
pub fn build(&self) -> &str {
|
||||||
&self.build
|
&self.build
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The individual rule specs.
|
/// The individual rule specs.
|
||||||
pub fn rules(&self) -> &[EnumRule] {
|
pub fn rules(&self) -> impl Iterator<Item = &EnumRule> {
|
||||||
&self.rules
|
self.rules.iter().map(Box::as_ref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EnumRule {
|
pub struct EnumRule {
|
||||||
rule: String,
|
rule: String,
|
||||||
build: String,
|
child: Option<Box<EnumRuleChild>>
|
||||||
with: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnumRule {
|
impl EnumRule {
|
||||||
pub fn from_rule(rule: &str) -> Self {
|
pub fn new(rule: &str, child: Option<Box<EnumRuleChild>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
rule: rule.to_string(),
|
rule: rule.to_string(),
|
||||||
build: rule.to_string(),
|
child
|
||||||
with: make_build_fn_name(rule),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(rule: &str, build: &str, with: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
rule: rule.to_string(),
|
|
||||||
build: build.to_string(),
|
|
||||||
with: with.to_string(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,160 +53,125 @@ impl EnumRule {
|
|||||||
&self.rule
|
&self.rule
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The type to build, in Pascal case.
|
pub fn child(&self) -> Option<&EnumRuleChild> {
|
||||||
|
if let Some(child) = &self.child {
|
||||||
|
Some(child.as_ref())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EnumRuleChild {
|
||||||
|
kind: Box<EnumRuleChildKind>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnumRuleChild {
|
||||||
|
pub fn new(kind: Box<EnumRuleChildKind>) -> Self {
|
||||||
|
Self { kind }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind(&self) -> &EnumRuleChildKind {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum EnumRuleChildKind {
|
||||||
|
Node(EnumRuleNodeChild),
|
||||||
|
Int,
|
||||||
|
Long,
|
||||||
|
Double,
|
||||||
|
USize,
|
||||||
|
String,
|
||||||
|
Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EnumRuleNodeChild {
|
||||||
|
build: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnumRuleNodeChild {
|
||||||
|
pub fn new(build: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
build: build.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(&self) -> &str {
|
pub fn build(&self) -> &str {
|
||||||
&self.build
|
&self.build
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The build-fn name, in snake case.
|
// Leaf enum build spec
|
||||||
pub fn with(&self) -> &str {
|
|
||||||
&self.with
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LeafEnumBuildSpec {
|
pub struct LeafEnumBuildSpec {
|
||||||
name: String,
|
|
||||||
build: String,
|
build: String,
|
||||||
rules: Vec<LeafEnumRule>,
|
rules: Vec<Box<LeafEnumRule>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LeafEnumBuildSpec {
|
impl LeafEnumBuildSpec {
|
||||||
pub fn from_name(name: &str, rules: Vec<LeafEnumRule>) -> Self {
|
pub fn new(build: &str, rules: Vec<Box<LeafEnumRule>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: name.to_string(),
|
build: build.to_string(),
|
||||||
build: name.to_string(),
|
rules
|
||||||
rules,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build(&self) -> &str {
|
pub fn build(&self) -> &str {
|
||||||
&self.build
|
&self.build
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rules(&self) -> &[LeafEnumRule] {
|
pub fn rules(&self) -> impl Iterator<Item = &LeafEnumRule> {
|
||||||
&self.rules
|
self.rules.iter().map(Box::as_ref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LeafEnumRule {
|
pub struct LeafEnumRule {
|
||||||
rule: String,
|
rule: String,
|
||||||
build: LeafEnumRuleBuild,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LeafEnumRule {
|
impl LeafEnumRule {
|
||||||
pub fn new(rule: &str, build: LeafEnumRuleBuild) -> Self {
|
pub fn new(rule: &str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
rule: rule.to_string(),
|
rule: rule.to_string(),
|
||||||
build,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rule(&self) -> &str {
|
pub fn rule(&self) -> &str {
|
||||||
&self.rule
|
&self.rule
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(&self) -> &LeafEnumRuleBuild {
|
|
||||||
&self.build
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LeafEnumRuleBuild {
|
// Struct build spec
|
||||||
rule: String,
|
|
||||||
child: Option<LeafEnumRuleBuildChild>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LeafEnumRuleBuild {
|
|
||||||
pub fn new(rule: &str, child: Option<LeafEnumRuleBuildChild>) -> Self {
|
|
||||||
Self {
|
|
||||||
rule: rule.to_string(),
|
|
||||||
child,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rule(&self) -> &str {
|
|
||||||
&self.rule
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn child(&self) -> Option<&LeafEnumRuleBuildChild> {
|
|
||||||
self.child.as_ref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LeafEnumRuleBuildChild {
|
|
||||||
build: String,
|
|
||||||
with: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LeafEnumRuleBuildChild {
|
|
||||||
pub fn new(build: &str, with: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
build: build.to_string(),
|
|
||||||
with: with.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build(&self) -> &str {
|
|
||||||
&self.build
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with(&self) -> &str {
|
|
||||||
&self.with
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct StructBuildSpec {
|
pub struct StructBuildSpec {
|
||||||
name: String,
|
|
||||||
build: String,
|
build: String,
|
||||||
var_name: String,
|
children: Vec<Box<StructChildSpec>>,
|
||||||
with: String,
|
|
||||||
children: Vec<ChildSpec>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StructBuildSpec {
|
impl StructBuildSpec {
|
||||||
pub fn from_name(name: &str, child_specs: Vec<ChildSpec>) -> Self {
|
pub fn new(build: &str, children: Vec<Box<StructChildSpec>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: name.to_string(),
|
build: build.to_string(),
|
||||||
build: name.to_string(),
|
children
|
||||||
var_name: name.to_case(Case::Snake),
|
|
||||||
with: make_build_fn_name(name),
|
|
||||||
children: child_specs,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The top-level name of this build spec.
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The type to be built, in Pascal case.
|
/// The type to be built, in Pascal case.
|
||||||
pub fn build(&self) -> &str {
|
pub fn build(&self) -> &str {
|
||||||
&self.build
|
&self.build
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The name of the variable to be built, in snake case.
|
|
||||||
pub fn var_name(&self) -> &str {
|
|
||||||
&self.var_name
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The build-fn name, in snake case.
|
|
||||||
pub fn with(&self) -> &str {
|
|
||||||
&self.with
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The children for this build spec.
|
/// The children for this build spec.
|
||||||
pub fn children(&self) -> &[ChildSpec] {
|
pub fn children(&self) -> impl Iterator<Item = &StructChildSpec> {
|
||||||
&self.children
|
self.children.iter().map(Box::as_ref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ChildSpec {
|
pub enum StructChildSpec {
|
||||||
SkipChild(SkipChild),
|
SkipChild(SkipChild),
|
||||||
VecChild(VecChild),
|
VecChild(VecChild),
|
||||||
SingleChild(SingleChild),
|
MemberChild(MemberChild),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SkipChild {
|
pub struct SkipChild {
|
||||||
@ -250,11 +201,11 @@ impl SkipChild {
|
|||||||
pub struct VecChild {
|
pub struct VecChild {
|
||||||
name: String,
|
name: String,
|
||||||
rule: String,
|
rule: String,
|
||||||
build: VecChildToBuild,
|
build: Box<VecChildToBuild>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VecChild {
|
impl VecChild {
|
||||||
pub fn new(name: &str, rule: &str, build: VecChildToBuild) -> Self {
|
pub fn new(name: &str, rule: &str, build: Box<VecChildToBuild>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
rule: rule.to_string(),
|
rule: rule.to_string(),
|
||||||
@ -280,62 +231,35 @@ impl VecChild {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum VecChildToBuild {
|
pub enum VecChildToBuild {
|
||||||
Type(VecTypeChildToBuild),
|
Node(VecNodeChildToBuild),
|
||||||
|
String
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct VecTypeChildToBuild {
|
pub struct VecNodeChildToBuild {
|
||||||
build: String,
|
build: String,
|
||||||
var_name: String,
|
|
||||||
with: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VecTypeChildToBuild {
|
impl VecNodeChildToBuild {
|
||||||
pub fn new(build: &str, var_name: &str, with: &str) -> Self {
|
pub fn new(build: &str) -> Self {
|
||||||
Self {
|
Self { build: build.to_string() }
|
||||||
build: build.to_string(),
|
|
||||||
var_name: var_name.to_string(),
|
|
||||||
with: with.to_string(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The type to build, in Pascal case.
|
/// The type to build, in Pascal case.
|
||||||
pub fn build(&self) -> &str {
|
pub fn build(&self) -> &str {
|
||||||
&self.build
|
&self.build
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The name of the variable to build, in snake case.
|
|
||||||
pub fn var_name(&self) -> &str {
|
|
||||||
&self.var_name
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The build-fn name.
|
|
||||||
pub fn with(&self) -> &str {
|
|
||||||
&self.with
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SingleChild {
|
pub struct MemberChild {
|
||||||
name: String,
|
name: String,
|
||||||
rule: String,
|
rule: String,
|
||||||
build: SingleChildToBuild,
|
build: Box<MemberChildToBuild>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SingleChild {
|
impl MemberChild {
|
||||||
pub fn from_name_snake(name: &str) -> Self {
|
pub fn new(name: &str, rule: &str, build: Box<MemberChildToBuild>) -> Self {
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
rule: name.to_case(Case::Pascal),
|
|
||||||
build: SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(
|
|
||||||
&name.to_case(Case::Pascal),
|
|
||||||
None,
|
|
||||||
false,
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(name: &str, rule: &str, build: SingleChildToBuild) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
rule: rule.to_string(),
|
rule: rule.to_string(),
|
||||||
@ -354,56 +278,32 @@ impl SingleChild {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The specification for what to actually build.
|
/// The specification for what to actually build.
|
||||||
pub fn build(&self) -> &SingleChildToBuild {
|
pub fn build(&self) -> &MemberChildToBuild {
|
||||||
&self.build
|
&self.build
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SingleChildToBuild {
|
pub enum MemberChildToBuild {
|
||||||
Type(SingleTypeChildToBuild),
|
Node(NodeChildToBuild),
|
||||||
Boolean(SingleBooleanChildToBuild),
|
Boolean(BooleanChildToBuild),
|
||||||
Int(SingleLiteralChildToBuild),
|
|
||||||
Long(SingleLiteralChildToBuild),
|
|
||||||
Double(SingleLiteralChildToBuild),
|
|
||||||
String(SingleLiteralChildToBuild),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SingleTypeChildToBuild {
|
pub struct NodeChildToBuild {
|
||||||
build: String,
|
build: String,
|
||||||
var_name: String,
|
|
||||||
with: String,
|
|
||||||
or_else: Option<String>,
|
or_else: Option<String>,
|
||||||
optional: bool,
|
optional: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SingleTypeChildToBuild {
|
impl NodeChildToBuild {
|
||||||
pub fn from_build_or_rule(
|
|
||||||
build_or_rule: &str,
|
|
||||||
or_else: Option<String>,
|
|
||||||
optional: bool,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
build: build_or_rule.to_string(),
|
|
||||||
var_name: build_or_rule.to_case(Case::Snake),
|
|
||||||
with: make_build_fn_name(build_or_rule),
|
|
||||||
or_else,
|
|
||||||
optional,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
build: &str,
|
build: &str,
|
||||||
var_name: &str,
|
|
||||||
with: &str,
|
|
||||||
or_else: Option<String>,
|
or_else: Option<String>,
|
||||||
optional: bool,
|
optional: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
build: build.to_string(),
|
build: build.to_string(),
|
||||||
var_name: var_name.to_string(),
|
|
||||||
with: with.to_string(),
|
|
||||||
or_else,
|
or_else,
|
||||||
optional,
|
optional,
|
||||||
}
|
}
|
||||||
@ -414,16 +314,6 @@ impl SingleTypeChildToBuild {
|
|||||||
&self.build
|
&self.build
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The variable name to build, in snake case.
|
|
||||||
pub fn var_name(&self) -> &str {
|
|
||||||
&self.var_name
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The build-fn name.
|
|
||||||
pub fn with(&self) -> &str {
|
|
||||||
&self.with
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The default fn to call when unwrapping the child (before passing as arg to new).
|
/// The default fn to call when unwrapping the child (before passing as arg to new).
|
||||||
pub fn or_else(&self) -> Option<&str> {
|
pub fn or_else(&self) -> Option<&str> {
|
||||||
self.or_else.as_deref()
|
self.or_else.as_deref()
|
||||||
@ -436,89 +326,56 @@ impl SingleTypeChildToBuild {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SingleBooleanChildToBuild {
|
pub struct BooleanChildToBuild {
|
||||||
var_name: String,
|
name: String
|
||||||
build: BooleanBuild,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SingleBooleanChildToBuild {
|
impl BooleanChildToBuild {
|
||||||
pub fn new(var_name: &str, build: BooleanBuild) -> Self {
|
pub fn new(name: &str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
var_name: var_name.to_string(),
|
name: name.to_string()
|
||||||
build,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn var_name(&self) -> &str {
|
|
||||||
&self.var_name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build(&self) -> &BooleanBuild {
|
|
||||||
&self.build
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum BooleanBuild {
|
|
||||||
RulePresent,
|
|
||||||
ParseWholePair,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct SingleLiteralChildToBuild {
|
|
||||||
var_name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SingleLiteralChildToBuild {
|
|
||||||
pub fn new(var_name: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
var_name: var_name.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn var_name(&self) -> &str {
|
|
||||||
&self.var_name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LeafStructBuildSpec {
|
|
||||||
name: String,
|
|
||||||
build: String,
|
|
||||||
children: Vec<LeafStructChild>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LeafStructBuildSpec {
|
|
||||||
pub fn new(name: &str, build: &str, children: Vec<LeafStructChild>) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
build: build.to_string(),
|
|
||||||
children,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &str {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leaf Struct build spec
|
||||||
|
|
||||||
|
pub struct LeafStructBuildSpec {
|
||||||
|
build: String,
|
||||||
|
members: Vec<Box<LeafStructMember>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LeafStructBuildSpec {
|
||||||
|
pub fn new(build: &str, members: Vec<Box<LeafStructMember>>) -> Self {
|
||||||
|
Self {
|
||||||
|
build: build.to_string(),
|
||||||
|
members,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(&self) -> &str {
|
pub fn build(&self) -> &str {
|
||||||
&self.build
|
&self.build
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn children(&self) -> &[LeafStructChild] {
|
pub fn members(&self) -> impl Iterator<Item = &LeafStructMember> {
|
||||||
&self.children
|
self.members.iter().map(Box::as_ref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LeafStructChild {
|
pub struct LeafStructMember {
|
||||||
name: String,
|
name: String,
|
||||||
r#type: LeafStructChildType,
|
kind: LeafStructMemberKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LeafStructChild {
|
impl LeafStructMember {
|
||||||
pub fn new(name: &str, r#type: LeafStructChildType) -> Self {
|
pub fn new(name: &str, kind: LeafStructMemberKind) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
r#type,
|
kind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,11 +383,46 @@ impl LeafStructChild {
|
|||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn r#type(&self) -> &LeafStructChildType {
|
pub fn kind(&self) -> &LeafStructMemberKind {
|
||||||
&self.r#type
|
&self.kind
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum LeafStructChildType {
|
pub enum LeafStructMemberKind {
|
||||||
String,
|
String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ProductionBuildSpec {
|
||||||
|
rule: String,
|
||||||
|
kind: ProductionKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProductionBuildSpec {
|
||||||
|
pub fn new(rule: &str, kind: ProductionKind) -> Self {
|
||||||
|
Self {
|
||||||
|
rule: rule.to_string(),
|
||||||
|
kind,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rule(&self) -> &str {
|
||||||
|
&self.rule
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind(&self) -> &ProductionKind {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ProductionKind {
|
||||||
|
Int,
|
||||||
|
Long,
|
||||||
|
Double,
|
||||||
|
String(ProductionStringFrom),
|
||||||
|
Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ProductionStringFrom {
|
||||||
|
StringInner,
|
||||||
|
WholePair
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::spec::{
|
use crate::spec::{
|
||||||
BooleanBuild, ChildSpec, SingleBooleanChildToBuild, SingleChildToBuild,
|
BooleanChildToBuild, MemberChildToBuild, NodeChildToBuild,
|
||||||
SingleLiteralChildToBuild, SingleTypeChildToBuild, StructBuildSpec, VecChild, VecChildToBuild,
|
StructBuildSpec, StructChildSpec, VecChild, VecChildToBuild,
|
||||||
};
|
};
|
||||||
use crate::util::make_build_pair;
|
use crate::util::make_build_pair;
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
@ -8,7 +8,7 @@ use quote::{format_ident, quote};
|
|||||||
|
|
||||||
fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream {
|
fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream {
|
||||||
let (child_ident, child_type_ident) = match vec_child.build() {
|
let (child_ident, child_type_ident) = match vec_child.build() {
|
||||||
VecChildToBuild::Type(vec_type_child) => (
|
VecChildToBuild::Node(vec_type_child) => (
|
||||||
format_ident!("{}", vec_type_child.var_name()),
|
format_ident!("{}", vec_type_child.var_name()),
|
||||||
format_ident!("{}", vec_type_child.build()),
|
format_ident!("{}", vec_type_child.build()),
|
||||||
),
|
),
|
||||||
@ -18,7 +18,7 @@ fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_single_type_child_holder(single_type_child: &SingleTypeChildToBuild) -> TokenStream {
|
fn make_single_type_child_holder(single_type_child: &NodeChildToBuild) -> TokenStream {
|
||||||
let child_ident = format_ident!("{}", single_type_child.var_name());
|
let child_ident = format_ident!("{}", single_type_child.var_name());
|
||||||
let child_type_ident = format_ident!("{}", single_type_child.build());
|
let child_type_ident = format_ident!("{}", single_type_child.build());
|
||||||
quote! {
|
quote! {
|
||||||
@ -26,10 +26,8 @@ fn make_single_type_child_holder(single_type_child: &SingleTypeChildToBuild) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_single_boolean_child_holder(
|
fn make_single_boolean_child_holder(single_boolean_child: &BooleanChildToBuild) -> TokenStream {
|
||||||
single_boolean_child: &SingleBooleanChildToBuild,
|
let child_ident = format_ident!("{}", single_boolean_child.name());
|
||||||
) -> TokenStream {
|
|
||||||
let child_ident = format_ident!("{}", single_boolean_child.var_name());
|
|
||||||
quote! {
|
quote! {
|
||||||
let mut #child_ident: bool = false
|
let mut #child_ident: bool = false
|
||||||
}
|
}
|
||||||
@ -45,30 +43,30 @@ fn make_literal_child_holder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_child_holder(child_spec: &ChildSpec) -> Option<TokenStream> {
|
fn make_child_holder(child_spec: &StructChildSpec) -> Option<TokenStream> {
|
||||||
match child_spec {
|
match child_spec {
|
||||||
ChildSpec::SkipChild(_) => None,
|
StructChildSpec::SkipChild(_) => None,
|
||||||
ChildSpec::VecChild(vec_child) => Some(make_vec_child_holder(vec_child)),
|
StructChildSpec::VecChild(vec_child) => Some(make_vec_child_holder(vec_child)),
|
||||||
ChildSpec::SingleChild(single_child) => match single_child.build() {
|
StructChildSpec::MemberChild(single_child) => match single_child.build() {
|
||||||
SingleChildToBuild::Type(single_type_child) => {
|
MemberChildToBuild::Node(single_type_child) => {
|
||||||
Some(make_single_type_child_holder(single_type_child))
|
Some(make_single_type_child_holder(single_type_child))
|
||||||
}
|
}
|
||||||
SingleChildToBuild::Boolean(boolean_child) => {
|
MemberChildToBuild::Boolean(boolean_child) => {
|
||||||
Some(make_single_boolean_child_holder(boolean_child))
|
Some(make_single_boolean_child_holder(boolean_child))
|
||||||
}
|
}
|
||||||
SingleChildToBuild::Int(literal_child) => Some(make_literal_child_holder(
|
MemberChildToBuild::Int(literal_child) => Some(make_literal_child_holder(
|
||||||
literal_child,
|
literal_child,
|
||||||
format_ident!("i32"),
|
format_ident!("i32"),
|
||||||
)),
|
)),
|
||||||
SingleChildToBuild::Long(literal_child) => Some(make_literal_child_holder(
|
MemberChildToBuild::Long(literal_child) => Some(make_literal_child_holder(
|
||||||
literal_child,
|
literal_child,
|
||||||
format_ident!("i64"),
|
format_ident!("i64"),
|
||||||
)),
|
)),
|
||||||
SingleChildToBuild::Double(literal_child) => Some(make_literal_child_holder(
|
MemberChildToBuild::Double(literal_child) => Some(make_literal_child_holder(
|
||||||
literal_child,
|
literal_child,
|
||||||
format_ident!("f64"),
|
format_ident!("f64"),
|
||||||
)),
|
)),
|
||||||
SingleChildToBuild::String(literal_child) => Some(make_literal_child_holder(
|
MemberChildToBuild::String(literal_child) => Some(make_literal_child_holder(
|
||||||
literal_child,
|
literal_child,
|
||||||
format_ident!("String"),
|
format_ident!("String"),
|
||||||
)),
|
)),
|
||||||
@ -80,12 +78,12 @@ fn get_literal_child_ident(literal_child: &SingleLiteralChildToBuild) -> Ident {
|
|||||||
format_ident!("{}", literal_child.var_name())
|
format_ident!("{}", literal_child.var_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_match_action(child_spec: &ChildSpec) -> TokenStream {
|
fn make_match_action(child_spec: &StructChildSpec) -> TokenStream {
|
||||||
match child_spec {
|
match child_spec {
|
||||||
ChildSpec::SkipChild(_) => quote! {},
|
StructChildSpec::SkipChild(_) => quote! {},
|
||||||
ChildSpec::VecChild(vec_child) => {
|
StructChildSpec::VecChild(vec_child) => {
|
||||||
let (child_name_ident, build_fn_ident) = match vec_child.build() {
|
let (child_name_ident, build_fn_ident) = match vec_child.build() {
|
||||||
VecChildToBuild::Type(vec_type_child) => (
|
VecChildToBuild::Node(vec_type_child) => (
|
||||||
format_ident!("{}", vec_type_child.var_name()),
|
format_ident!("{}", vec_type_child.var_name()),
|
||||||
format_ident!("{}", vec_type_child.with()),
|
format_ident!("{}", vec_type_child.with()),
|
||||||
),
|
),
|
||||||
@ -94,16 +92,16 @@ fn make_match_action(child_spec: &ChildSpec) -> TokenStream {
|
|||||||
#child_name_ident.push(Box::new(#build_fn_ident(inner_pair)))
|
#child_name_ident.push(Box::new(#build_fn_ident(inner_pair)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ChildSpec::SingleChild(single_child) => match single_child.build() {
|
StructChildSpec::MemberChild(single_child) => match single_child.build() {
|
||||||
SingleChildToBuild::Type(single_type_child) => {
|
MemberChildToBuild::Node(single_type_child) => {
|
||||||
let child_name_ident = format_ident!("{}", single_type_child.var_name());
|
let child_name_ident = format_ident!("{}", single_type_child.var_name());
|
||||||
let build_fn_ident = format_ident!("{}", single_type_child.with());
|
let build_fn_ident = format_ident!("{}", single_type_child.with());
|
||||||
quote! {
|
quote! {
|
||||||
#child_name_ident = Some(Box::new(#build_fn_ident(inner_pair)))
|
#child_name_ident = Some(Box::new(#build_fn_ident(inner_pair)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SingleChildToBuild::Boolean(single_boolean_child) => {
|
MemberChildToBuild::Boolean(single_boolean_child) => {
|
||||||
let child_name_ident = format_ident!("{}", single_boolean_child.var_name());
|
let child_name_ident = format_ident!("{}", single_boolean_child.name());
|
||||||
match single_boolean_child.build() {
|
match single_boolean_child.build() {
|
||||||
BooleanBuild::RulePresent => quote! {
|
BooleanBuild::RulePresent => quote! {
|
||||||
#child_name_ident = true
|
#child_name_ident = true
|
||||||
@ -113,13 +111,13 @@ fn make_match_action(child_spec: &ChildSpec) -> TokenStream {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SingleChildToBuild::Int(literal_child) => {
|
MemberChildToBuild::Int(literal_child) => {
|
||||||
let child_ident = get_literal_child_ident(literal_child);
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
quote! {
|
quote! {
|
||||||
#child_ident = Some(inner_pair.as_str().parse().unwrap())
|
#child_ident = Some(inner_pair.as_str().parse().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SingleChildToBuild::Long(literal_child) => {
|
MemberChildToBuild::Long(literal_child) => {
|
||||||
let child_ident = get_literal_child_ident(literal_child);
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
quote! {
|
quote! {
|
||||||
let as_string = inner_pair.as_str();
|
let as_string = inner_pair.as_str();
|
||||||
@ -127,13 +125,13 @@ fn make_match_action(child_spec: &ChildSpec) -> TokenStream {
|
|||||||
#child_ident = Some(without_el.parse().unwrap())
|
#child_ident = Some(without_el.parse().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SingleChildToBuild::Double(literal_child) => {
|
MemberChildToBuild::Double(literal_child) => {
|
||||||
let child_ident = get_literal_child_ident(literal_child);
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
quote! {
|
quote! {
|
||||||
#child_ident = Some(inner_pair.as_str().parse().unwrap())
|
#child_ident = Some(inner_pair.as_str().parse().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SingleChildToBuild::String(literal_child) => {
|
MemberChildToBuild::String(literal_child) => {
|
||||||
let child_ident = get_literal_child_ident(literal_child);
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
quote! {
|
quote! {
|
||||||
#child_ident = Some(inner_pair.as_str().to_string())
|
#child_ident = Some(inner_pair.as_str().to_string())
|
||||||
@ -143,11 +141,11 @@ fn make_match_action(child_spec: &ChildSpec) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_rule_matcher(child_spec: &ChildSpec) -> TokenStream {
|
fn make_rule_matcher(child_spec: &StructChildSpec) -> TokenStream {
|
||||||
let rule_ident = match child_spec {
|
let rule_ident = match child_spec {
|
||||||
ChildSpec::SkipChild(skip_child) => format_ident!("{}", skip_child.rule()),
|
StructChildSpec::SkipChild(skip_child) => format_ident!("{}", skip_child.rule()),
|
||||||
ChildSpec::VecChild(vec_child) => format_ident!("{}", vec_child.rule()),
|
StructChildSpec::VecChild(vec_child) => format_ident!("{}", vec_child.rule()),
|
||||||
ChildSpec::SingleChild(single_child) => format_ident!("{}", single_child.rule()),
|
StructChildSpec::MemberChild(single_child) => format_ident!("{}", single_child.rule()),
|
||||||
};
|
};
|
||||||
let action = make_match_action(child_spec);
|
let action = make_match_action(child_spec);
|
||||||
|
|
||||||
@ -158,19 +156,19 @@ fn make_rule_matcher(child_spec: &ChildSpec) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_child_arg(child_spec: &ChildSpec) -> Option<TokenStream> {
|
fn make_child_arg(child_spec: &StructChildSpec) -> Option<TokenStream> {
|
||||||
match child_spec {
|
match child_spec {
|
||||||
ChildSpec::SkipChild(_) => None,
|
StructChildSpec::SkipChild(_) => None,
|
||||||
ChildSpec::VecChild(vec_child) => {
|
StructChildSpec::VecChild(vec_child) => {
|
||||||
let child_ident = match vec_child.build() {
|
let child_ident = match vec_child.build() {
|
||||||
VecChildToBuild::Type(vec_type_child) => {
|
VecChildToBuild::Node(vec_type_child) => {
|
||||||
format_ident!("{}", vec_type_child.var_name())
|
format_ident!("{}", vec_type_child.var_name())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Some(quote! { #child_ident })
|
Some(quote! { #child_ident })
|
||||||
}
|
}
|
||||||
ChildSpec::SingleChild(single_child) => match single_child.build() {
|
StructChildSpec::MemberChild(single_child) => match single_child.build() {
|
||||||
SingleChildToBuild::Type(single_type_child) => {
|
MemberChildToBuild::Node(single_type_child) => {
|
||||||
let child_ident = format_ident!("{}", single_type_child.var_name());
|
let child_ident = format_ident!("{}", single_type_child.var_name());
|
||||||
if single_type_child.optional() {
|
if single_type_child.optional() {
|
||||||
Some(quote! { #child_ident })
|
Some(quote! { #child_ident })
|
||||||
@ -184,23 +182,23 @@ fn make_child_arg(child_spec: &ChildSpec) -> Option<TokenStream> {
|
|||||||
Some(quote! { #child_ident.unwrap() })
|
Some(quote! { #child_ident.unwrap() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SingleChildToBuild::Boolean(single_boolean_child) => {
|
MemberChildToBuild::Boolean(single_boolean_child) => {
|
||||||
let child_ident = format_ident!("{}", single_boolean_child.var_name());
|
let child_ident = format_ident!("{}", single_boolean_child.name());
|
||||||
Some(quote! { #child_ident })
|
Some(quote! { #child_ident })
|
||||||
}
|
}
|
||||||
SingleChildToBuild::Int(literal_child) => {
|
MemberChildToBuild::Int(literal_child) => {
|
||||||
let child_ident = get_literal_child_ident(literal_child);
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
Some(quote! { #child_ident.unwrap() })
|
Some(quote! { #child_ident.unwrap() })
|
||||||
}
|
}
|
||||||
SingleChildToBuild::Long(literal_child) => {
|
MemberChildToBuild::Long(literal_child) => {
|
||||||
let child_ident = get_literal_child_ident(literal_child);
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
Some(quote! { #child_ident.unwrap() })
|
Some(quote! { #child_ident.unwrap() })
|
||||||
}
|
}
|
||||||
SingleChildToBuild::Double(literal_child) => {
|
MemberChildToBuild::Double(literal_child) => {
|
||||||
let child_ident = get_literal_child_ident(literal_child);
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
Some(quote! { #child_ident.unwrap() })
|
Some(quote! { #child_ident.unwrap() })
|
||||||
}
|
}
|
||||||
SingleChildToBuild::String(literal_child) => {
|
MemberChildToBuild::String(literal_child) => {
|
||||||
let child_ident = get_literal_child_ident(literal_child);
|
let child_ident = get_literal_child_ident(literal_child);
|
||||||
Some(quote! { #child_ident.unwrap() })
|
Some(quote! { #child_ident.unwrap() })
|
||||||
}
|
}
|
||||||
@ -269,14 +267,14 @@ pub fn make_struct_build_fn(build_spec: &StructBuildSpec) -> TokenStream {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::spec::VecTypeChildToBuild;
|
use crate::spec::VecNodeChildToBuild;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn vec_child_holder() {
|
fn vec_child_holder() {
|
||||||
let vec_child = VecChild::new(
|
let vec_child = VecChild::new(
|
||||||
"test_child",
|
"test_child",
|
||||||
"Test",
|
"Test",
|
||||||
VecChildToBuild::Type(VecTypeChildToBuild::new(
|
VecChildToBuild::Node(VecNodeChildToBuild::new(
|
||||||
"TestType",
|
"TestType",
|
||||||
"test_child",
|
"test_child",
|
||||||
"build_test_child",
|
"build_test_child",
|
||||||
@ -293,7 +291,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn single_type_child_holder() {
|
fn single_type_child_holder() {
|
||||||
let single_type_child = SingleTypeChildToBuild::from_build_or_rule("TestType", None, false);
|
let single_type_child = NodeChildToBuild::from_build_or_rule("TestType", None, false);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
make_single_type_child_holder(&single_type_child).to_string(),
|
make_single_type_child_holder(&single_type_child).to_string(),
|
||||||
quote! {
|
quote! {
|
||||||
@ -306,7 +304,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn single_boolean_child_holder() {
|
fn single_boolean_child_holder() {
|
||||||
let single_boolean_child =
|
let single_boolean_child =
|
||||||
SingleBooleanChildToBuild::new("test_child", BooleanBuild::RulePresent);
|
BooleanChildToBuild::new("test_child", BooleanBuild::RulePresent);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
make_single_boolean_child_holder(&single_boolean_child).to_string(),
|
make_single_boolean_child_holder(&single_boolean_child).to_string(),
|
||||||
quote! {
|
quote! {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::spec::{
|
use crate::spec::{
|
||||||
BuildSpec, ChildSpec, EnumBuildSpec, LeafEnumBuildSpec, LeafStructBuildSpec,
|
BooleanChildToBuild, BuildSpec, EnumBuildSpec, LeafEnumBuildSpec, LeafStructBuildSpec,
|
||||||
LeafStructChildType, SingleBooleanChildToBuild, SingleChildToBuild, SingleTypeChildToBuild,
|
LeafStructMemberKind, MemberChildToBuild, NodeChildToBuild, StructBuildSpec, StructChildSpec,
|
||||||
StructBuildSpec, VecChild, VecChildToBuild,
|
VecChild, VecChildToBuild,
|
||||||
};
|
};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
@ -61,7 +61,7 @@ fn handle_vec_child(
|
|||||||
accessors: &mut Vec<TokenStream>,
|
accessors: &mut Vec<TokenStream>,
|
||||||
) {
|
) {
|
||||||
let (child_ident, child_ident_mut, child_type_ident) = match vec_child.build() {
|
let (child_ident, child_ident_mut, child_type_ident) = match vec_child.build() {
|
||||||
VecChildToBuild::Type(vec_type_child) => (
|
VecChildToBuild::Node(vec_type_child) => (
|
||||||
format_ident!("{}", vec_type_child.var_name()),
|
format_ident!("{}", vec_type_child.var_name()),
|
||||||
format_ident!("{}_mut", vec_type_child.var_name()),
|
format_ident!("{}_mut", vec_type_child.var_name()),
|
||||||
format_ident!("{}", vec_type_child.build()),
|
format_ident!("{}", vec_type_child.build()),
|
||||||
@ -84,7 +84,7 @@ fn handle_vec_child(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_single_type_child(
|
fn handle_single_type_child(
|
||||||
single_type_child: &SingleTypeChildToBuild,
|
single_type_child: &NodeChildToBuild,
|
||||||
member_names: &mut Vec<Ident>,
|
member_names: &mut Vec<Ident>,
|
||||||
annotated_members: &mut Vec<TokenStream>,
|
annotated_members: &mut Vec<TokenStream>,
|
||||||
accessors: &mut Vec<TokenStream>,
|
accessors: &mut Vec<TokenStream>,
|
||||||
@ -134,12 +134,12 @@ fn handle_single_type_child(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_single_boolean_child(
|
fn handle_single_boolean_child(
|
||||||
single_boolean_child: &SingleBooleanChildToBuild,
|
single_boolean_child: &BooleanChildToBuild,
|
||||||
member_names: &mut Vec<Ident>,
|
member_names: &mut Vec<Ident>,
|
||||||
annotated_members: &mut Vec<TokenStream>,
|
annotated_members: &mut Vec<TokenStream>,
|
||||||
accessors: &mut Vec<TokenStream>,
|
accessors: &mut Vec<TokenStream>,
|
||||||
) {
|
) {
|
||||||
let child_ident = format_ident!("{}", single_boolean_child.var_name());
|
let child_ident = format_ident!("{}", single_boolean_child.name());
|
||||||
member_names.push(child_ident.clone());
|
member_names.push(child_ident.clone());
|
||||||
annotated_members.push(quote! {
|
annotated_members.push(quote! {
|
||||||
#child_ident: bool
|
#child_ident: bool
|
||||||
@ -158,8 +158,8 @@ fn make_struct_type(build_spec: &StructBuildSpec) -> TokenStream {
|
|||||||
|
|
||||||
for child_spec in build_spec.children().iter() {
|
for child_spec in build_spec.children().iter() {
|
||||||
match child_spec {
|
match child_spec {
|
||||||
ChildSpec::SkipChild(_) => {}
|
StructChildSpec::SkipChild(_) => {}
|
||||||
ChildSpec::VecChild(vec_child) => {
|
StructChildSpec::VecChild(vec_child) => {
|
||||||
handle_vec_child(
|
handle_vec_child(
|
||||||
vec_child,
|
vec_child,
|
||||||
&mut member_names,
|
&mut member_names,
|
||||||
@ -167,9 +167,9 @@ fn make_struct_type(build_spec: &StructBuildSpec) -> TokenStream {
|
|||||||
&mut accessors,
|
&mut accessors,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ChildSpec::SingleChild(single_child) => {
|
StructChildSpec::MemberChild(single_child) => {
|
||||||
match single_child.build() {
|
match single_child.build() {
|
||||||
SingleChildToBuild::Type(single_type_child) => {
|
MemberChildToBuild::Node(single_type_child) => {
|
||||||
handle_single_type_child(
|
handle_single_type_child(
|
||||||
single_type_child,
|
single_type_child,
|
||||||
&mut member_names,
|
&mut member_names,
|
||||||
@ -177,7 +177,7 @@ fn make_struct_type(build_spec: &StructBuildSpec) -> TokenStream {
|
|||||||
&mut accessors,
|
&mut accessors,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
SingleChildToBuild::Boolean(single_boolean_child) => {
|
MemberChildToBuild::Boolean(single_boolean_child) => {
|
||||||
handle_single_boolean_child(
|
handle_single_boolean_child(
|
||||||
single_boolean_child,
|
single_boolean_child,
|
||||||
&mut member_names,
|
&mut member_names,
|
||||||
@ -214,12 +214,12 @@ fn make_leaf_struct_type(build_spec: &LeafStructBuildSpec) -> TokenStream {
|
|||||||
let type_ident = format_ident!("{}", build_spec.build());
|
let type_ident = format_ident!("{}", build_spec.build());
|
||||||
|
|
||||||
let annotated_members = build_spec
|
let annotated_members = build_spec
|
||||||
.children()
|
.members()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|leaf_struct_child| {
|
.map(|leaf_struct_child| {
|
||||||
let name_ident = format_ident!("{}", leaf_struct_child.name());
|
let name_ident = format_ident!("{}", leaf_struct_child.name());
|
||||||
let type_ident = match leaf_struct_child.r#type() {
|
let type_ident = match leaf_struct_child.r#type() {
|
||||||
LeafStructChildType::String => format_ident!("{}", "String"),
|
LeafStructMemberKind::String => format_ident!("{}", "String"),
|
||||||
};
|
};
|
||||||
quote! {
|
quote! {
|
||||||
#name_ident: #type_ident
|
#name_ident: #type_ident
|
||||||
@ -228,18 +228,18 @@ fn make_leaf_struct_type(build_spec: &LeafStructBuildSpec) -> TokenStream {
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let member_names = build_spec
|
let member_names = build_spec
|
||||||
.children()
|
.members()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|leaf_struct_child| format_ident!("{}", leaf_struct_child.name()))
|
.map(|leaf_struct_child| format_ident!("{}", leaf_struct_child.name()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let accessors = build_spec
|
let accessors = build_spec
|
||||||
.children()
|
.members()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|leaf_struct_child| {
|
.map(|leaf_struct_child| {
|
||||||
let name_ident = format_ident!("{}", leaf_struct_child.name());
|
let name_ident = format_ident!("{}", leaf_struct_child.name());
|
||||||
match leaf_struct_child.r#type() {
|
match leaf_struct_child.r#type() {
|
||||||
LeafStructChildType::String => {
|
LeafStructMemberKind::String => {
|
||||||
quote! {
|
quote! {
|
||||||
pub fn #name_ident(&self) -> &str {
|
pub fn #name_ident(&self) -> &str {
|
||||||
&self.#name_ident
|
&self.#name_ident
|
||||||
|
|||||||
@ -132,6 +132,7 @@ $defs:
|
|||||||
kind:
|
kind:
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
|
- node # default
|
||||||
- string
|
- string
|
||||||
vec:
|
vec:
|
||||||
type: boolean
|
type: boolean
|
||||||
@ -142,9 +143,6 @@ $defs:
|
|||||||
StructChildMemberDefinition:
|
StructChildMemberDefinition:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
description: |
|
|
||||||
A definition for a child rule that builds one member. If a bare string, it is assumed to be the name/build-type
|
|
||||||
for a node. An object allows different types (i.e., things additional to nodes) to be built.
|
|
||||||
properties:
|
properties:
|
||||||
rule:
|
rule:
|
||||||
type: string
|
type: string
|
||||||
@ -195,15 +193,15 @@ $defs:
|
|||||||
oneOf:
|
oneOf:
|
||||||
- type: string
|
- type: string
|
||||||
description: Shorthand where child name, var, build, and with are inferred from the given Pascal-case rule name.
|
description: Shorthand where child name, var, build, and with are inferred from the given Pascal-case rule name.
|
||||||
- $ref: "#/$defs/LongEnumChildDefinition"
|
- $ref: "#/$defs/LongEnumChildWrapper"
|
||||||
LongEnumChildDefinition:
|
LongEnumChildWrapper:
|
||||||
type: object
|
type: object
|
||||||
|
minProperties: 1
|
||||||
|
maxProperties: 1
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
description: A format for an advanced enum child.
|
patternProperties:
|
||||||
properties:
|
"^([A-Z][a-z]*)*$":
|
||||||
child:
|
type: string
|
||||||
type: boolean
|
|
||||||
kind:
|
|
||||||
enum:
|
enum:
|
||||||
- int
|
- int
|
||||||
- long
|
- long
|
||||||
@ -211,12 +209,6 @@ $defs:
|
|||||||
- usize
|
- usize
|
||||||
- string
|
- string
|
||||||
- boolean
|
- boolean
|
||||||
from:
|
|
||||||
enum:
|
|
||||||
- translate
|
|
||||||
required:
|
|
||||||
- kind
|
|
||||||
- from
|
|
||||||
|
|
||||||
# Production definition
|
# Production definition
|
||||||
ProductionDefinition:
|
ProductionDefinition:
|
||||||
@ -234,7 +226,6 @@ $defs:
|
|||||||
- boolean
|
- boolean
|
||||||
from:
|
from:
|
||||||
enum:
|
enum:
|
||||||
- translate_and_parse
|
|
||||||
- string_inner
|
- string_inner
|
||||||
- whole_pair
|
- whole_pair
|
||||||
- parse_whole_pair
|
- parse_whole_pair
|
||||||
|
|||||||
@ -753,35 +753,27 @@ Literal:
|
|||||||
rules:
|
rules:
|
||||||
- IntLiteral:
|
- IntLiteral:
|
||||||
kind: int
|
kind: int
|
||||||
from: translate
|
|
||||||
- LongLiteral:
|
- LongLiteral:
|
||||||
kind: long
|
kind: long
|
||||||
from: translate
|
|
||||||
- DoubleLiteral:
|
- DoubleLiteral:
|
||||||
kind: double
|
kind: double
|
||||||
from: translate
|
|
||||||
- SingleQuoteString:
|
- SingleQuoteString:
|
||||||
kind: string
|
kind: string
|
||||||
from: translate
|
|
||||||
- DString
|
- DString
|
||||||
- BacktickString
|
- BacktickString
|
||||||
- BooleanLiteral:
|
- BooleanLiteral:
|
||||||
kind: boolean
|
kind: boolean
|
||||||
from: translate
|
|
||||||
|
|
||||||
# Numbers
|
# Numbers
|
||||||
IntLiteral:
|
IntLiteral:
|
||||||
produce:
|
produce:
|
||||||
kind: int
|
kind: int
|
||||||
from: translate_and_parse
|
|
||||||
LongLiteral:
|
LongLiteral:
|
||||||
produce:
|
produce:
|
||||||
kind: long
|
kind: long
|
||||||
from: translate_and_parse
|
|
||||||
DoubleLiteral:
|
DoubleLiteral:
|
||||||
produce:
|
produce:
|
||||||
kind: double
|
kind: double
|
||||||
from: translate_and_parse
|
|
||||||
|
|
||||||
# Strings
|
# Strings
|
||||||
SingleQuoteString:
|
SingleQuoteString:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user