display methods, fixing parsing for assert

This commit is contained in:
elvis
2025-07-30 18:05:55 +02:00
parent fde3c45a12
commit 39837498b3
2 changed files with 287 additions and 108 deletions

View File

@ -20,7 +20,11 @@ pub enum Tree {
For(Variable, Range, Box<Tree>), For(Variable, Range, Box<Tree>),
} }
pub type Variable = String; #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Variable {
Id(String),
Label
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum AssignmentVariable { pub enum AssignmentVariable {
@ -28,15 +32,6 @@ pub enum AssignmentVariable {
QualifiedVar(Variable, QualifierRestricted) QualifiedVar(Variable, QualifierRestricted)
} }
impl fmt::Display for AssignmentVariable {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Var(v) => write!(f, "{v}"),
Self::QualifiedVar(v, q) => write!(f, "{v}.{q}"),
}
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Expression { pub enum Expression {
True, True,
@ -67,9 +62,26 @@ pub enum Unary {
Length, Length,
ToStr, ToStr,
Qualifier(Qualifier), Qualifier(Qualifier),
ToEl
} }
impl Unary { impl Unary {
fn is_prefix(&self) -> bool {
match self {
Self::Not |
Self::Rand => {true},
Self::Empty |
Self::Length |
Self::ToStr |
Self::Qualifier(_) |
Self::ToEl => {false}
}
}
fn is_suffix(&self) -> bool {
!self.is_prefix()
}
fn associated_types_unary(&self) -> Vec<AssertionTypes> { fn associated_types_unary(&self) -> Vec<AssertionTypes> {
match self { match self {
Unary::Not => vec![AssertionTypes::Boolean], Unary::Not => vec![AssertionTypes::Boolean],
@ -80,25 +92,12 @@ impl Unary {
Unary::ToStr => vec![AssertionTypes::Boolean, Unary::ToStr => vec![AssertionTypes::Boolean,
AssertionTypes::Integer, AssertionTypes::Integer,
AssertionTypes::Element], AssertionTypes::Element],
Unary::Qualifier(_) => vec![AssertionTypes::Set] Unary::Qualifier(_) => vec![AssertionTypes::Set],
Unary::ToEl => vec![AssertionTypes::String]
} }
} }
} }
impl fmt::Display for Unary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Unary::Not => write!(f, "not"),
Unary::Rand => write!(f, "rand"),
Unary::Empty => write!(f, ".empty"),
Unary::Length => write!(f, ".length"),
Unary::ToStr => write!(f, ".tostr"),
Unary::Qualifier(q) => write!(f, ".{q}"),
}
}
}
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum QualifierRestricted { pub enum QualifierRestricted {
Entities, Entities,
@ -110,27 +109,6 @@ pub enum QualifierRestricted {
Products, Products,
} }
impl fmt::Display for QualifierRestricted {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
QualifierRestricted::Entities =>
write!(f, "Entities"),
QualifierRestricted::Context =>
write!(f, "Context"),
QualifierRestricted::Reactants =>
write!(f, "Reactants"),
QualifierRestricted::ReactantsAbsent =>
write!(f, "ReactantsAbsent"),
QualifierRestricted::Inhibitors =>
write!(f, "Inhibitors"),
QualifierRestricted::InhibitorsPresent =>
write!(f, "InhibitorsPresent"),
QualifierRestricted::Products =>
write!(f, "Products"),
}
}
}
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum Qualifier { pub enum Qualifier {
AvailableEntities, AvailableEntities,
@ -139,18 +117,6 @@ pub enum Qualifier {
Restricted(QualifierRestricted), Restricted(QualifierRestricted),
} }
impl fmt::Display for Qualifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::AvailableEntities => write!(f, "AvailableEntities"),
Self::AllReactants => write!(f, "AllReactants"),
Self::AllInhibitors => write!(f, "AllInhibitors"),
Self::Restricted(q) => write!(f, "{q}"),
}
}
}
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum Binary { pub enum Binary {
And, And,
@ -177,6 +143,60 @@ pub enum Binary {
} }
impl Binary { impl Binary {
fn is_prefix(&self) -> bool {
match self {
Self::And |
Self::Or |
Self::Xor |
Self::Less |
Self::LessEq |
Self::More |
Self::MoreEq |
Self::Eq |
Self::NotEq |
Self::Plus |
Self::Minus |
Self::Times |
Self::Exponential |
Self::Quotient |
Self::Reminder |
Self::Concat => false,
Self::SubStr |
Self::Min |
Self::Max |
Self::CommonSubStr => true,
}
}
fn is_suffix(&self) -> bool {
false
}
fn is_infix(&self) -> bool {
match self {
Self::And |
Self::Or |
Self::Xor |
Self::Less |
Self::LessEq |
Self::More |
Self::MoreEq |
Self::Eq |
Self::NotEq |
Self::Plus |
Self::Minus |
Self::Times |
Self::Exponential |
Self::Quotient |
Self::Reminder |
Self::Concat => true,
Self::SubStr |
Self::Min |
Self::Max |
Self::CommonSubStr => false,
}
}
fn associate( fn associate(
&self, &self,
t1: &AssertionTypes, t1: &AssertionTypes,
@ -274,40 +294,13 @@ impl Binary {
} }
} }
impl fmt::Display for Binary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::And => write!(f, "&&"),
Self::Or => write!(f, "||"),
Self::Xor => write!(f, "^^"),
Self::Less => write!(f, "<"),
Self::LessEq => write!(f, "<="),
Self::More => write!(f, ">"),
Self::MoreEq => write!(f, ">="),
Self::Eq => write!(f, "=="),
Self::NotEq => write!(f, "!="),
Self::Plus => write!(f, "+"),
Self::Minus => write!(f, "-"),
Self::Times => write!(f, "*"),
Self::Exponential => write!(f, "^"),
Self::Quotient => write!(f, "/"),
Self::Reminder => write!(f, "%"),
Self::Concat => write!(f, "::"),
Self::SubStr => write!(f, "substr"),
Self::Min => write!(f, "min"),
Self::Max => write!(f, "max"),
Self::CommonSubStr => write!(f, "commonsubstr"),
}
}
}
use core::fmt; use core::fmt;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
use std::collections::HashMap; use std::collections::HashMap;
struct Context { struct Context {
data: HashMap<Variable, AssertionTypes>, data: HashMap<String, AssertionTypes>,
ty_return: Option<AssertionTypes> ty_return: Option<AssertionTypes>
} }
@ -326,10 +319,13 @@ impl Context {
) -> Result<(), String> { ) -> Result<(), String> {
match v { match v {
AssignmentVariable::Var(v) => { AssignmentVariable::Var(v) => {
if let Variable::Id(v) = v {
self.data.insert(v.clone(), ty); self.data.insert(v.clone(), ty);
}
Ok(()) Ok(())
}, },
AssignmentVariable::QualifiedVar(v, q) => { AssignmentVariable::QualifiedVar(Variable::Label, _) => Ok(()),
AssignmentVariable::QualifiedVar(Variable::Id(v), q) => {
if let Some(AssertionTypes::Label) = self.data.get(v) { if let Some(AssertionTypes::Label) = self.data.get(v) {
Ok(()) Ok(())
} else { } else {
@ -362,6 +358,11 @@ impl Context {
v: &Variable, v: &Variable,
ty: AssertionTypes ty: AssertionTypes
) -> Result<(), String> { ) -> Result<(), String> {
let v = match v {
Variable::Label => return Err("Protected word label used in for \
assignment.".into()),
Variable::Id(v) => v
};
match ty { match ty {
AssertionTypes::RangeSet => { AssertionTypes::RangeSet => {
self.data.insert(v.clone(), AssertionTypes::Element); self.data.insert(v.clone(), AssertionTypes::Element);
@ -383,13 +384,22 @@ impl Context {
) -> Result<AssertionTypes, String> { ) -> Result<AssertionTypes, String> {
match v { match v {
AssignmentVariable::Var(v) => { AssignmentVariable::Var(v) => {
match v {
Variable::Label => Ok(AssertionTypes::Label),
Variable::Id(v) => {
if let Some(ty) = self.data.get(v) { if let Some(ty) = self.data.get(v) {
Ok(*ty) Ok(*ty)
} else { } else {
Err(format!("Could not find variable {v}.")) Err(format!("Could not find variable {v}."))
} }
}
}
}, },
AssignmentVariable::QualifiedVar(var, _) => { AssignmentVariable::QualifiedVar(var, _) => {
let var = match var {
Variable::Id(v) => v,
Variable::Label => return Ok(AssertionTypes::Set),
};
if let Some(ty) = self.data.get(var) { if let Some(ty) = self.data.get(var) {
if *ty == AssertionTypes::Label { if *ty == AssertionTypes::Label {
Ok(AssertionTypes::Set) Ok(AssertionTypes::Set)
@ -559,3 +569,164 @@ impl RSassert {
Ok(()) Ok(())
} }
} }
// -----------------------------------------------------------------------------
// Display Implementation for all types
// -----------------------------------------------------------------------------
impl fmt::Display for RSassert {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "label {{\n{}\n}}", self.tree)
}
}
impl fmt::Display for Tree {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Concat(t1, t2) => {write!(f, "{t1};\n{t2}")},
Self::If(exp, t) => {write!(f, "if {exp} {{\n{t}\n}}")},
Self::IfElse(exp, t1, t2) => {
write!(f, "if {exp} {{\n{t1}\n}} else {{\n{t2}\n}}")
},
Self::Assignment(v, exp) => {write!(f, "{v} = {exp}")},
Self::Return(exp) => {write!(f, "return {exp}")},
Self::For(v, r, t) => {write!(f, "for {v} in {r} {{\n{t}\n}}")},
}
}
}
impl fmt::Display for Variable {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Label => {write!(f, "label")},
Self::Id(s) => {write!(f, "{s}")}
}
}
}
impl fmt::Display for AssignmentVariable {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Var(v) => write!(f, "{v}"),
Self::QualifiedVar(v, q) => write!(f, "{v}.{q}"),
}
}
}
impl fmt::Display for Expression {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::True => {write!(f, "True")},
Self::False => {write!(f, "False")},
Self::Integer(i) => {write!(f, "{i}")},
Self::Label(rslabel) => {write!(f, "{rslabel:?}")},
Self::Set(set) => {write!(f, "{set:?}")},
Self::Element(el) => {write!(f, "'{el}'")},
Self::String(s) => {write!(f, r#""{s}""#)},
Self::Var(v) => {write!(f, "{v}")},
Self::Unary(u, exp) => {
if u.is_prefix() {
write!(f, "{u}({exp})")
} else if u.is_suffix() {
write!(f, "{exp}{u}")
} else {
unreachable!()
}
},
Self::Binary(b, exp1, exp2) => {
if b.is_prefix() {
write!(f, "{b}({exp1}, {exp2})")
} else if b.is_suffix() {
write!(f, "({exp1}, {exp2}){b}")
} else if b.is_infix() {
write!(f, "({exp1} {b} {exp2})")
} else {
unreachable!()
}
},
}
}
}
impl fmt::Display for Range {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::IterateOverSet(exp) => {write!(f, "{{{exp}}}")},
Self::IterateInRange(exp1, exp2) => {write!(f, "{exp1}..{exp2}")}
}
}
}
impl fmt::Display for Unary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Unary::Not => write!(f, "not"),
Unary::Rand => write!(f, "rand"),
Unary::Empty => write!(f, ".empty"),
Unary::Length => write!(f, ".length"),
Unary::ToStr => write!(f, ".tostr"),
Unary::Qualifier(q) => write!(f, ".{q}"),
Unary::ToEl => write!(f, ".toel")
}
}
}
impl fmt::Display for QualifierRestricted {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
QualifierRestricted::Entities =>
write!(f, "Entities"),
QualifierRestricted::Context =>
write!(f, "Context"),
QualifierRestricted::Reactants =>
write!(f, "Reactants"),
QualifierRestricted::ReactantsAbsent =>
write!(f, "ReactantsAbsent"),
QualifierRestricted::Inhibitors =>
write!(f, "Inhibitors"),
QualifierRestricted::InhibitorsPresent =>
write!(f, "InhibitorsPresent"),
QualifierRestricted::Products =>
write!(f, "Products"),
}
}
}
impl fmt::Display for Qualifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::AvailableEntities => write!(f, "AvailableEntities"),
Self::AllReactants => write!(f, "AllReactants"),
Self::AllInhibitors => write!(f, "AllInhibitors"),
Self::Restricted(q) => write!(f, "{q}"),
}
}
}
impl fmt::Display for Binary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::And => write!(f, "&&"),
Self::Or => write!(f, "||"),
Self::Xor => write!(f, "^^"),
Self::Less => write!(f, "<"),
Self::LessEq => write!(f, "<="),
Self::More => write!(f, ">"),
Self::MoreEq => write!(f, ">="),
Self::Eq => write!(f, "=="),
Self::NotEq => write!(f, "!="),
Self::Plus => write!(f, "+"),
Self::Minus => write!(f, "-"),
Self::Times => write!(f, "*"),
Self::Exponential => write!(f, "^"),
Self::Quotient => write!(f, "/"),
Self::Reminder => write!(f, "%"),
Self::Concat => write!(f, "::"),
Self::SubStr => write!(f, "substr"),
Self::Min => write!(f, "min"),
Self::Max => write!(f, "max"),
Self::CommonSubStr => write!(f, "commonsubstr"),
}
}
}

