537 lines
11 KiB
Rust
537 lines
11 KiB
Rust
use crate::util::make_build_fn_name;
|
|
use convert_case::{Case, Casing};
|
|
|
|
pub enum BuildSpec {
|
|
Enum(EnumBuildSpec),
|
|
LeafEnum(LeafEnumBuildSpec),
|
|
Struct(StructBuildSpec),
|
|
LeafStruct(LeafStructBuildSpec),
|
|
}
|
|
|
|
pub struct EnumBuildSpec {
|
|
name: String,
|
|
build: String,
|
|
rules: Vec<EnumRule>,
|
|
}
|
|
|
|
impl EnumBuildSpec {
|
|
pub fn from_name(name: &str, rules: Vec<EnumRule>) -> Self {
|
|
EnumBuildSpec {
|
|
name: name.to_string(),
|
|
build: name.to_string(),
|
|
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.
|
|
pub fn build(&self) -> &str {
|
|
&self.build
|
|
}
|
|
|
|
/// The individual rule specs.
|
|
pub fn rules(&self) -> &[EnumRule] {
|
|
&self.rules
|
|
}
|
|
}
|
|
|
|
pub struct EnumRule {
|
|
rule: String,
|
|
build: String,
|
|
with: String,
|
|
}
|
|
|
|
impl EnumRule {
|
|
pub fn from_rule(rule: &str) -> Self {
|
|
Self {
|
|
rule: rule.to_string(),
|
|
build: rule.to_string(),
|
|
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(),
|
|
}
|
|
}
|
|
|
|
/// The enum rule to match, in Pascal case.
|
|
pub fn rule(&self) -> &str {
|
|
&self.rule
|
|
}
|
|
|
|
/// The type to build, in Pascal case.
|
|
pub fn build(&self) -> &str {
|
|
&self.build
|
|
}
|
|
|
|
/// The build-fn name, in snake case.
|
|
pub fn with(&self) -> &str {
|
|
&self.with
|
|
}
|
|
}
|
|
|
|
pub struct LeafEnumBuildSpec {
|
|
name: String,
|
|
build: String,
|
|
rules: Vec<LeafEnumRule>,
|
|
}
|
|
|
|
impl LeafEnumBuildSpec {
|
|
pub fn from_name(name: &str, rules: Vec<LeafEnumRule>) -> Self {
|
|
Self {
|
|
name: name.to_string(),
|
|
build: name.to_string(),
|
|
rules,
|
|
}
|
|
}
|
|
|
|
pub fn name(&self) -> &str {
|
|
&self.name
|
|
}
|
|
|
|
pub fn build(&self) -> &str {
|
|
&self.build
|
|
}
|
|
|
|
pub fn rules(&self) -> &[LeafEnumRule] {
|
|
&self.rules
|
|
}
|
|
}
|
|
|
|
pub struct LeafEnumRule {
|
|
rule: String,
|
|
build: LeafEnumRuleBuild,
|
|
}
|
|
|
|
impl LeafEnumRule {
|
|
pub fn new(rule: &str, build: LeafEnumRuleBuild) -> Self {
|
|
Self {
|
|
rule: rule.to_string(),
|
|
build,
|
|
}
|
|
}
|
|
|
|
pub fn rule(&self) -> &str {
|
|
&self.rule
|
|
}
|
|
|
|
pub fn build(&self) -> &LeafEnumRuleBuild {
|
|
&self.build
|
|
}
|
|
}
|
|
|
|
pub struct LeafEnumRuleBuild {
|
|
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 {
|
|
name: String,
|
|
build: String,
|
|
var_name: String,
|
|
with: String,
|
|
children: Vec<ChildSpec>,
|
|
}
|
|
|
|
impl StructBuildSpec {
|
|
pub fn from_name(name: &str, child_specs: Vec<ChildSpec>) -> Self {
|
|
Self {
|
|
name: name.to_string(),
|
|
build: name.to_string(),
|
|
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.
|
|
pub fn build(&self) -> &str {
|
|
&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.
|
|
pub fn children(&self) -> &[ChildSpec] {
|
|
&self.children
|
|
}
|
|
}
|
|
|
|
pub enum ChildSpec {
|
|
SkipChild(SkipChild),
|
|
VecChild(VecChild),
|
|
SingleChild(SingleChild),
|
|
}
|
|
|
|
pub struct SkipChild {
|
|
name: String,
|
|
rule: String,
|
|
}
|
|
|
|
impl SkipChild {
|
|
pub fn new(name: &str, rule: &str) -> Self {
|
|
Self {
|
|
name: name.to_string(),
|
|
rule: rule.to_string(),
|
|
}
|
|
}
|
|
|
|
/// The name of this child spec.
|
|
pub fn name(&self) -> &str {
|
|
&self.name
|
|
}
|
|
|
|
/// The grammar rule to match.
|
|
pub fn rule(&self) -> &str {
|
|
&self.rule
|
|
}
|
|
}
|
|
|
|
pub struct VecChild {
|
|
name: String,
|
|
rule: String,
|
|
build: VecChildToBuild,
|
|
}
|
|
|
|
impl VecChild {
|
|
pub fn new(name: &str, rule: &str, build: VecChildToBuild) -> Self {
|
|
Self {
|
|
name: name.to_string(),
|
|
rule: rule.to_string(),
|
|
build,
|
|
}
|
|
}
|
|
|
|
/// The name of this child.
|
|
pub fn name(&self) -> &str {
|
|
&self.name
|
|
}
|
|
|
|
/// The rule to match to build this child.
|
|
pub fn rule(&self) -> &str {
|
|
&self.rule
|
|
}
|
|
|
|
/// The build info for this child.
|
|
pub fn build(&self) -> &VecChildToBuild {
|
|
&self.build
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum VecChildToBuild {
|
|
Type(VecTypeChildToBuild),
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct VecTypeChildToBuild {
|
|
build: String,
|
|
var_name: String,
|
|
with: String,
|
|
}
|
|
|
|
impl VecTypeChildToBuild {
|
|
pub fn new(build: &str, var_name: &str, with: &str) -> Self {
|
|
Self {
|
|
build: build.to_string(),
|
|
var_name: var_name.to_string(),
|
|
with: with.to_string(),
|
|
}
|
|
}
|
|
|
|
/// The type to build, in Pascal case.
|
|
pub fn build(&self) -> &str {
|
|
&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)]
|
|
pub struct SingleChild {
|
|
name: String,
|
|
rule: String,
|
|
build: SingleChildToBuild,
|
|
}
|
|
|
|
impl SingleChild {
|
|
pub fn from_name_snake(name: &str) -> 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 {
|
|
name: name.to_string(),
|
|
rule: rule.to_string(),
|
|
build,
|
|
}
|
|
}
|
|
|
|
/// The name of this child in the yaml file, in snake case.
|
|
pub fn name(&self) -> &str {
|
|
&self.name
|
|
}
|
|
|
|
/// The grammar rule to match to build this child.
|
|
pub fn rule(&self) -> &str {
|
|
&self.rule
|
|
}
|
|
|
|
/// The specification for what to actually build.
|
|
pub fn build(&self) -> &SingleChildToBuild {
|
|
&self.build
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum SingleChildToBuild {
|
|
Type(SingleTypeChildToBuild),
|
|
Boolean(SingleBooleanChildToBuild),
|
|
Int(SingleLiteralChildToBuild),
|
|
Long(SingleLiteralChildToBuild),
|
|
Double(SingleLiteralChildToBuild),
|
|
String(SingleLiteralChildToBuild),
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct SingleTypeChildToBuild {
|
|
build: String,
|
|
var_name: String,
|
|
with: String,
|
|
or_else: Option<String>,
|
|
optional: bool,
|
|
}
|
|
|
|
impl SingleTypeChildToBuild {
|
|
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(
|
|
build: &str,
|
|
var_name: &str,
|
|
with: &str,
|
|
or_else: Option<String>,
|
|
optional: bool,
|
|
) -> Self {
|
|
Self {
|
|
build: build.to_string(),
|
|
var_name: var_name.to_string(),
|
|
with: with.to_string(),
|
|
or_else,
|
|
optional,
|
|
}
|
|
}
|
|
|
|
/// The type to build, in Pascal case.
|
|
pub fn build(&self) -> &str {
|
|
&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).
|
|
pub fn or_else(&self) -> Option<&str> {
|
|
self.or_else.as_deref()
|
|
}
|
|
|
|
/// If the type should be wrapped in an Option.
|
|
pub fn optional(&self) -> bool {
|
|
self.optional
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct SingleBooleanChildToBuild {
|
|
var_name: String,
|
|
build: BooleanBuild,
|
|
}
|
|
|
|
impl SingleBooleanChildToBuild {
|
|
pub fn new(var_name: &str, build: BooleanBuild) -> Self {
|
|
Self {
|
|
var_name: var_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 {
|
|
&self.name
|
|
}
|
|
|
|
pub fn build(&self) -> &str {
|
|
&self.build
|
|
}
|
|
|
|
pub fn children(&self) -> &[LeafStructChild] {
|
|
&self.children
|
|
}
|
|
}
|
|
|
|
pub struct LeafStructChild {
|
|
name: String,
|
|
r#type: LeafStructChildType,
|
|
}
|
|
|
|
impl LeafStructChild {
|
|
pub fn new(name: &str, r#type: LeafStructChildType) -> Self {
|
|
Self {
|
|
name: name.to_string(),
|
|
r#type,
|
|
}
|
|
}
|
|
|
|
pub fn name(&self) -> &str {
|
|
&self.name
|
|
}
|
|
|
|
pub fn r#type(&self) -> &LeafStructChildType {
|
|
&self.r#type
|
|
}
|
|
}
|
|
|
|
pub enum LeafStructChildType {
|
|
String,
|
|
}
|