Files
ReactionSystems/src/rsprocess/grammar.lalrpop

766 lines
25 KiB
Plaintext
Raw Normal View History

2025-05-21 00:03:36 +02:00
use std::rc::Rc;
2025-05-14 11:42:19 +02:00
use std::str::FromStr;
use lalrpop_util::ParseError;
use crate::rsprocess::structure::{RSset,
RSprocess,
RSenvironment,
RSsystem,
2025-08-16 21:52:36 +02:00
// RSlabel,
RSreaction};
2025-07-29 22:56:32 +02:00
use crate::rsprocess::structure::assert;
2025-06-16 14:46:04 +02:00
use crate::rsprocess::translator::{Translator, IdType};
use crate::rsprocess::presets::Instructions;
use crate::rsprocess::presets;
use crate::rsprocess::graph;
2025-05-14 11:42:19 +02:00
2025-06-16 14:46:04 +02:00
grammar(translator: &mut Translator);
2025-05-14 11:42:19 +02:00
// -----------------------------------------------------------------------------
// Helpers
// -----------------------------------------------------------------------------
2025-07-03 16:28:28 +02:00
// order
match {
".", ",", ";",
2025-07-03 23:44:10 +02:00
"nill",
"{", "}",
"[", "]",
"(", ")",
"<", ">",
"r:", "i:", "p:",
"-", "^",
"true", "false",
"Environment", "Initial Entities", "Context", "Reactions",
"Weights", "Sets",
"Print", "Save",
"Dot", "GraphML", "Serialize",
"Stats", "Target", "Run", "Loop", "Frequency", "LimitFrequency",
2025-07-16 00:05:14 +02:00
"FastFrequency", "Digraph", "Bisimilarity",
"Deserialize",
"?",
"Hide",
"Entities", "MaskEntities", "UncommonEntities", "UncommonMaskEntities",
"MaskContext", "UncommonContext", "UncommonMaskContext",
"Products", "MaskProducts", "UncommonProducts", "UncommonMaskProducts",
"Union", "MaskUnion", "UncommonUnion", "UncommonMaskUnion",
"Difference", "MaskDifference",
"UncommonDifference", "UncommonMaskDifference",
"EntitiesDeleted", "MaskEntitiesDeleted",
"UncommonEntitiesDeleted", "UncommonMaskEntitiesDeleted",
"EntitiesAdded", "MaskEntitiesAdded",
"UncommonEntitiesAdded", "UncommonMaskEntitiesAdded",
"label", "edge", "if", "then", "else", "let", "=", "return", "for", "in",
"not", "rand", ".empty", ".length", ".tostr", ".source", ".target",
"&&", "||", "^^", "<=", ">=", "==", "!=", "+", "*", "/", "%",
"::", "substr", "min", "max", "commonsubstr",
2025-08-14 21:20:10 +02:00
"SystemEntities", "SystemContext",
"AvailableEntities", "AllReactants", "AllInhibitors",
2025-08-15 00:32:58 +02:00
"relabel",
2025-07-03 23:44:10 +02:00
} else {
2025-07-03 16:28:28 +02:00
r"[0-9]+" => NUMBER
} else {
r"([[:alpha:]])([[:word:]])*" => WORD
// r"(\p{L}|\p{Emoji})(\p{L}|\p{Emoji}|\p{Dash}|\p{N})*" => WORD,
} else {
2025-07-13 18:14:35 +02:00
r#""[^"]+""# => PATH, // " <- ignore comment, its for the linter in emacs
2025-07-03 16:28:28 +02:00
} else {
_
}
2025-05-14 12:14:13 +02:00
// matches words (letter followed by numbers, letters or _)
2025-07-03 16:28:28 +02:00
Literal: String = {
WORD => <>.to_string()
};
2025-05-14 11:42:19 +02:00
2025-05-14 12:14:13 +02:00
// all numbers are i64
2025-05-14 11:42:19 +02:00
Num: i64 = {
2025-07-03 16:28:28 +02:00
NUMBER =>? i64::from_str(<>)
.map_err(|_| ParseError::User { error: "Number is too big" })
2025-05-14 11:42:19 +02:00
};
Path: String = {
PATH => <>.trim_end_matches("\"").trim_start_matches("\"").to_string()
};
2025-05-14 12:14:13 +02:00
// macro for matching sequence of patterns with C as separator
2025-07-02 17:27:36 +02:00
Separated<T, C>: Vec<T> = {
2025-05-14 11:42:19 +02:00
<mut v:(<T> C)+> <e:T?> => match e {
None => v,
Some(e) => {
v.push(e);
v
}
}
};
Separated_Or<T, C>: Vec<T> = {
<v: T> => vec![v],
<v: Separated<T, C>> => v
}
// -----------------------------------------------------------------------------
// SetParser
// -----------------------------------------------------------------------------
2025-06-16 14:46:04 +02:00
pub Set: RSset = {
2025-05-14 11:42:19 +02:00
<s: Set_of_entities> => s
};
2025-06-16 14:46:04 +02:00
Set_of_entities: RSset = {
2025-05-19 00:10:23 +02:00
"{" "}" => RSset::from(vec![]),
"{" <t: Separated_Or<Literal, ",">> "}" =>
2025-07-13 18:14:35 +02:00
RSset::from(t.into_iter().map(|t| translator.encode(t))
.collect::<Vec<_>>())
2025-05-19 00:10:23 +02:00
};
2025-06-12 16:23:39 +02:00
// -----------------------------------------------------------------------------
// ReactionParser
// -----------------------------------------------------------------------------
pub Reactions: Vec<RSreaction> = {
"(" ")" => vec![],
"(" <s: Separated_Or<Reaction, ";">> ")" => s
}
Reaction: RSreaction = {
"[" <r: Set> "," <i: Set> "," <p: Set> "]" => RSreaction::from(r, i, p),
2025-07-01 19:22:50 +02:00
"[" "r:" <r: Set> "," "i:" <i: Set> "," "p:" <p: Set> "]" =>
RSreaction::from(r, i, p),
}
2025-07-29 22:56:32 +02:00
// -----------------------------------------------------------------------------
// ContextParser
// -----------------------------------------------------------------------------
pub Context: RSprocess = {
"[" "]" => RSprocess::NondeterministicChoice{ children: vec![] },
"[" <t: Separated_Or<Boxed_CTX_process, ",">> "]" =>
RSprocess::NondeterministicChoice{ children: t }
2025-05-14 11:42:19 +02:00
};
2025-06-16 14:46:04 +02:00
Boxed_CTX_process: Rc<RSprocess> = {
2025-05-21 00:03:36 +02:00
<t: CTX_process> => Rc::new(t)
}
2025-06-16 14:46:04 +02:00
CTX_process: RSprocess = {
2025-07-03 23:44:10 +02:00
"nill" => RSprocess::Nill,
2025-05-19 00:10:23 +02:00
<c: Set_of_entities> "." <k: CTX_process> =>
2025-05-21 00:03:36 +02:00
RSprocess::EntitySet{ entities: c, next_process: Rc::new(k) },
2025-05-14 11:42:19 +02:00
"(" <k: CTX_process> ")" => k,
2025-07-02 17:27:36 +02:00
"(" <k: Separated<CTX_process, "+">> ")" =>
2025-07-01 19:22:50 +02:00
RSprocess::Summation{
children: k.into_iter().map(Rc::new).collect::<Vec<_>>()
},
2025-05-19 00:10:23 +02:00
"<" <n: Num> <k1: CTX_process> ">" "." <k: CTX_process> =>
RSprocess::WaitEntity{ repeat: n,
2025-05-21 00:03:36 +02:00
repeated_process: Rc::new(k1),
2025-07-01 19:22:50 +02:00
next_process: Rc::new(k) },
2025-05-19 00:10:23 +02:00
<identifier: Literal> =>
2025-07-01 19:22:50 +02:00
RSprocess::RecursiveIdentifier{
identifier: translator.encode(identifier)
}
2025-05-14 11:42:19 +02:00
};
2025-07-29 22:56:32 +02:00
// -----------------------------------------------------------------------------
// EnvironmentParser
// -----------------------------------------------------------------------------
2025-06-16 14:46:04 +02:00
pub Environment: Box<RSenvironment> = {
2025-05-14 11:42:19 +02:00
"[" "]" => Box::new(RSenvironment::new()),
"[" <t: Separated_Or<Env_term, ",">> "]" => Box::new(RSenvironment::from(t))
2025-05-14 11:42:19 +02:00
};
2025-06-16 14:46:04 +02:00
Env_term: (IdType, RSprocess) = {
<identifier: Literal> "=" <k: CTX_process> =>
2025-06-18 11:28:04 +02:00
(translator.encode(identifier), k)
2025-05-14 11:42:19 +02:00
};
2025-07-29 22:56:32 +02:00
// -----------------------------------------------------------------------------
// AssertParser
// -----------------------------------------------------------------------------
2025-08-16 21:52:36 +02:00
// pub Assert: Box<assert::RSassert> = {
// "label" "{" <f: AssertTree> "}" =>
// Box::new(assert::RSassert{tree: f}),
// };
2025-07-29 22:56:32 +02:00
2025-08-16 21:52:36 +02:00
// 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: AssertVariable> <q: AssertQualifierLet?> "=" <e: AssertExpression> =>
// assert::Tree::Assignment(v, q, 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)),
// }
// AssertQualifierLet: assert::Qualifier {
// "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,
// }
// AssertAssignmentVar: assert::AssignmentVariable = {
// <v: AssertVariable> => assert::AssignmentVariable::Var(v),
// <v: AssertVariable> "." <q: AssertQualifierRestricted> =>
// assert::AssignmentVariable::QualifiedVar(v, q),
// }
// AssertVariable: assert::Variable = {
// "label" => assert::Variable::Label,
// "edge" => assert::Variable::Edge,
// <v: Literal> => assert::Variable::Id(v),
// }
// 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,
// "true" => assert::Expression::True,
// "false" => assert::Expression::False,
// <v: AssertAssignmentVar> => assert::Expression::Var(v),
// // 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()),
// }
// 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,
// ".toel" => assert::Unary::ToEl,
// ".source" => assert::Unary::Source,
// ".target" => assert::Unary::Target,
// ".neighbours" => assert::Unary::Neighbours,
// ".system" => assert::Unary::System,
// "." <q: AssertQualifierLabel> => assert::Unary::QualifierLabel(q),
// "." <q: AssertQualifierSystem> => assert::Unary::QualifierSystem(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,
// }
// AssertQualifierSystem: assert::QualifierSystem = {
// "SystemEntities" => assert::QualifierSystem::Entities,
// "SystemContext" => assert::QualifierSystem::Context,
// }
// AssertQualifierLabel: assert::QualifierLabel = {
// "AvailableEntities" => assert::QualifierLabel::AvailableEntities,
// "AllReactants" => assert::QualifierLabel::AllReactants,
// "AllInhibitors" => assert::QualifierLabel::AllInhibitors,
// <q: AssertQualifierRestricted> => assert::QualifierLabel::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)),
// }
2025-07-29 19:35:25 +02:00
2025-05-14 11:42:19 +02:00
// -----------------------------------------------------------------------------
// BHMLParser
// -----------------------------------------------------------------------------
2025-07-29 19:35:25 +02:00
// pub BHML: Box<RSBHML> = {
// <g: Formula_BHML> => Box::new(g)
// };
// Formula_BHML: RSBHML = {
// "true" => RSBHML::True,
// "false" => RSBHML::False,
// "(" <g: Separated<Formula_BHML, "\\/">> ")" => RSBHML::Or(g),
// "(" <g: Separated<Formula_BHML, "/\\">> ")" => RSBHML::And(g),
// "<" <f: Formula_Assert> ">" <g: Formula_BHML> =>
// RSBHML::Diamond(Box::new(f), Box::new(g)),
// "[" <f: Formula_Assert> "]" <g: Formula_BHML> =>
// RSBHML::Box(Box::new(f), Box::new(g)),
// };
// ----------------------------------------------------------------------------
// File Parsing
// ----------------------------------------------------------------------------
// system
// a system is an environment, a set of entities as initial state, a context and
// a set of reaction rules.
pub System: RSsystem = {
"Environment" ":" <delta: Environment>
"Initial Entities" ":" <available_entities: Set>
"Context" ":" <context_process: Context>
"Reactions" ":" <reaction_rules: Reactions>
2025-07-01 19:22:50 +02:00
=> RSsystem::from(delta.into(),
available_entities,
context_process,
Rc::new(reaction_rules))
}
2025-07-02 17:27:36 +02:00
// experiment
// an experiment is composed by a sequence of weights and a sequence of sets of
// entities of equal length.
pub Experiment: (Vec<u32>, Vec<RSset>) = {
"Weights" ":" <w: Separated_Or<Num, ",">>
"Sets" ":" <s: Separated_Or<Set_of_entities, ",">>
=> (w.into_iter().map(|x| x as u32).collect::<Vec<_>>(), s),
2025-07-02 17:27:36 +02:00
}
2025-07-13 17:28:13 +02:00
// ~~~~~~~~~~~~~~~~~~~
// Instruction Parsing
2025-07-13 17:28:13 +02:00
// ~~~~~~~~~~~~~~~~~~~
2025-07-13 17:28:13 +02:00
/// Decides whetherer to print to stdout or to save to file
Helper_SO: presets::SaveOptions = {
"Print" =>
presets::SaveOptions {print: true, save: None},
"Save" "(" <p: Path> ")" =>
presets::SaveOptions {print: false, save: Some(vec![p])}
}
2025-07-13 17:28:13 +02:00
/// we could need to save to multiple files
SaveOptions: presets::SaveOptions = {
<p: Separated_Or<Helper_SO, ";">> => {
2025-07-12 02:42:28 +02:00
p.into_iter()
.reduce(|mut acc, mut e| {acc.combine(&mut e); acc})
.unwrap_or_default()
}
}
2025-07-13 17:28:13 +02:00
/// Match for strings between nodes formatters
LiteralSeparatorNode: graph::NodeDisplayBase = {
PATH =>
graph::NodeDisplayBase::String {
string: <>.trim_end_matches("\"")
.trim_start_matches("\"")
.to_string()
}
};
2025-07-13 17:28:13 +02:00
/// Match for strings between edge formatters
LiteralSeparatorEdge: graph::EdgeDisplayBase = {
PATH =>
graph::EdgeDisplayBase::String {
2025-07-29 22:56:32 +02:00
string: <>.trim_end_matches("\"")
.trim_start_matches("\"")
.to_string()
}
};
NodeDisplayBase: graph::NodeDisplayBase = {
"Hide" =>
graph::NodeDisplayBase::Hide,
"Entities" =>
graph::NodeDisplayBase::Entities,
"MaskEntities" <mask: Set> =>
graph::NodeDisplayBase::MaskEntities{mask},
"ExcludeEntities" <mask: Set> =>
graph::NodeDisplayBase::ExcludeEntities{mask},
"Context" =>
graph::NodeDisplayBase::Context,
"UncommonEntities" =>
graph::NodeDisplayBase::UncommonEntities,
"MaskUncommonentities" <mask: Set> =>
graph::NodeDisplayBase::MaskUncommonEntities{mask},
}
2025-07-13 17:28:13 +02:00
/// Node display formatters separated by arbitrary strings in quotes
SeparatorNode: graph::NodeDisplay = {
<v: NodeDisplayBase> => graph::NodeDisplay {base: vec![v]},
<v:(<NodeDisplayBase> <LiteralSeparatorNode>)+> <e: NodeDisplayBase?> =>
match e {
None => graph::NodeDisplay {
base:
v.iter().fold(vec![],
|mut acc, (a, b)| {
acc.push(a.clone());
acc.push(b.clone());
acc.clone()
})
},
Some(e) => {
2025-07-13 18:14:35 +02:00
let mut v = v.iter().fold(vec![],
|mut acc, (a, b)| {
acc.push(a.clone());
acc.push(b.clone());
acc.clone()
});
v.push(e);
graph::NodeDisplay { base: v }
}
}
}
EdgeDisplay: graph::EdgeDisplayBase = {
2025-07-13 18:14:35 +02:00
"Hide" =>
graph::EdgeDisplayBase::Hide,
2025-07-13 18:14:35 +02:00
"Products" =>
graph::EdgeDisplayBase::Products
{ mask: None, filter_common: false },
"MaskProducts" <mask: Set> =>
graph::EdgeDisplayBase::Entities
{ mask: Some(mask), filter_common: false },
"UncommonProducts" =>
graph::EdgeDisplayBase::Products
{ mask: None, filter_common: true },
"UncommonMaskProducts" <mask: Set> =>
graph::EdgeDisplayBase::Entities
{ mask: Some(mask), filter_common: true },
2025-07-13 18:14:35 +02:00
"Entities" =>
graph::EdgeDisplayBase::Entities
{ mask: None, filter_common: false },
2025-07-13 18:14:35 +02:00
"MaskEntities" <mask: Set> =>
graph::EdgeDisplayBase::Entities
{ mask: Some(mask), filter_common: false },
"UncommonEntities" =>
graph::EdgeDisplayBase::Entities
{ mask: None, filter_common: true },
"UncommonMaskEntities" <mask: Set> =>
graph::EdgeDisplayBase::Entities
{ mask: Some(mask), filter_common: true },
2025-07-13 18:14:35 +02:00
"Context" =>
graph::EdgeDisplayBase::Context
{ mask: None, filter_common: false },
2025-07-13 18:14:35 +02:00
"MaskContext" <mask: Set> =>
graph::EdgeDisplayBase::Context
{ mask: Some(mask), filter_common: false },
"UncommonContext" =>
graph::EdgeDisplayBase::Context
{ mask: None, filter_common: true },
"UncommonMaskContext" <mask: Set> =>
graph::EdgeDisplayBase::Context
{ mask: Some(mask), filter_common: true },
2025-07-13 18:14:35 +02:00
"Union" =>
graph::EdgeDisplayBase::Union
{ mask: None, filter_common: false },
2025-07-13 18:14:35 +02:00
"MaskUnion" <mask: Set> =>
graph::EdgeDisplayBase::Union
{ mask: Some(mask), filter_common: false },
"UncommonUnion" =>
graph::EdgeDisplayBase::Union
{ mask: None, filter_common: true },
"UncommonMaskUnion" <mask: Set> =>
graph::EdgeDisplayBase::Union
{ mask: Some(mask), filter_common: true },
2025-07-13 18:14:35 +02:00
"Difference" =>
graph::EdgeDisplayBase::Difference
{ mask: None, filter_common: false },
2025-07-13 18:14:35 +02:00
"MaskDifference" <mask: Set> =>
graph::EdgeDisplayBase::Difference
{ mask: Some(mask), filter_common: false },
"UncommonDifference" =>
graph::EdgeDisplayBase::Difference
{ mask: None, filter_common: true },
"UncommonMaskDifference" <mask: Set> =>
graph::EdgeDisplayBase::Difference
{ mask: Some(mask), filter_common: true },
2025-07-13 18:14:35 +02:00
"EntitiesDeleted" =>
graph::EdgeDisplayBase::EntitiesDeleted
{ mask: None, filter_common: false },
2025-07-13 18:14:35 +02:00
"MaskEntitiesDeleted" <mask: Set> =>
graph::EdgeDisplayBase::EntitiesDeleted
{ mask: Some(mask), filter_common: false },
"UncommonEntitiesDeleted" =>
graph::EdgeDisplayBase::EntitiesDeleted
{ mask: None, filter_common: true },
"UncommonMaskEntitiesDeleted" <mask: Set> =>
graph::EdgeDisplayBase::EntitiesDeleted
{ mask: Some(mask), filter_common: true },
2025-07-13 18:14:35 +02:00
"EntitiesAdded" =>
graph::EdgeDisplayBase::EntitiesAdded
{ mask: None, filter_common: false },
2025-07-13 18:14:35 +02:00
"MaskEntitiesAdded" <mask: Set> =>
graph::EdgeDisplayBase::EntitiesAdded
{ mask: Some(mask), filter_common: false },
"UncommonEntitiesAdded" =>
graph::EdgeDisplayBase::EntitiesAdded
{ mask: None, filter_common: true },
"UncommonMaskEntitiesAdded" <mask: Set> =>
graph::EdgeDisplayBase::EntitiesAdded
{ mask: Some(mask), filter_common: true },
}
2025-07-13 17:28:13 +02:00
/// Edge display formatters separated by arbitrary strings in quotes
SeparatorEdge: graph::EdgeDisplay = {
<v: EdgeDisplay> => graph::EdgeDisplay{ base: vec![v] },
<v:(<EdgeDisplay> <LiteralSeparatorEdge>)+> <e: EdgeDisplay?> =>
match e {
None => graph::EdgeDisplay{ base: v.iter().fold(vec![],
|mut acc, (a, b)| {
acc.push(a.clone());
acc.push(b.clone());
acc.clone()
}) },
Some(e) => {
2025-07-13 18:14:35 +02:00
let mut v = v.iter().fold(vec![],
|mut acc, (a, b)| {
acc.push(a.clone());
acc.push(b.clone());
acc.clone()
});
v.push(e);
graph::EdgeDisplay{ base: v }
}
}
}
2025-07-13 18:14:35 +02:00
Operation: graph::OperationType = {
"==" => graph::OperationType::Equals,
"=" => graph::OperationType::Equals,
"<" => graph::OperationType::Subset,
"⊂" => graph::OperationType::Subset,
"<=" => graph::OperationType::SubsetEqual,
"⊆" => graph::OperationType::SubsetEqual,
">" => graph::OperationType::Superset,
"⊃" => graph::OperationType::Superset,
">=" => graph::OperationType::SupersetEqual,
"⊇" => graph::OperationType::SupersetEqual
}
NodeColorConditional: (graph::NodeColorConditional, String) = {
"Entities" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::NodeColorConditional::EntitiesConditional(op, set),
color.to_string()),
"Context.Nill" "?" <color: PATH> =>
(graph::NodeColorConditional::ContextConditional(
graph::ContextColorConditional::Nill),
color.to_string()),
"Context.RecursiveIdentifier" "(" <x: Literal> ")" "?" <color: PATH> =>
(graph::NodeColorConditional::ContextConditional(
graph::ContextColorConditional::RecursiveIdentifier(
translator.encode(x)
)),
color.to_string()),
"Context.EntitySet" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::NodeColorConditional::ContextConditional(
graph::ContextColorConditional::EntitySet(op, set)),
color.to_string()),
"Context.NonDeterministicChoice" "?" <color: PATH> =>
(graph::NodeColorConditional::ContextConditional(
graph::ContextColorConditional::NonDeterministicChoice),
color.to_string()),
"Context.Summation" "?" <color: PATH> =>
(graph::NodeColorConditional::ContextConditional(
graph::ContextColorConditional::Summation),
color.to_string()),
"Context.WaitEntity" "?" <color: PATH> =>
(graph::NodeColorConditional::ContextConditional(
graph::ContextColorConditional::WaitEntity),
color.to_string()),
}
/// Node color formatter
ColorNode: graph::NodeColor = {
<conditionals: Separated_Or<NodeColorConditional, "||">>
"!" <base_color: PATH> =>
2025-07-13 19:08:39 +02:00
graph::NodeColor { conditionals,
2025-07-13 18:14:35 +02:00
base_color: base_color.to_string() },
"!" <base_color: PATH> =>
graph::NodeColor { conditionals: vec![],
base_color: base_color.to_string() },
}
2025-07-13 19:08:39 +02:00
EdgeColorConditional: (graph::EdgeColorConditional, String) = {
"Entities" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::Entities(op, set),
color.to_string()),
"Context" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::Context(op, set),
color.to_string()),
"T" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::T(op, set),
color.to_string()),
"Reactants" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::Reactants(op, set),
color.to_string()),
"AbsentReactants" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::ReactantsAbsent(op, set),
color.to_string()),
"Inhibitors" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::Inhibitors(op, set),
color.to_string()),
"PresentInhibitors" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::InhibitorsPresent(op, set),
color.to_string()),
"Products" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::Products(op, set),
color.to_string()),
}
ColorEdge: graph::EdgeColor = {
<conditionals: Separated_Or<EdgeColorConditional, "||">>
"!" <base_color: PATH> =>
graph::EdgeColor { conditionals,
base_color: base_color.to_string() },
"!" <base_color: PATH> =>
graph::EdgeColor { conditionals: vec![],
base_color: base_color.to_string() },
}
2025-07-13 18:14:35 +02:00
GraphSaveOptions: presets::GraphSaveOptions = {
2025-07-13 19:32:11 +02:00
"Dot" "|"? <s_node: SeparatorNode> "|" <s_edge: SeparatorEdge> "|"
2025-07-13 19:08:39 +02:00
<c_node: ColorNode> "|" <c_edge: ColorEdge> ">"
<so: SaveOptions> =>
presets::GraphSaveOptions::Dot { node_display: s_node,
edge_display: s_edge,
2025-07-13 18:14:35 +02:00
node_color: c_node,
2025-07-13 19:08:39 +02:00
edge_color: c_edge,
so },
2025-07-13 19:32:11 +02:00
"GraphML" "|"? <s_node: SeparatorNode> "|" <s_edge: SeparatorEdge> ">"
<so: SaveOptions> =>
presets::GraphSaveOptions::GraphML { node_display: s_node,
edge_display: s_edge,
so },
"Serialize" "(" <path: Path> ")" =>
presets::GraphSaveOptions::Serialize { path },
}
Instruction: presets::Instruction = {
"Stats" ">" <so: SaveOptions> =>
presets::Instruction::Stats { so },
"Target" ">" <so: SaveOptions> =>
presets::Instruction::Target { so },
"Run" ">" <so: SaveOptions> =>
presets::Instruction::Run { so },
"Loop" "(" <symbol: Literal> ")" ">" <so: SaveOptions> =>
presets::Instruction::Loop { symbol, so },
2025-07-12 02:42:28 +02:00
"Frequency" ">" <so: SaveOptions> =>
presets::Instruction::Frequency { so },
"LimitFrequency" "(" <p: Path> ")" ">" <so: SaveOptions> =>
presets::Instruction::LimitFrequency { experiment: p, so },
"FastFrequency" "(" <p: Path> ")" ">" <so: SaveOptions> =>
presets::Instruction::FastFrequency { experiment: p, so },
"Digraph" ">" <gso: Separated_Or<GraphSaveOptions, "|">> =>
presets::Instruction::Digraph { gso },
2025-08-16 21:52:36 +02:00
// <edge_relabeler: Assert>
"Bisimilarity" "(" <p: Path> ")" "relabel"
2025-08-15 00:32:58 +02:00
">" <so: SaveOptions> =>
2025-08-16 21:52:36 +02:00
presets::Instruction::Bisimilarity {
system_b: p,
edge_relabeler: Box::new(assert::RSassert {
tree: assert::Tree::Return(Box::new(assert::Expression::True))
}),
so
},
}
pub Run: presets::Instructions = {
<sys: System> <instr: Separated_Or<Instruction, ",">> =>
Instructions { system: presets::System::RSsystem { sys },
instructions: instr },
2025-07-13 18:14:35 +02:00
2025-07-16 00:05:14 +02:00
<sys: System> =>
Instructions { system: presets::System::RSsystem { sys },
instructions: vec![] },
2025-07-13 18:14:35 +02:00
"Deserialize" "(" <path: Path> ")"
<instr: Separated_Or<Instruction, ",">> =>
Instructions { system: presets::System::Deserialize { path },
instructions: instr },
}