View File

@ -30,7 +30,6 @@ match {
"r:", "i:", "p:", "r:", "i:", "p:",
"-", "^", "-", "^",
"true", "false", "true", "false",
"inW", "inR", "inI", "inP",
"Environment", "Initial Entities", "Context", "Reactions", "Environment", "Initial Entities", "Context", "Reactions",
"Weights", "Sets", "Weights", "Sets",
"Print", "Save", "Print", "Save",
@ -38,6 +37,7 @@ match {
"Stats", "Target", "Run", "Loop", "Frequency", "LimitFrequency", "Stats", "Target", "Run", "Loop", "Frequency", "LimitFrequency",
"FastFrequency", "Digraph", "Bisimilarity", "FastFrequency", "Digraph", "Bisimilarity",
"Deserialize", "Deserialize",
"?",
"Hide", "Hide",
"Entities", "MaskEntities", "UncommonEntities", "UncommonMaskEntities", "Entities", "MaskEntities", "UncommonEntities", "UncommonMaskEntities",
"MaskContext", "UncommonContext", "UncommonMaskContext", "MaskContext", "UncommonContext", "UncommonMaskContext",
@ -49,6 +49,11 @@ match {
"UncommonEntitiesDeleted", "UncommonMaskEntitiesDeleted", "UncommonEntitiesDeleted", "UncommonMaskEntitiesDeleted",
"EntitiesAdded", "MaskEntitiesAdded", "EntitiesAdded", "MaskEntitiesAdded",
"UncommonEntitiesAdded", "UncommonMaskEntitiesAdded", "UncommonEntitiesAdded", "UncommonMaskEntitiesAdded",
"label", "if", "then", "else", "let", "=", "return", "for", "in",
"not", "rand", ".empty", ".length", ".tostr",
"&&", "||", "^^", "<=", ">=", "==", "!=", "+", "*", "/", "%",
"::", "substr", "min", "max", "commonsubstr",
"AvailableEntities", "AllReactants", "AllInhibitors",
} else { } else {
r"[0-9]+" => NUMBER r"[0-9]+" => NUMBER
} else { } else {
@ -174,7 +179,7 @@ Env_term: (IdType, RSprocess) = {
// AssertParser // AssertParser
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
pub Assert: Box<assert::RSassert> = { pub Assert: Box<assert::RSassert> = {
"fn" "{" <f: AssertTree> "}" => "label" "{" <f: AssertTree> "}" =>
Box::new(assert::RSassert{tree: f}), Box::new(assert::RSassert{tree: f}),
}; };
@ -211,13 +216,27 @@ AssertAssignmentVar: assert::AssignmentVariable = {
} }
AssertVariable: assert::Variable = { AssertVariable: assert::Variable = {
<v: Literal> => v "label" => assert::Variable::Label,
<v: Literal> => assert::Variable::Id(v),
} }
AssertExpression: assert::Expression = { AssertExpression: assert::Expression = {
<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)),
"(" <e: AssertExpression> ")" => e, "(" <e: AssertExpression> ")" => e,
"True" => assert::Expression::True, "true" => assert::Expression::True,
"False" => assert::Expression::False, "false" => assert::Expression::False,
<v: AssertAssignmentVar> => assert::Expression::Var(v),
// If changing IntegerType in assert.rs, also change from Num to another // If changing IntegerType in assert.rs, also change from Num to another
// similar parser with different return type // similar parser with different return type
@ -231,17 +250,6 @@ AssertExpression: assert::Expression = {
PATH => assert::Expression::String(<>.trim_end_matches("\"") PATH => assert::Expression::String(<>.trim_end_matches("\"")
.trim_start_matches("\"") .trim_start_matches("\"")
.to_string()), .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 = { AssertUnaryPrefix: assert::Unary = {