esl_compiler/builder/
transformation.rs

1//! Transformation requirement builder module
2
3use crate::builder::auxiliary::{build_kw_aux_verb, AuxiliaryVerb};
4use crate::builder::design::{build_with_subclauses, DesignClauses};
5use crate::builder::subject::Subject;
6use crate::builder::variable::build_some_variables;
7use crate::builder::Stringency;
8use crate::context::Context;
9use crate::cursor::{Cursor, Error, Token};
10use crate::location::FileLocation;
11use crate::parser::Rule;
12use crate::reference::{Reference, VariableTarget, VerbDefinitionTarget};
13
14/// Transformation requirement or constraint.
15#[derive(Clone, Debug, Default, PartialEq)]
16pub struct Transformation {
17    /// Transformation's name or label.
18    pub name: Token,
19    /// Complete transformation's textual location.
20    pub loc: FileLocation,
21    /// Transformation's auxiliary verb.
22    pub auxiliary: AuxiliaryVerb,
23    /// Transformation's verb and preposition.
24    pub verb: Reference<(Token, Token), VerbDefinitionTarget>,
25    /// Transformation's input flows.
26    pub inputs: Vec<Reference<Subject, VariableTarget>>,
27    /// Transformation's output flows.
28    pub outputs: Vec<Reference<Subject, VariableTarget>>,
29    /// Transformation's subclauses (should be AND-concatenated).
30    pub subclauses: DesignClauses,
31    /// Whether this is a requirement or a constraint.
32    pub stringency: Stringency,
33}
34impl std::fmt::Display for Transformation {
35    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36        write!(f, "{}", self.name)
37    }
38}
39
40/// Build a transformation requirement or constraint from a cursor.
41pub fn build_transformation_instantiation(
42    ctx: &mut Context,
43    transformation_instantiation: Cursor,
44    stringency: Stringency,
45) -> Result<Transformation, Error> {
46    let loc = transformation_instantiation.as_location();
47    let mut cs = transformation_instantiation.into_inner();
48    let name = cs
49        .req_first(Rule::some_label)?
50        .into_inner()
51        .req_first(Rule::some_name)?
52        .into();
53    let auxiliary = cs
54        .req_first(Rule::kw_aux_verb)
55        .and_then(|c| build_kw_aux_verb(ctx, c))?;
56    let verb: Token = cs.req_first(Rule::some_verb)?.into();
57    let inputs = cs
58        .req_first(Rule::some_variables)
59        .and_then(|c| build_some_variables(ctx, c))?;
60    let preposition: Token = cs.req_first(Rule::some_preposition)?.into();
61    let outputs = cs
62        .req_first(Rule::some_variables)
63        .and_then(|c| build_some_variables(ctx, c))?;
64    let subclauses = {
65        if let Some(c) = cs.find_first(Rule::with_subclauses) {
66            build_with_subclauses(ctx, c)?
67        } else {
68            Default::default()
69        }
70    };
71    Ok(Transformation {
72        name,
73        loc,
74        auxiliary,
75        verb: Reference::new((verb, preposition)),
76        inputs,
77        outputs,
78        subclauses,
79        stringency,
80    })
81}