Version two of assert, now with parser

This commit is contained in:
elvis
2025-07-29 22:56:32 +02:00
parent 1a2ffe1b32
commit c28a8c9685
3 changed files with 240 additions and 134 deletions

View File

@ -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<Tree>, Box<Tree>),
If(Box<Boolean>, Box<Tree>),
IfElse(Box<Boolean>, Box<Tree>, Box<Tree>),
Assignment(AssignmentVar, Box<Expression>),
If(Box<Expression>, Box<Tree>),
IfElse(Box<Expression>, Box<Tree>, Box<Tree>),
Assignment(AssignmentVariable, Box<Expression>),
Return(Box<Expression>),
For(Variable, Range, Box<Tree>),
}
#[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<Boolean>),
And(Box<Boolean>, Box<Boolean>),
Or(Box<Boolean>, Box<Boolean>),
Xor(Box<Boolean>, Box<Boolean>),
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<Arithmetic>, Box<Arithmetic>),
Minus(Box<Arithmetic>, Box<Arithmetic>),
Times(Box<Arithmetic>, Box<Arithmetic>),
Quotient(Box<Arithmetic>, Box<Arithmetic>),
Reminder(Box<Arithmetic>, Box<Arithmetic>),
Exponential(Box<Arithmetic>, Box<Arithmetic>),
Rand(Box<Arithmetic>, Box<Arithmetic>),
Min(Box<Arithmetic>, Box<Arithmetic>),
Max(Box<Arithmetic>, Box<Arithmetic>),
Label(Box<super::structure::RSlabel>),
Set(super::structure::RSset),
Element(super::translator::IdType),
String(String),
Var(AssignmentVariable),
SetLength(Set),
StrLength(Str),
Unary(Unary, Box<Expression>),
Binary(Binary, Box<Expression>, Box<Expression>),
}
#[derive(Debug, Clone)]
pub enum Label {
Var(Variable), // should be of type label
Literal(Box<super::structure::RSlabel>),
}
#[derive(Debug, Clone)]
pub enum Set {
Var(Variable), // should be of type set
Literal(super::structure::RSset),
Append(Box<Set>, Element),
Union(Box<Set>, Box<Set>),
Intersection(Box<Set>, Box<Set>),
Difference(Box<Set>, Box<Set>),
SimmetricDifference(Box<Set>, Box<Set>),
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<Str>, Box<Str>),
ArithmeticToString(Box<Arithmetic>),
BooleanToString(Box<Boolean>),
ElementToString(Element),
CommonSubstring(Box<Str>, Box<Str>),
}
#[derive(Debug, Clone)]
pub enum AssignmentVar {
Var(Variable),
ValueOfVariable(Variable, QualifierAssignment),
}
#[derive(Debug, Clone)]
pub struct Variable {
name: String,
pub enum Range {
IterateOverSet(Box<Expression>),
IterateInRange(Box<Expression>, Box<Expression>),
}
#[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<Arithmetic>, Box<Arithmetic>),
#[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,
}

View File

@ -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<RSassert> = {
// <f: Formula_Assert> => Box::new(f)
// };
pub Assert: Box<assert::RSassert> = {
"fn" "{" <f: AssertTree> "}" =>
Box::new(assert::RSassert{tree: f}),
};
AssertTree: assert::Tree = {
<t1: AssertTree2> ";" <t2: AssertTree> =>
assert::Tree::Concat(Box::new(t1), Box::new(t2)),
<t: AssertTree2> => t,
}
AssertTree2: assert::Tree = {
"if" <e: AssertExpression>
"then" "{" <t: AssertTree> "}" =>
assert::Tree::If(Box::new(e), Box::new(t)),
"if" <e: AssertExpression>
"then" "{" <t1: AssertTree> "}"
"else" "{" <t2: AssertTree> "}" =>
assert::Tree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)),
"let" <v: AssertAssignmentVar> "=" <e: AssertExpression> =>
assert::Tree::Assignment(v, Box::new(e)),
"return" <e: AssertExpression> =>
assert::Tree::Return(Box::new(e)),
"for" <v: AssertVariable> "in" <r: AssertRange> "{" <t: AssertTree> "}" =>
assert::Tree::For(v, r, Box::new(t)),
}
AssertAssignmentVar: assert::AssignmentVariable = {
<v: AssertVariable> => assert::AssignmentVariable::Var(v),
<v: AssertVariable> "." <q: AssertQualifierRestricted> =>
assert::AssignmentVariable::QualifiedVar(v, q),
}
AssertVariable: assert::Variable = {
<v: Literal> => assert::Variable::from(v)
}
AssertExpression: assert::Expression = {
"(" <e: AssertExpression> ")" => 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
<i: Num> => assert::Expression::Integer(i),
<lab: AssertLabel> => assert::Expression::Label(Box::new(lab)),
<set: Set_of_entities> => assert::Expression::Set(set),
"'" <el: Literal> "'" => assert::Expression::Element(translator.encode(el)),
// strings
PATH => assert::Expression::String(<>.trim_end_matches("\"")
.trim_start_matches("\"")
.to_string()),
<unp: AssertUnaryPrefix> <e: AssertExpression> =>
assert::Expression::Unary(unp, Box::new(e)),
"(" <e: AssertExpression> ")" <uns: AssertUnarySuffix> =>
assert::Expression::Unary(uns, Box::new(e)),
"(" <e1: AssertExpression> <b: AssertBinary> <e2: AssertExpression> ")" =>
assert::Expression::Binary(b, Box::new(e1), Box::new(e2)),
<b: AssertBinaryPrefix>
"(" <e1: AssertExpression> "," <e2: AssertExpression> ")" =>
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,
"." <q: AssertQualifier> => 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,
<q: AssertQualifierRestricted> => 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" ":" <e: Set_of_entities> ","
"Context" ":" <c: Set_of_entities> ","
"Reactants" ":" <r: Set_of_entities> ","
"ReactantsAbsent" ":" <r_a: Set_of_entities> ","
"Inhibitors" ":" <i: Set_of_entities> ","
"InhibitorsPresent" ":" <i_p: Set_of_entities> ","
"Products" ":" <p: Set_of_entities> ","
"]" => RSlabel::create(e, c, r, r_a, i, i_p, p)
}
AssertRange: assert::Range = {
"{" <e: AssertExpression> "}" => assert::Range::IterateOverSet(Box::new(e)),
"{" <e1: AssertExpression> ".." <e2: AssertExpression> "}" =>
assert::Range::IterateInRange(Box::new(e1), Box::new(e2)),
}
// Formula_Assert: RSassert = {
// "-" <f: Formula_Assert> => RSassert::Not(Box::new(f)),
// "(" <f1: Formula_Assert> "^" <f2: Formula_Assert> ")" =>
// RSassert::Xor(Box::new(f1), Box::new(f2)),
// "(" <f: Separated<Formula_Assert, "\\/">> ")" => RSassert::Or(f),
// "(" <f: Separated<Formula_Assert, "/\\">> ")" => RSassert::And(f),
// <c: Set_of_entities> "inW" => RSassert::Sub(c, RSassertOp::InW),
// <c: Set_of_entities> "inR" => RSassert::Sub(c, RSassertOp::InR),
// <c: Set_of_entities> "inI" => RSassert::Sub(c, RSassertOp::InI),
// <c: Set_of_entities> "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()
}
};

View File

@ -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,