diff --git a/src/rsprocess/assert.rs b/src/rsprocess/assert.rs index fe1d7b5..7aaad49 100644 --- a/src/rsprocess/assert.rs +++ b/src/rsprocess/assert.rs @@ -1,5 +1,8 @@ #![allow(dead_code)] +// If changing IntegerType in assert.rs, also change from Num to another +// similar parser with different return type in grammar.lalrpop in +// AssertExpression type IntegerType = i64; #[derive(Debug, Clone)] @@ -10,126 +13,65 @@ pub struct RSassert { #[derive(Debug, Clone)] pub enum Tree { Concat(Box, Box), - If(Box, Box), - IfElse(Box, Box, Box), - Assignment(AssignmentVar, Box), + If(Box, Box), + IfElse(Box, Box, Box), + Assignment(AssignmentVariable, Box), Return(Box), For(Variable, Range, Box), } #[derive(Debug, Clone)] -pub enum Expression { - B(Boolean), - A(Arithmetic), - Lab(Label), - Set(Set), - El(Element), - Str(Str), +pub struct Variable { + data: String, +} - Var(Variable), // for when the type should just be passed through +impl Variable { + pub fn from(data: String) -> Self { + Self { data } + } } #[derive(Debug, Clone)] -pub enum Boolean { - Var(Variable), // should be of type boolean +pub enum AssignmentVariable { + Var(Variable), + QualifiedVar(Variable, QualifierRestricted) +} + +#[derive(Debug, Clone)] +pub enum Expression { True, False, - Not(Box), - And(Box, Box), - Or(Box, Box), - Xor(Box, Box), - - Less(Arithmetic, Arithmetic), - LessEq(Arithmetic, Arithmetic), - More(Arithmetic, Arithmetic), - MoreEq(Arithmetic, Arithmetic), - Eq(Arithmetic, Arithmetic), - NotEq(Arithmetic, Arithmetic), - - LabelEq(Label, Label), - LabelNotEq(Label, Label), - - SetSub(Set, Set), - SetSubEq(Set, Set), - SetSuper(Set, Set), - SetSuperEq(Set, Set), - SetEq(Set, Set), - SetEmpty(Set), - - ElEq(Element, Element), - ElNotEq(Element, Element), - - StrEq(Str, Str), - StrNotEq(Str, Str), - StrSubstring(Str, Str), -} - -#[derive(Debug, Clone)] -pub enum Arithmetic { - Var(Variable), // should be of type arithmetic Integer(IntegerType), - Plus(Box, Box), - Minus(Box, Box), - Times(Box, Box), - Quotient(Box, Box), - Reminder(Box, Box), - Exponential(Box, Box), - Rand(Box, Box), - Min(Box, Box), - Max(Box, Box), + Label(Box), + Set(super::structure::RSset), + Element(super::translator::IdType), + String(String), + Var(AssignmentVariable), - SetLength(Set), - StrLength(Str), + Unary(Unary, Box), + Binary(Binary, Box, Box), } #[derive(Debug, Clone)] -pub enum Label { - Var(Variable), // should be of type label - Literal(Box), -} - -#[derive(Debug, Clone)] -pub enum Set { - Var(Variable), // should be of type set - Literal(super::structure::RSset), - Append(Box, Element), - Union(Box, Box), - Intersection(Box, Box), - Difference(Box, Box), - SimmetricDifference(Box, Box), - ValueOfLabel(Label, Qualifier), -} - -#[derive(Debug, Clone)] -pub enum Element { - Var(Variable), // should be of type element - Literal(super::translator::IdType), -} - -#[derive(Debug, Clone)] -pub enum Str { - Var(Variable), // should be of type string - Literal(String), - Concat(Box, Box), - ArithmeticToString(Box), - BooleanToString(Box), - ElementToString(Element), - CommonSubstring(Box, Box), -} - -#[derive(Debug, Clone)] -pub enum AssignmentVar { - Var(Variable), - ValueOfVariable(Variable, QualifierAssignment), -} - -#[derive(Debug, Clone)] -pub struct Variable { - name: String, +pub enum Range { + IterateOverSet(Box), + IterateInRange(Box, Box), } #[derive(Debug, Clone, Copy)] -pub enum QualifierAssignment { +pub enum Unary { + Not, + Rand, + + Empty, + Length, + ToStr, + Qualifier(Qualifier) +} + + +#[derive(Debug, Clone, Copy)] +pub enum QualifierRestricted { Entities, Context, Reactants, @@ -141,23 +83,33 @@ pub enum QualifierAssignment { #[derive(Debug, Clone, Copy)] pub enum Qualifier { - Entities, - Context, AvailableEntities, - - Reactants, - ReactantsAbsent, AllReactants, - - Inhibitors, - InhibitorsPresent, AllInhibitors, - - Products, + Restricted(QualifierRestricted), } -#[derive(Debug, Clone)] -pub enum Range { - IterateOverSet(Set), - IterateInRange(Box, Box), +#[derive(Debug, Clone, Copy)] +pub enum Binary { + And, + Or, + Xor, + Less, + LessEq, + More, + MoreEq, + Eq, + NotEq, + Plus, + Minus, + Times, + Exponential, + Quotient, + Reminder, + Concat, + + SubStr, + Min, + Max, + CommonSubStr, } diff --git a/src/rsprocess/grammar.lalrpop b/src/rsprocess/grammar.lalrpop index a46f116..1b8a5d7 100644 --- a/src/rsprocess/grammar.lalrpop +++ b/src/rsprocess/grammar.lalrpop @@ -5,7 +5,9 @@ use crate::rsprocess::structure::{RSset, RSprocess, RSenvironment, RSsystem, + RSlabel, RSreaction}; +use crate::rsprocess::structure::assert; use crate::rsprocess::translator::{Translator, IdType}; use crate::rsprocess::presets::Instructions; use crate::rsprocess::presets; @@ -120,6 +122,7 @@ Reaction: RSreaction = { RSreaction::from(r, i, p), } + // ----------------------------------------------------------------------------- // ContextParser // ----------------------------------------------------------------------------- @@ -152,6 +155,7 @@ CTX_process: RSprocess = { } }; + // ----------------------------------------------------------------------------- // EnvironmentParser // ----------------------------------------------------------------------------- @@ -165,28 +169,154 @@ Env_term: (IdType, RSprocess) = { (translator.encode(identifier), k) }; + // ----------------------------------------------------------------------------- // AssertParser // ----------------------------------------------------------------------------- -// pub Assert: Box = { -// => Box::new(f) -// }; +pub Assert: Box = { + "fn" "{" "}" => + Box::new(assert::RSassert{tree: f}), +}; + +AssertTree: assert::Tree = { + ";" => + assert::Tree::Concat(Box::new(t1), Box::new(t2)), + => t, +} + +AssertTree2: assert::Tree = { + "if" + "then" "{" "}" => + assert::Tree::If(Box::new(e), Box::new(t)), + + "if" + "then" "{" "}" + "else" "{" "}" => + assert::Tree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)), + + "let" "=" => + assert::Tree::Assignment(v, Box::new(e)), + + "return" => + assert::Tree::Return(Box::new(e)), + + "for" "in" "{" "}" => + assert::Tree::For(v, r, Box::new(t)), +} + +AssertAssignmentVar: assert::AssignmentVariable = { + => assert::AssignmentVariable::Var(v), + "." => + assert::AssignmentVariable::QualifiedVar(v, q), +} + +AssertVariable: assert::Variable = { + => assert::Variable::from(v) +} + +AssertExpression: assert::Expression = { + "(" ")" => e, + "True" => assert::Expression::True, + "False" => assert::Expression::False, + + // If changing IntegerType in assert.rs, also change from Num to another + // similar parser with different return type + => assert::Expression::Integer(i), + + => assert::Expression::Label(Box::new(lab)), + => assert::Expression::Set(set), + "'" "'" => assert::Expression::Element(translator.encode(el)), + + // strings + PATH => assert::Expression::String(<>.trim_end_matches("\"") + .trim_start_matches("\"") + .to_string()), + + => + assert::Expression::Unary(unp, Box::new(e)), + "(" ")" => + assert::Expression::Unary(uns, Box::new(e)), + + "(" ")" => + assert::Expression::Binary(b, Box::new(e1), Box::new(e2)), + + "(" "," ")" => + assert::Expression::Binary(b, Box::new(e1), Box::new(e2)), +} + +AssertUnaryPrefix: assert::Unary = { + "not" => assert::Unary::Not, + "rand" => assert::Unary::Rand, +} + +AssertUnarySuffix: assert::Unary = { + ".empty" => assert::Unary::Empty, + ".length" => assert::Unary::Length, + ".tostr" => assert::Unary::ToStr, + "." => assert::Unary::Qualifier(q), +} + +AssertBinary: assert::Binary = { + "&&" => assert::Binary::And, + "||" => assert::Binary::Or, + "^^" => assert::Binary::Xor, + "<" => assert::Binary::Less, + "<=" => assert::Binary::LessEq, + ">" => assert::Binary::More, + ">=" => assert::Binary::MoreEq, + "==" => assert::Binary::Eq, + "!=" => assert::Binary::NotEq, + "+" => assert::Binary::Plus, + "-" => assert::Binary::Minus, + "*" => assert::Binary::Times, + "^" => assert::Binary::Exponential, + "/" => assert::Binary::Quotient, + "%" => assert::Binary::Reminder, + "::" => assert::Binary::Concat, +} + +AssertBinaryPrefix: assert::Binary = { + "substr" => assert::Binary::SubStr, + "min" => assert::Binary::Min, + "max" => assert::Binary::Max, + "commonsubstr" => assert::Binary::CommonSubStr, +} + +AssertQualifier: assert::Qualifier = { + "AvailableEntities" => assert::Qualifier::AvailableEntities, + "AllReactants" => assert::Qualifier::AllReactants, + "AllInhibitors" => assert::Qualifier::AllInhibitors, + => assert::Qualifier::Restricted(q), +} + +AssertQualifierRestricted: assert::QualifierRestricted = { + "Entities" => assert::QualifierRestricted::Entities, + "Context" => assert::QualifierRestricted::Context, + "Reactants" => assert::QualifierRestricted::Reactants, + "ReactantsAbsent" => assert::QualifierRestricted::ReactantsAbsent, + "Inhibitors" => assert::QualifierRestricted::Inhibitors, + "InhibitorsPresent" => assert::QualifierRestricted::InhibitorsPresent, + "Products" => assert::QualifierRestricted::Products, +} + +AssertLabel: RSlabel = { + "[" + "Entities" ":" "," + "Context" ":" "," + "Reactants" ":" "," + "ReactantsAbsent" ":" "," + "Inhibitors" ":" "," + "InhibitorsPresent" ":" "," + "Products" ":" "," + "]" => RSlabel::create(e, c, r, r_a, i, i_p, p) +} + +AssertRange: assert::Range = { + "{" "}" => assert::Range::IterateOverSet(Box::new(e)), + "{" ".." "}" => + assert::Range::IterateInRange(Box::new(e1), Box::new(e2)), +} -// Formula_Assert: RSassert = { -// "-" => RSassert::Not(Box::new(f)), -// "(" "^" ")" => -// RSassert::Xor(Box::new(f1), Box::new(f2)), -// "(" > ")" => RSassert::Or(f), -// "(" > ")" => RSassert::And(f), -// "inW" => RSassert::Sub(c, RSassertOp::InW), -// "inR" => RSassert::Sub(c, RSassertOp::InR), -// "inI" => RSassert::Sub(c, RSassertOp::InI), -// "inP" => RSassert::Sub(c, RSassertOp::InP), -// "?" "inW" => RSassert::NonEmpty(RSassertOp::InW), -// "?" "inR" => RSassert::NonEmpty(RSassertOp::InR), -// "?" "inI" => RSassert::NonEmpty(RSassertOp::InI), -// "?" "inP" => RSassert::NonEmpty(RSassertOp::InP), -// }; // ----------------------------------------------------------------------------- // BHMLParser @@ -272,7 +402,9 @@ LiteralSeparatorNode: graph::NodeDisplayBase = { LiteralSeparatorEdge: graph::EdgeDisplayBase = { PATH => graph::EdgeDisplayBase::String { - string: <>.trim_end_matches("\"").trim_start_matches("\"").to_string() + string: <>.trim_end_matches("\"") + .trim_start_matches("\"") + .to_string() } }; diff --git a/src/rsprocess/structure.rs b/src/rsprocess/structure.rs index 09a2588..e7914e3 100644 --- a/src/rsprocess/structure.rs +++ b/src/rsprocess/structure.rs @@ -551,6 +551,28 @@ impl RSlabel { } } + #[allow(clippy::too_many_arguments)] + pub fn create( + available_entities: RSset, + context: RSset, + reactants: RSset, + reactants_absent: RSset, + inhibitors: RSset, + inhibitors_present: RSset, + products: RSset, + ) -> Self { + RSlabel { + available_entities: available_entities.clone(), + context: context.clone(), + t: available_entities.union(&context), + reactants, + reactants_absent, + inhibitors, + inhibitors_present, + products, + } + } + pub fn get_context(&self) -> (&RSset, &RSset, &RSset) { ( &self.available_entities,