More exaustive example, fixed grammar

This commit is contained in:
elvis
2025-09-11 02:17:40 +02:00
parent 91f69c9e6d
commit 63c34981ae
5 changed files with 396 additions and 102 deletions

View File

@ -279,15 +279,15 @@ impl Unary {
type_exp: &AssertionTypes, type_exp: &AssertionTypes,
) -> Result<AssertionTypes, String> { ) -> Result<AssertionTypes, String> {
match (self, type_exp) { match (self, type_exp) {
(Self::Not, AssertionTypes::Boolean) => Ok(AssertionTypes::Boolean), (Self::Not, AssertionTypes::Boolean) =>
(Self::Rand, AssertionTypes::Integer) => { Ok(AssertionTypes::Boolean),
Ok(AssertionTypes::Integer) (Self::Rand, AssertionTypes::Integer) =>
} Ok(AssertionTypes::Integer),
(Self::Empty, AssertionTypes::Set) => Ok(AssertionTypes::Boolean), (Self::Empty, AssertionTypes::Set) =>
(Self::Length, AssertionTypes::Set) Ok(AssertionTypes::Boolean),
| (Self::Length, AssertionTypes::String) => { (Self::Length, AssertionTypes::Set) |
Ok(AssertionTypes::Integer) (Self::Length, AssertionTypes::String) =>
} Ok(AssertionTypes::Integer),
(Self::ToStr, AssertionTypes::Boolean) (Self::ToStr, AssertionTypes::Boolean)
| (Self::ToStr, AssertionTypes::Element) | (Self::ToStr, AssertionTypes::Element)
| (Self::ToStr, AssertionTypes::Integer) => { | (Self::ToStr, AssertionTypes::Integer) => {
@ -470,8 +470,11 @@ impl Binary {
(Self::Concat, AssertionTypes::String, AssertionTypes::String) => { (Self::Concat, AssertionTypes::String, AssertionTypes::String) => {
Ok(AssertionTypes::String) Ok(AssertionTypes::String)
} }
(Self::Concat, AssertionTypes::Set, AssertionTypes::Element) => {
Ok(AssertionTypes::Set)
}
(Self::SubStr, AssertionTypes::String, AssertionTypes::String) => { (Self::SubStr, AssertionTypes::String, AssertionTypes::String) => {
Ok(AssertionTypes::Boolean) Ok(AssertionTypes::Integer)
} }
(Self::Min, AssertionTypes::Integer, AssertionTypes::Integer) (Self::Min, AssertionTypes::Integer, AssertionTypes::Integer)
| (Self::Max, AssertionTypes::Integer, AssertionTypes::Integer) => { | (Self::Max, AssertionTypes::Integer, AssertionTypes::Integer) => {
@ -860,20 +863,30 @@ impl AssertReturnValue {
(Binary::Less, Set(s1), Set(s2)) => { (Binary::Less, Set(s1), Set(s2)) => {
Boolean(s1.is_subset(&s2) && !s2.is_subset(&s1)) Boolean(s1.is_subset(&s2) && !s2.is_subset(&s1))
} }
(Binary::LessEq, Integer(i1), Integer(i2)) => Boolean(i1 <= i2), (Binary::LessEq, Integer(i1), Integer(i2)) =>
(Binary::LessEq, Set(s1), Set(s2)) => Boolean(s1.is_subset(&s2)), Boolean(i1 <= i2),
(Binary::More, Integer(i1), Integer(i2)) => Boolean(i1 > i2), (Binary::LessEq, Set(s1), Set(s2)) =>
(Binary::More, Set(s1), Set(s2)) => { Boolean(s1.is_subset(&s2)),
Boolean(s2.is_subset(&s1) && !s1.is_subset(&s2)) (Binary::More, Integer(i1), Integer(i2)) =>
} Boolean(i1 > i2),
(Binary::MoreEq, Integer(i1), Integer(i2)) => Boolean(i1 >= i2), (Binary::More, Set(s1), Set(s2)) =>
(Binary::MoreEq, Set(s1), Set(s2)) => Boolean(s1.is_subset(&s2)), Boolean(s2.is_subset(&s1) && !s1.is_subset(&s2)),
(Binary::Eq, Integer(i1), Integer(i2)) => Boolean(i1 == i2), (Binary::MoreEq, Integer(i1), Integer(i2)) =>
(Binary::Eq, Boolean(b1), Boolean(b2)) => Boolean(b1 == b2), Boolean(i1 >= i2),
(Binary::Eq, Element(el1), Element(el2)) => Boolean(el1 == el2), (Binary::MoreEq, Set(s1), Set(s2)) =>
(Binary::Eq, Label(l1), Label(l2)) => Boolean(l1 == l2), Boolean(s2.is_subset(&s1)),
(Binary::Eq, String(s1), String(s2)) => Boolean(s1 == s2), (Binary::Eq, Integer(i1), Integer(i2)) =>
(Binary::Eq, Set(set1), Set(set2)) => Boolean(set1 == set2), Boolean(i1 == i2),
(Binary::Eq, Boolean(b1), Boolean(b2)) =>
Boolean(b1 == b2),
(Binary::Eq, Element(el1), Element(el2)) =>
Boolean(el1 == el2),
(Binary::Eq, Label(l1), Label(l2)) =>
Boolean(l1 == l2),
(Binary::Eq, String(s1), String(s2)) =>
Boolean(s1 == s2),
(Binary::Eq, Set(set1), Set(set2)) =>
Boolean(set1 == set2),
(Binary::NotEq, Integer(i1), Integer(i2)) => Boolean(i1 != i2), (Binary::NotEq, Integer(i1), Integer(i2)) => Boolean(i1 != i2),
(Binary::NotEq, Boolean(b1), Boolean(b2)) => Boolean(b1 != b2), (Binary::NotEq, Boolean(b1), Boolean(b2)) => Boolean(b1 != b2),
(Binary::NotEq, Element(el1), Element(el2)) => Boolean(el1 != el2), (Binary::NotEq, Element(el1), Element(el2)) => Boolean(el1 != el2),
@ -904,6 +917,8 @@ impl AssertReturnValue {
Integer(i1.rem_euclid(i2)) Integer(i1.rem_euclid(i2))
} }
(Binary::Concat, String(s1), String(s2)) => String(s1 + &s2), (Binary::Concat, String(s1), String(s2)) => String(s1 + &s2),
(Binary::Concat, Set(s), Element(e)) =>
Set(s.union(&set::Set::from([e]))),
(Binary::SubStr, String(s1), String(s2)) => { (Binary::SubStr, String(s1), String(s2)) => {
let mut len = s1.len() as i64; let mut len = s1.len() as i64;
for (p, c) in s1.chars().enumerate() { for (p, c) in s1.chars().enumerate() {

View File

@ -35,16 +35,16 @@ match {
"?", "?",
"Hide", "Hide",
"Entities", "MaskEntities", "UncommonEntities", "UncommonMaskEntities", "Entities", "MaskEntities", "UncommonEntities", "UncommonMaskEntities",
"MaskContext", "UncommonContext", "UncommonMaskContext", "MaskContext", "UncommonContext", "UncommonMaskContext", "Reactants",
"Products", "MaskProducts", "UncommonProducts", "UncommonMaskProducts", "Products", "MaskProducts", "UncommonProducts", "UncommonMaskProducts",
"Union", "MaskUnion", "UncommonUnion", "UncommonMaskUnion", "Union", "MaskUnion", "UncommonUnion", "UncommonMaskUnion",
"Difference", "MaskDifference", "Difference", "MaskDifference", "ReactantsAbsent", "Inhibitors",
"UncommonDifference", "UncommonMaskDifference", "UncommonDifference", "UncommonMaskDifference", "InhibitorsPresent",
"EntitiesDeleted", "MaskEntitiesDeleted", "EntitiesDeleted", "MaskEntitiesDeleted",
"UncommonEntitiesDeleted", "UncommonMaskEntitiesDeleted", "UncommonEntitiesDeleted", "UncommonMaskEntitiesDeleted",
"EntitiesAdded", "MaskEntitiesAdded", "EntitiesAdded", "MaskEntitiesAdded",
"UncommonEntitiesAdded", "UncommonMaskEntitiesAdded", "UncommonEntitiesAdded", "UncommonMaskEntitiesAdded",
"node", "entities", "system", "neighbours", "node", "entities", "system", "neighbours", "toel",
"label", "edge", "if", "then", "else", "let", "=", "return", "for", "in", "label", "edge", "if", "then", "else", "let", "=", "return", "for", "in",
"not", "rand", "empty", "length", "tostr", "source", "target", "not", "rand", "empty", "length", "tostr", "source", "target",
"&&", "||", "^^", "<=", ">=", "==", "!=", "+", "*", "/", "%", "&&", "||", "^^", "<=", ">=", "==", "!=", "+", "*", "/", "%",
@ -95,6 +95,10 @@ LiteralProcess: String = {
"Bisimilarity" => <>.into(), "Bisimilarity" => <>.into(),
"Deserialize" => <>.into(), "Deserialize" => <>.into(),
"Hide" => <>.into(), "Hide" => <>.into(),
"Reactants" => <>.into(),
"ReactantsAbsent" => <>.into(),
"Inhibitors" => <>.into(),
"InhibitorsPresent" => <>.into(),
"Entities" => <>.into(), "Entities" => <>.into(),
"MaskEntities" => <>.into(), "MaskEntities" => <>.into(),
"UncommonEntities" => <>.into(), "UncommonEntities" => <>.into(),
@ -127,6 +131,7 @@ LiteralProcess: String = {
"system" => <>.into(), "system" => <>.into(),
"label" => <>.into(), "label" => <>.into(),
"neighbours" => <>.into(), "neighbours" => <>.into(),
"toel" => <>.into(),
"edge" => <>.into(), "edge" => <>.into(),
"if" => <>.into(), "if" => <>.into(),
"then" => <>.into(), "then" => <>.into(),
@ -183,7 +188,7 @@ Separated_Or<T, C>: Vec<T> = {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// SetParser // SetParser
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
pub Set: set::Set = { Set: set::Set = {
<s: Set_of_entities> => s <s: Set_of_entities> => s
}; };
@ -199,7 +204,7 @@ Set_of_entities: set::Set = {
// ReactionParser // ReactionParser
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
pub Reactions: Vec<reaction::Reaction> = { Reactions: Vec<reaction::Reaction> = {
"(" ")" => vec![], "(" ")" => vec![],
"(" <s: Separated_Or<Reaction, ";">> ")" => s "(" <s: Separated_Or<Reaction, ";">> ")" => s
} }
@ -218,7 +223,7 @@ Reaction: reaction::Reaction = {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// ContextParser // ContextParser
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
pub Context: process::Process = { Context: process::Process = {
"[" "]" => process::Process::NondeterministicChoice{ children: vec![] }, "[" "]" => process::Process::NondeterministicChoice{ children: vec![] },
"[" <t: Separated_Or<Boxed_CTX_process, ",">> "]" => "[" <t: Separated_Or<Boxed_CTX_process, ",">> "]" =>
process::Process::NondeterministicChoice{ children: t } process::Process::NondeterministicChoice{ children: t }
@ -259,7 +264,7 @@ CTX_process: process::Process = {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// EnvironmentParser // EnvironmentParser
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
pub Environment: Box<environment::Environment> = { Environment: Box<environment::Environment> = {
"[" "]" => "[" "]" =>
Box::new(environment::Environment::default()), Box::new(environment::Environment::default()),
"[" <t: Separated_Or<Env_term, ",">> "]" => "[" <t: Separated_Or<Env_term, ",">> "]" =>
@ -283,21 +288,20 @@ Label: label::Label = {
"ReactantsAbsent" ":" <r_a: Set_of_entities> "," "ReactantsAbsent" ":" <r_a: Set_of_entities> ","
"Inhibitors" ":" <i: Set_of_entities> "," "Inhibitors" ":" <i: Set_of_entities> ","
"InhibitorsPresent" ":" <i_p: Set_of_entities> "," "InhibitorsPresent" ":" <i_p: Set_of_entities> ","
"Products" ":" <p: Set_of_entities> "," "Products" ":" <p: Set_of_entities> ","?
"]" => label::Label::create(e, c, r, r_a, i, i_p, p) "]" => label::Label::create(e, c, r, r_a, i, i_p, p)
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// AssertParser // AssertParser
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
pub Assert: Box<relabel::Assert> = { Assert: Box<relabel::Assert> = {
"label" "{" <f: AssertTree> "}" => "label" "{" <f: AssertTree> "}" =>
Box::new(relabel::Assert{tree: f}), Box::new(relabel::Assert{tree: f}),
}; };
AssertTree: relabel::Tree = { AssertTree: relabel::Tree = {
<t1: AssertTree2> ";" <t2: AssertTree> => <t1: AssertTree2> <t2: AssertTree> =>
relabel::Tree::Concat(Box::new(t1), Box::new(t2)), relabel::Tree::Concat(Box::new(t1), Box::new(t2)),
<t: AssertTree2> => t, <t: AssertTree2> => t,
} }
@ -305,83 +309,83 @@ AssertTree: relabel::Tree = {
AssertTree2: relabel::Tree = { AssertTree2: relabel::Tree = {
#[precedence(level="1")] #[precedence(level="1")]
"if" <e: AssertExpression> "if" <e: AssertExpression>
"then" "{" <t: AssertTree> "}" => "then" "{" <t: AssertTree> "}" ";"? =>
relabel::Tree::If(Box::new(e), Box::new(t)), relabel::Tree::If(Box::new(e), Box::new(t)),
#[precedence(level="0")] #[precedence(level="0")]
"if" <e: AssertExpression> "if" <e: AssertExpression>
"then" "{" <t1: AssertTree> "}" "then" "{" <t1: AssertTree> "}"
"else" "{" <t2: AssertTree> "}" => "else" "{" <t2: AssertTree> "}" ";"? =>
relabel::Tree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)), relabel::Tree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)),
#[precedence(level="2")] "let" <v: AssertVariable> <q: AssertQualifier?> "=" <e: AssertExpression>
"let" <v: AssertVariable> <q: AssertQualifier?> "=" <e: AssertExpression> => ";"
relabel::Tree::Assignment(v, q, Box::new(e)), => relabel::Tree::Assignment(v, q, Box::new(e)),
#[precedence(level="3")] "return" <e: AssertExpression> ";" =>
"return" <e: AssertExpression> =>
relabel::Tree::Return(Box::new(e)), relabel::Tree::Return(Box::new(e)),
#[precedence(level="4")] "for" <v: AssertVariable> "in" <r: AssertRange> "{" <t: AssertTree> "}" ";"?
"for" <v: AssertVariable> "in" <r: AssertRange> "{" <t: AssertTree> "}" => => relabel::Tree::For(v, r, Box::new(t)),
relabel::Tree::For(v, r, Box::new(t)),
} }
AssertVariable: relabel::Variable = { AssertVariable: relabel::Variable = {
#[precedence(level="0")] #[precedence(level="0")]
"label" => relabel::Variable::Special(relabel::Special::Label), "label" => relabel::Variable::Special(relabel::Special::Label),
#[precedence(level="1")]
"edge" => relabel::Variable::Special(relabel::Special::Edge), "edge" => relabel::Variable::Special(relabel::Special::Edge),
#[precedence(level="2")] #[precedence(level="1")]
<v: Literal> => relabel::Variable::Id(v), <v: Literal> => relabel::Variable::Id(v),
} }
AssertExpression: relabel::Expression = { AssertExpression: relabel::Expression = {
// Unary #[precedence(level="100")]
#[precedence(level="0")] <unp: AssertUnaryPrefix> "(" <e: AssertExpression> ")" =>
<unp: AssertUnaryPrefix> <e: AssertExpression> =>
relabel::Expression::Unary(unp, Box::new(e)), relabel::Expression::Unary(unp, Box::new(e)),
#[precedence(level="2")]
<e: AssertExpression> <uns: AssertUnarySuffix> => #[precedence(level="100")]
<e: AssertExpression> "." <uns: AssertUnarySuffix> =>
relabel::Expression::Unary(uns, Box::new(e)), relabel::Expression::Unary(uns, Box::new(e)),
// binary #[precedence(level="100")] #[assoc(side="left")]
#[precedence(level="3")] #[assoc(side="left")] "(" <e1: AssertExpression> <b: AssertBinary> <e2: AssertExpression> ")" =>
<e1: AssertExpression> <b: AssertBinary> <e2: AssertExpression> =>
relabel::Expression::Binary(b, Box::new(e1), Box::new(e2)), relabel::Expression::Binary(b, Box::new(e1), Box::new(e2)),
#[precedence(level="1")]
#[precedence(level="100")]
<b: AssertBinaryPrefix> <b: AssertBinaryPrefix>
"(" <e1: AssertExpression> "," <e2: AssertExpression> ")" => "(" <e1: AssertExpression> "," <e2: AssertExpression> ")" =>
relabel::Expression::Binary(b, Box::new(e1), Box::new(e2)), relabel::Expression::Binary(b, Box::new(e1), Box::new(e2)),
#[precedence(level="4")] #[precedence(level="50")]
"(" <e: AssertExpression> ")" => e, "(" <e: AssertExpression> ")" => e,
#[precedence(level="0")]
<t: AssertTerm> => t,
}
AssertTerm: relabel::Expression = {
"true" => relabel::Expression::True, "true" => relabel::Expression::True,
"false" => relabel::Expression::False, "false" => relabel::Expression::False,
#[precedence(level="5")]
<v: AssertVariable> => relabel::Expression::Var(v), <v: AssertVariable> => relabel::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
#[precedence(level="6")]
<i: Num> => relabel::Expression::Integer(i), <i: Num> => relabel::Expression::Integer(i),
#[precedence(level="7")]
<lab: Label> => relabel::Expression::Label(Box::new(lab)), <lab: Label> => relabel::Expression::Label(Box::new(lab)),
<set: Set_of_entities> => relabel::Expression::Set(set), <set: Set_of_entities> => relabel::Expression::Set(set),
"'" <el: Literal> "'" => relabel::Expression::Element(translator.encode(el)), "'" <el: Literal> "'" =>
relabel::Expression::Element(translator.encode(el)),
// strings // strings
#[precedence(level="8")]
PATH => relabel::Expression::String(<>.trim_end_matches("\"") PATH => relabel::Expression::String(<>.trim_end_matches("\"")
.trim_start_matches("\"") .trim_start_matches("\"")
.to_string()), .to_string()),
} }
AssertRange: relabel::Range = { AssertRange: relabel::Range = {
"{" <e: AssertExpression> "}" => relabel::Range::IterateOverSet(Box::new(e)), "{" <e: AssertExpression> "}" =>
relabel::Range::IterateOverSet(Box::new(e)),
"{" <e1: AssertExpression> ".." <e2: AssertExpression> "}" => "{" <e1: AssertExpression> ".." <e2: AssertExpression> "}" =>
relabel::Range::IterateInRange(Box::new(e1), Box::new(e2)), relabel::Range::IterateInRange(Box::new(e1), Box::new(e2)),
} }
@ -393,13 +397,13 @@ AssertUnaryPrefix: relabel::Unary = {
AssertUnarySuffix: relabel::Unary = { AssertUnarySuffix: relabel::Unary = {
#[precedence(level="0")] #[precedence(level="0")]
"." "empty" => relabel::Unary::Empty, "empty" => relabel::Unary::Empty,
"." "length" => relabel::Unary::Length, "length" => relabel::Unary::Length,
"." "tostr" => relabel::Unary::ToStr, "tostr" => relabel::Unary::ToStr,
"." "toel" => relabel::Unary::ToEl, "toel" => relabel::Unary::ToEl,
#[precedence(level="1")] #[precedence(level="1")]
"." <q: AssertQualifier> => relabel::Unary::Qualifier(q), <q: AssertQualifier> => relabel::Unary::Qualifier(q),
} }
AssertQualifierRestricted: relabel::QualifierRestricted = { AssertQualifierRestricted: relabel::QualifierRestricted = {
@ -441,7 +445,6 @@ AssertQualifier: relabel::Qualifier = {
<q: AssertQualifierNode> => relabel::Qualifier::Node(q), <q: AssertQualifierNode> => relabel::Qualifier::Node(q),
} }
AssertBinary: relabel::Binary = { AssertBinary: relabel::Binary = {
"&&" => relabel::Binary::And, "&&" => relabel::Binary::And,
"||" => relabel::Binary::Or, "||" => relabel::Binary::Or,
@ -471,13 +474,13 @@ AssertBinaryPrefix: relabel::Binary = {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// GroupingParser // GroupingParser
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
pub Group: Box<grouping::Assert> = { Group: Box<grouping::Assert> = {
">" "node" "{" <f: GroupTree> "}" => ">" "node" "{" <f: GroupTree> "}" =>
Box::new(grouping::Assert{tree: f}), Box::new(grouping::Assert{tree: f}),
}; };
GroupTree: grouping::Tree = { GroupTree: grouping::Tree = {
<t1: GroupTree2> ";" <t2: GroupTree> => <t1: GroupTree2> <t2: GroupTree> =>
grouping::Tree::Concat(Box::new(t1), Box::new(t2)), grouping::Tree::Concat(Box::new(t1), Box::new(t2)),
<t: GroupTree2> => t, <t: GroupTree2> => t,
} }
@ -485,34 +488,30 @@ GroupTree: grouping::Tree = {
GroupTree2: grouping::Tree = { GroupTree2: grouping::Tree = {
#[precedence(level="1")] #[precedence(level="1")]
"if" <e: GroupExpression> "if" <e: GroupExpression>
"then" "{" <t: GroupTree> "}" => "then" "{" <t: GroupTree> "}" ";"? =>
grouping::Tree::If(Box::new(e), Box::new(t)), grouping::Tree::If(Box::new(e), Box::new(t)),
#[precedence(level="0")] #[precedence(level="0")]
"if" <e: GroupExpression> "if" <e: GroupExpression>
"then" "{" <t1: GroupTree> "}" "then" "{" <t1: GroupTree> "}"
"else" "{" <t2: GroupTree> "}" => "else" "{" <t2: GroupTree> "}" ";"? =>
grouping::Tree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)), grouping::Tree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)),
#[precedence(level="2")] "let" <v: GroupVariable> <q: GroupQualifier?> "=" <e: GroupExpression> ";"
"let" <v: GroupVariable> <q: GroupQualifier?> "=" <e: GroupExpression> => => grouping::Tree::Assignment(v, q, Box::new(e)),
grouping::Tree::Assignment(v, q, Box::new(e)),
#[precedence(level="3")] "return" <e: GroupExpression> ";" =>
"return" <e: GroupExpression> =>
grouping::Tree::Return(Box::new(e)), grouping::Tree::Return(Box::new(e)),
#[precedence(level="4")] "for" <v: GroupVariable> "in" <r: GroupRange> "{" <t: GroupTree> "}" ";"? =>
"for" <v: GroupVariable> "in" <r: GroupRange> "{" <t: GroupTree> "}" =>
grouping::Tree::For(v, r, Box::new(t)), grouping::Tree::For(v, r, Box::new(t)),
} }
GroupVariable: grouping::Variable = { GroupVariable: grouping::Variable = {
#[precedence(level="0")] #[precedence(level="0")]
"entities" => grouping::Variable::Special(grouping::Special::Entities), "entities" => grouping::Variable::Special(grouping::Special::Entities),
#[precedence(level="1")]
"node" => grouping::Variable::Special(grouping::Special::Node), "node" => grouping::Variable::Special(grouping::Special::Node),
#[precedence(level="2")] #[precedence(level="1")]
<v: Literal> => grouping::Variable::Id(v), <v: Literal> => grouping::Variable::Id(v),
} }
@ -521,12 +520,12 @@ GroupExpression: grouping::Expression = {
<unp: GroupUnaryPrefix> "(" <e: GroupExpression> ")" => <unp: GroupUnaryPrefix> "(" <e: GroupExpression> ")" =>
grouping::Expression::Unary(unp, Box::new(e)), grouping::Expression::Unary(unp, Box::new(e)),
#[precedence(level="100")] #[precedence(level="50")]
<e: GroupExpression> "." <uns: GroupUnarySuffix> => <e: GroupExpression> "." <uns: GroupUnarySuffix> =>
grouping::Expression::Unary(uns, Box::new(e)), grouping::Expression::Unary(uns, Box::new(e)),
#[precedence(level="100")] #[assoc(side="left")] #[precedence(level="100")] #[assoc(side="left")]
"(" <e1: GroupExpression> <b: GroupBinary> <e2: GroupExpression> ")" => <e1: GroupExpression> <b: GroupBinary> <e2: GroupExpression> =>
grouping::Expression::Binary(b, Box::new(e1), Box::new(e2)), grouping::Expression::Binary(b, Box::new(e1), Box::new(e2)),
#[precedence(level="100")] #[precedence(level="100")]
@ -534,9 +533,6 @@ GroupExpression: grouping::Expression = {
"(" <e1: GroupExpression> "," <e2: GroupExpression> ")" => "(" <e1: GroupExpression> "," <e2: GroupExpression> ")" =>
grouping::Expression::Binary(b, Box::new(e1), Box::new(e2)), grouping::Expression::Binary(b, Box::new(e1), Box::new(e2)),
#[precedence(level="50")]
"(" <e: GroupExpression> ")" => e,
#[precedence(level="0")] #[precedence(level="0")]
<t: GroupTerm> => t, <t: GroupTerm> => t,
} }
@ -553,25 +549,32 @@ GroupTerm: grouping::Expression = {
<lab: Label> => grouping::Expression::Label(Box::new(lab)), <lab: Label> => grouping::Expression::Label(Box::new(lab)),
<set: Set_of_entities> => grouping::Expression::Set(set), <set: Set_of_entities> => grouping::Expression::Set(set),
"'" <el: Literal> "'" => grouping::Expression::Element(translator.encode(el)), "'" <el: Literal> "'" =>
grouping::Expression::Element(translator.encode(el)),
// strings // strings
PATH => grouping::Expression::String(<>.trim_end_matches("\"") PATH => grouping::Expression::String(<>.trim_end_matches("\"")
.trim_start_matches("\"") .trim_start_matches("\"")
.to_string()), .to_string()),
// allow arbitrary parenthesis
"(" <e: GroupExpression> ")" => e,
} }
#[inline]
GroupRange: grouping::Range = { GroupRange: grouping::Range = {
"{" <e: GroupExpression> "}" => grouping::Range::IterateOverSet(Box::new(e)), "{" <e: GroupExpression> "}" =>
grouping::Range::IterateOverSet(Box::new(e)),
"{" <e1: GroupExpression> ".." <e2: GroupExpression> "}" => "{" <e1: GroupExpression> ".." <e2: GroupExpression> "}" =>
grouping::Range::IterateInRange(Box::new(e1), Box::new(e2)), grouping::Range::IterateInRange(Box::new(e1), Box::new(e2)),
} }
#[inline]
GroupUnaryPrefix: grouping::Unary = { GroupUnaryPrefix: grouping::Unary = {
"not" => grouping::Unary::Not, "not" => grouping::Unary::Not,
"rand" => grouping::Unary::Rand, "rand" => grouping::Unary::Rand,
} }
#[inline]
GroupUnarySuffix: grouping::Unary = { GroupUnarySuffix: grouping::Unary = {
#[precedence(level="0")] #[precedence(level="0")]
"empty" => grouping::Unary::Empty, "empty" => grouping::Unary::Empty,
@ -583,6 +586,7 @@ GroupUnarySuffix: grouping::Unary = {
<q: GroupQualifier> => grouping::Unary::Qualifier(q), <q: GroupQualifier> => grouping::Unary::Qualifier(q),
} }
#[inline]
GroupQualifierRestricted: grouping::QualifierRestricted = { GroupQualifierRestricted: grouping::QualifierRestricted = {
"Entities" => grouping::QualifierRestricted::Entities, "Entities" => grouping::QualifierRestricted::Entities,
"Context" => grouping::QualifierRestricted::Context, "Context" => grouping::QualifierRestricted::Context,
@ -593,27 +597,32 @@ GroupQualifierRestricted: grouping::QualifierRestricted = {
"Products" => grouping::QualifierRestricted::Products, "Products" => grouping::QualifierRestricted::Products,
} }
#[inline]
GroupQualifierLabel: grouping::QualifierLabel = { GroupQualifierLabel: grouping::QualifierLabel = {
"AvailableEntities" => grouping::QualifierLabel::AvailableEntities, "AvailableEntities" => grouping::QualifierLabel::AvailableEntities,
"AllReactants" => grouping::QualifierLabel::AllReactants, "AllReactants" => grouping::QualifierLabel::AllReactants,
"AllInhibitors" => grouping::QualifierLabel::AllInhibitors, "AllInhibitors" => grouping::QualifierLabel::AllInhibitors,
} }
#[inline]
GroupQualifierSystem: grouping::QualifierSystem = { GroupQualifierSystem: grouping::QualifierSystem = {
"SystemEntities" => grouping::QualifierSystem::Entities, "SystemEntities" => grouping::QualifierSystem::Entities,
"SystemContext" => grouping::QualifierSystem::Context, "SystemContext" => grouping::QualifierSystem::Context,
} }
#[inline]
GroupQualifierEdge: grouping::QualifierEdge = { GroupQualifierEdge: grouping::QualifierEdge = {
"source" => grouping::QualifierEdge::Source, "source" => grouping::QualifierEdge::Source,
"target" => grouping::QualifierEdge::Target, "target" => grouping::QualifierEdge::Target,
} }
#[inline]
GroupQualifierNode: grouping::QualifierNode = { GroupQualifierNode: grouping::QualifierNode = {
"neighbours" => grouping::QualifierNode::Neighbours, "neighbours" => grouping::QualifierNode::Neighbours,
"system" => grouping::QualifierNode::System, "system" => grouping::QualifierNode::System,
} }
#[inline]
GroupQualifier: grouping::Qualifier = { GroupQualifier: grouping::Qualifier = {
<q: GroupQualifierSystem> => grouping::Qualifier::System(q), <q: GroupQualifierSystem> => grouping::Qualifier::System(q),
<q: GroupQualifierLabel> => grouping::Qualifier::Label(q), <q: GroupQualifierLabel> => grouping::Qualifier::Label(q),
@ -622,7 +631,7 @@ GroupQualifier: grouping::Qualifier = {
<q: GroupQualifierNode> => grouping::Qualifier::Node(q), <q: GroupQualifierNode> => grouping::Qualifier::Node(q),
} }
#[inline]
GroupBinary: grouping::Binary = { GroupBinary: grouping::Binary = {
"&&" => grouping::Binary::And, "&&" => grouping::Binary::And,
"||" => grouping::Binary::Or, "||" => grouping::Binary::Or,
@ -642,6 +651,7 @@ GroupBinary: grouping::Binary = {
"::" => grouping::Binary::Concat, "::" => grouping::Binary::Concat,
} }
#[inline]
GroupBinaryPrefix: grouping::Binary = { GroupBinaryPrefix: grouping::Binary = {
"substr" => grouping::Binary::SubStr, "substr" => grouping::Binary::SubStr,
"min" => grouping::Binary::Min, "min" => grouping::Binary::Min,
@ -649,12 +659,10 @@ GroupBinaryPrefix: grouping::Binary = {
"commonsubstr" => grouping::Binary::CommonSubStr, "commonsubstr" => grouping::Binary::CommonSubStr,
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// BHMLParser // BHMLParser
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// pub BHML: Box<RSBHML> = { // BHML: Box<RSBHML> = {
// <g: Formula_BHML> => Box::new(g) // <g: Formula_BHML> => Box::new(g)
// }; // };
@ -677,7 +685,7 @@ GroupBinaryPrefix: grouping::Binary = {
// system // system
// a system is an environment, a set of entities as initial state, a context and // a system is an environment, a set of entities as initial state, a context and
// a set of reaction rules. // a set of reaction rules.
pub System: system::System = { System: system::System = {
"Environment" ":" <delta: Environment> "Environment" ":" <delta: Environment>
"Initial Entities" ":" <available_entities: Set> "Initial Entities" ":" <available_entities: Set>
"Context" ":" <context_process: Context> "Context" ":" <context_process: Context>

View File

@ -241,7 +241,7 @@ where
); );
// Temporary debug. // Temporary debug.
err.push_str("Expected: "); err.push_str("\nExpected: ");
let mut it = expected.iter().peekable(); let mut it = expected.iter().peekable();
while let Some(s) = it.next() { while let Some(s) = it.next() {
err.push('('); err.push('(');
@ -577,6 +577,7 @@ pub fn grouping(
if let EvaluatedSystem::Graph { graph, translator } = system { if let EvaluatedSystem::Graph { graph, translator } = system {
for node in graph.node_indices() { for node in graph.node_indices() {
let val = group.execute(graph, &node, translator)?; let val = group.execute(graph, &node, translator)?;
println!("node: {node:?} -> val: {val:?}");
buckets.entry(val.clone()).or_insert(vec![]).push(node); buckets.entry(val.clone()).or_insert(vec![]).push(node);
let l = buckets.get(&val).unwrap().first().unwrap(); let l = buckets.get(&val).unwrap().first().unwrap();
leader.insert(node, (*l, val)); leader.insert(node, (*l, val));

View File

@ -16,8 +16,8 @@ Digraph > GraphML
> Print, > Print,
Digraph > node { if (entities == {a, b}) Digraph > node { if (entities == {a, b})
then { return 0 } then { return 0; }
else { return 2 } } else { return 2; } }
> Dot > Dot
| Entities | Entities
| Entities | Entities
@ -25,7 +25,7 @@ Digraph > node { if (entities == {a, b})
| ! "black" | ! "black"
> Print, > Print,
Digraph > node { return entities == {b} } Digraph > node { return entities == {b}; }
> Dot > Dot
| Entities | Entities
| Entities | Entities

270
testing/test.system Normal file
View File

@ -0,0 +1,270 @@
Environment: [x = {a}.y, y =({a}.x + {b}.y) ]
Initial Entities: {a, b}
Context: [({a,b}.{a}.{a,c}.x + {a,b}.{a}.{a}.nill)]
Reactions: ([{a,b}, {c}, {b}])
Digraph > node {
let x = 10;
if false
then { return {a}; }
return {a, b, c};
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
if false
then { return "abc"; }
else { let x = 11; };
return x.tostr;
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
return not(true);
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
return rand(10 - 3);
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
if {a, b}.empty
then {return 0;}
else {return 1;}
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
if entities.length < 2
then {
return 1;
} else {
if "123".length > 3 then {
return 2;
}
}
return 3;
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
let x = 10;
let d = (true.tostr :: ('a'.tostr :: x.tostr));
return d :: "test";
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
let x = entities.length;
let y = ((x + 1 - (2 * 3)) ^ (x / 5 % 6));
return y;
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
for next in {node.neighbours} {
return next.target.system.SystemEntities;
};
return {a, b, c};
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
let x = entities.length;
let y = x + 1 / 2;
let z = x + (1 / 2);
let out = x.tostr :: " - " :: y.tostr :: " - " :: z.tostr;
return out;
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
let sum = 0;
for i in {0..100} {
let sum = sum + i;
};
return sum;
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
let string_b = "b";
let element_b = string_b.toel;
return entities >= ({} :: element_b);
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
let l = [
Entities: {a},
Context: {b},
Reactants: {c},
ReactantsAbsent: {d},
Inhibitors: {e},
InhibitorsPresent: {f},
Products: {g}
];
return l.Entities + l.Context + l.Reactants + l.ReactantsAbsent +
l.Inhibitors + l.InhibitorsPresent + l.Products;
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
let l = [
Entities: {a},
Context: {b},
Reactants: {c},
ReactantsAbsent: {d},
Inhibitors: {e},
InhibitorsPresent: {f},
Products: {g}
];
return l.AvailableEntities - l.AllReactants - l.AllInhibitors;
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
for next in {node.neighbours} {
return next.source.system.SystemContext;
};
return node.system.SystemContext;
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
let one = substr("a", "abc");
let two = substr("abd", "abc");
return min(one, two) + (max(one, two));
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
return (commonsubstr("abc", "abd")).length;
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,
Digraph > node {
let x = true && true;
let x = true || false;
let x = true ^^ false;
let x = {a, b, c} ^^ {b, e} == {a, c, e};
let x = 1 < 2;
let x = {a, b} < {a, b, c};
let x = 1 <= 2;
let x = {a, b} <= {a, b, c};
let x = 2 > 1;
let x = {a} > {};
let x = 2 >= 2;
let x = {} >= {};
let x = (1 == 1) && (false == false) && ('a' == 'a') && ("ab" == "ab");
let x = (1 != 2) && (false != true) && ('a' != 'b') && ("ab" != "b");
let x = 1 + 2 == 3;
let x = {a, b} + {c} == {a, b, c};
let x = 1 - 2 == (0-1);
let x = {a, b} - {b} == {a};
let x = 1 * 2 == 2;
let x = {a, b, c} * {b, c, d} == {b, c};
let x = 2 ^ 4 == 16;
let x = 10 / 3 == 3;
let x = 10 % 3 == 1;
let x = "ab" :: "c" == "abc";
let x = {a, b} :: 'c' == {a, b, c};
return x;
}
> Dot
| Entities
| Context
| ! "white"
| ! "black"
> Print,