Positive version of assert and group functions w/ parsers
Grouping function in execution::data
This commit is contained in:
@ -1,5 +1,10 @@
|
|||||||
pub mod dsl;
|
pub mod dsl;
|
||||||
pub mod rsassert;
|
mod fmt;
|
||||||
|
|
||||||
|
pub mod positivedsl;
|
||||||
|
mod positivefmt;
|
||||||
|
|
||||||
|
mod rsassert;
|
||||||
|
|
||||||
pub mod relabel {
|
pub mod relabel {
|
||||||
pub use super::rsassert::useful_types_edge_relabeler::*;
|
pub use super::rsassert::useful_types_edge_relabeler::*;
|
||||||
@ -9,7 +14,13 @@ pub mod grouping {
|
|||||||
pub use super::rsassert::useful_types_node_relabeler::*;
|
pub use super::rsassert::useful_types_node_relabeler::*;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod fmt;
|
pub mod positive_relabel {
|
||||||
|
pub use super::rsassert::useful_types_positive_edge_relabeler::*;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod positive_grouping {
|
||||||
|
pub use super::rsassert::useful_types_positive_node_relabeler::*;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|||||||
1222
assert/src/positivedsl.rs
Normal file
1222
assert/src/positivedsl.rs
Normal file
File diff suppressed because it is too large
Load Diff
615
assert/src/positivefmt.rs
Normal file
615
assert/src/positivefmt.rs
Normal file
@ -0,0 +1,615 @@
|
|||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Display Implementation for all types
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use rsprocess::translator::{Formatter, PrintableWithTranslator, Translator};
|
||||||
|
|
||||||
|
use super::positivedsl::*;
|
||||||
|
|
||||||
|
impl<S> fmt::Debug for PositiveAssert<S>
|
||||||
|
where
|
||||||
|
S: fmt::Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "label {{\n{:?}\n}}", self.tree)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> fmt::Debug for PositiveTree<S>
|
||||||
|
where
|
||||||
|
S: fmt::Debug,
|
||||||
|
{
|
||||||
|
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, q, exp) =>
|
||||||
|
if let Some(q) = q {
|
||||||
|
write!(f, "{v:?}.{q:?} = {exp:?}")
|
||||||
|
} else {
|
||||||
|
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<S> fmt::Debug for PositiveVariable<S>
|
||||||
|
where
|
||||||
|
S: fmt::Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Special(s) => {
|
||||||
|
write!(f, "{s:?}")
|
||||||
|
},
|
||||||
|
| Self::Id(s) => {
|
||||||
|
write!(f, "{s:?}")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> fmt::Debug for PositiveExpression<S>
|
||||||
|
where
|
||||||
|
S: fmt::Debug,
|
||||||
|
{
|
||||||
|
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, "{{debug: {rslabel:?}}}")
|
||||||
|
},
|
||||||
|
| Self::Set(set) => {
|
||||||
|
write!(f, "{{debug: {set:?}}}")
|
||||||
|
},
|
||||||
|
| Self::PositiveElement(el) => {
|
||||||
|
write!(f, "'{{debug: {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<S> fmt::Debug for PositiveRange<S>
|
||||||
|
where
|
||||||
|
S: fmt::Debug,
|
||||||
|
{
|
||||||
|
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::Debug for PositiveUnary {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Not => write!(f, "not"),
|
||||||
|
| Self::Rand => write!(f, "rand"),
|
||||||
|
| Self::Empty => write!(f, ".empty"),
|
||||||
|
| Self::Length => write!(f, ".length"),
|
||||||
|
| Self::ToStr => write!(f, ".tostr"),
|
||||||
|
| Self::ToEl => write!(f, ".toel"),
|
||||||
|
| Self::Qualifier(q) => write!(f, ".{q:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for QualifierRestricted {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Entities => write!(f, "Entities"),
|
||||||
|
| Self::Context => write!(f, "Context"),
|
||||||
|
| Self::Reactants => write!(f, "Reactants"),
|
||||||
|
| Self::ReactantsAbsent => write!(f, "ReactantsAbsent"),
|
||||||
|
| Self::Inhibitors => write!(f, "Inhibitors"),
|
||||||
|
| Self::InhibitorsPresent => write!(f, "InhibitorsPresent"),
|
||||||
|
| Self::Products => write!(f, "Products"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for QualifierLabel {
|
||||||
|
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"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for QualifierSystem {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Context => write!(f, "context"),
|
||||||
|
| Self::Entities => write!(f, "entities"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for QualifierEdge {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Source => write!(f, "source"),
|
||||||
|
| Self::Target => write!(f, "target"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for QualifierNode {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Neighbours => write!(f, "neighbours"),
|
||||||
|
| Self::System => write!(f, "system"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for PositiveQualifier {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Label(q) => write!(f, "{q:?}"),
|
||||||
|
| Self::Restricted(q) => write!(f, "{q:?}"),
|
||||||
|
| Self::System(q) => write!(f, "{q:?}"),
|
||||||
|
| Self::Edge(q) => write!(f, "{q:?}"),
|
||||||
|
| Self::Node(q) => write!(f, "{q:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for PositiveBinary {
|
||||||
|
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"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for PositiveAssertReturnValue {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Boolean(b) => write!(f, "{b:?}"),
|
||||||
|
| Self::Integer(i) => write!(f, "{i:?}"),
|
||||||
|
| Self::String(s) => write!(f, r#""{s:?}""#),
|
||||||
|
| Self::Label(l) => write!(f, "{{debug: {l:?}}}"),
|
||||||
|
| Self::Set(set) => write!(f, "{{debug: {set:?}}}"),
|
||||||
|
| Self::PositiveElement(el) => write!(f, "{{debug: {el:?}}}"),
|
||||||
|
| Self::Edge(edge) => write!(f, "{{debug: {edge:?}}}"),
|
||||||
|
| Self::Node(node) => write!(f, "{{debug: {node:?}}}"),
|
||||||
|
| Self::Neighbours(node) => {
|
||||||
|
write!(f, "{{debug: {node:?}}}.neighbours")
|
||||||
|
},
|
||||||
|
| Self::System(sys) => write!(f, "{{debug: {sys:?}}}"),
|
||||||
|
| Self::Context(ctx) => write!(f, "{{debug: {ctx:?}}}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for PositiveAssertionTypes {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Boolean => write!(f, "boolean"),
|
||||||
|
| Self::Integer => write!(f, "integer"),
|
||||||
|
| Self::String => write!(f, "string"),
|
||||||
|
| Self::Label => write!(f, "label"),
|
||||||
|
| Self::Set => write!(f, "set"),
|
||||||
|
| Self::PositiveElement => write!(f, "element"),
|
||||||
|
| Self::System => write!(f, "system"),
|
||||||
|
| Self::Context => write!(f, "context"),
|
||||||
|
| Self::NoType => write!(f, "no type"),
|
||||||
|
| Self::RangeInteger => write!(f, "range of integers"),
|
||||||
|
| Self::RangeSet => write!(f, "range of set"),
|
||||||
|
| Self::RangeNeighbours => write!(f, "range of edges"),
|
||||||
|
| Self::Edge => write!(f, "edge"),
|
||||||
|
| Self::Node => write!(f, "node"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
impl<S> PrintableWithTranslator for PositiveAssert<S>
|
||||||
|
where
|
||||||
|
S: PrintableWithTranslator,
|
||||||
|
{
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
translator: &Translator,
|
||||||
|
) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"label {{\n{}\n}}",
|
||||||
|
Formatter::from(translator, &self.tree)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> PrintableWithTranslator for PositiveTree<S>
|
||||||
|
where
|
||||||
|
S: PrintableWithTranslator,
|
||||||
|
{
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
translator: &Translator,
|
||||||
|
) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Concat(t1, t2) => write!(
|
||||||
|
f,
|
||||||
|
"{};\n{}",
|
||||||
|
Formatter::from(translator, &**t1),
|
||||||
|
Formatter::from(translator, &**t2)
|
||||||
|
),
|
||||||
|
| Self::If(exp, t) => write!(
|
||||||
|
f,
|
||||||
|
"if {} {{\n{}\n}}",
|
||||||
|
Formatter::from(translator, &**exp),
|
||||||
|
Formatter::from(translator, &**t)
|
||||||
|
),
|
||||||
|
| Self::IfElse(exp, t1, t2) => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"if {} {{\n{}\n}} else {{\n{}\n}}",
|
||||||
|
Formatter::from(translator, &**exp),
|
||||||
|
Formatter::from(translator, &**t1),
|
||||||
|
Formatter::from(translator, &**t2)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
| Self::Assignment(v, q, exp) =>
|
||||||
|
if let Some(q) = q {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}.{} = {}",
|
||||||
|
Formatter::from(translator, v),
|
||||||
|
Formatter::from(translator, q),
|
||||||
|
Formatter::from(translator, &**exp)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{} = {}",
|
||||||
|
Formatter::from(translator, v),
|
||||||
|
Formatter::from(translator, &**exp)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
| Self::Return(exp) => {
|
||||||
|
write!(f, "return {}", Formatter::from(translator, &**exp))
|
||||||
|
},
|
||||||
|
| Self::For(v, r, t) => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"for {} in {} {{\n{}\n}}",
|
||||||
|
Formatter::from(translator, v),
|
||||||
|
Formatter::from(translator, r),
|
||||||
|
Formatter::from(translator, &**t)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> PrintableWithTranslator for PositiveVariable<S>
|
||||||
|
where
|
||||||
|
S: PrintableWithTranslator,
|
||||||
|
{
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
translator: &Translator,
|
||||||
|
) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Special(s) => {
|
||||||
|
write!(f, "{}", Formatter::from(translator, s))
|
||||||
|
},
|
||||||
|
| Self::Id(s) => write!(f, "{s}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> PrintableWithTranslator for PositiveExpression<S>
|
||||||
|
where
|
||||||
|
S: PrintableWithTranslator,
|
||||||
|
{
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
translator: &Translator,
|
||||||
|
) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::True => write!(f, "True"),
|
||||||
|
| Self::False => write!(f, "False"),
|
||||||
|
| Self::Integer(i) => write!(f, "{i}"),
|
||||||
|
| Self::Label(l) => {
|
||||||
|
write!(f, "{}", Formatter::from(translator, &**l))
|
||||||
|
},
|
||||||
|
| Self::Set(set) => {
|
||||||
|
write!(f, "{}", Formatter::from(translator, set))
|
||||||
|
},
|
||||||
|
| Self::PositiveElement(el) => {
|
||||||
|
write!(f, "'{}'", Formatter::from(translator, el))
|
||||||
|
},
|
||||||
|
| Self::String(s) => write!(f, r#""{s}""#),
|
||||||
|
| Self::Var(v) => write!(f, "{}", Formatter::from(translator, v)),
|
||||||
|
| Self::Unary(u, exp) =>
|
||||||
|
if u.is_prefix() {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}({})",
|
||||||
|
Formatter::from(translator, u),
|
||||||
|
Formatter::from(translator, &**exp)
|
||||||
|
)
|
||||||
|
} else if u.is_suffix() {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}{}",
|
||||||
|
Formatter::from(translator, &**exp),
|
||||||
|
Formatter::from(translator, u)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
},
|
||||||
|
| Self::Binary(b, exp1, exp2) =>
|
||||||
|
if b.is_prefix() {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}({}, {})",
|
||||||
|
Formatter::from(translator, b),
|
||||||
|
Formatter::from(translator, &**exp1),
|
||||||
|
Formatter::from(translator, &**exp2)
|
||||||
|
)
|
||||||
|
} else if b.is_suffix() {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"({}, {}){}",
|
||||||
|
Formatter::from(translator, &**exp1),
|
||||||
|
Formatter::from(translator, &**exp2),
|
||||||
|
Formatter::from(translator, b)
|
||||||
|
)
|
||||||
|
} else if b.is_infix() {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"({} {} {})",
|
||||||
|
Formatter::from(translator, &**exp1),
|
||||||
|
Formatter::from(translator, b),
|
||||||
|
Formatter::from(translator, &**exp2)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> PrintableWithTranslator for PositiveRange<S>
|
||||||
|
where
|
||||||
|
S: PrintableWithTranslator,
|
||||||
|
{
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
translator: &Translator,
|
||||||
|
) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::IterateOverSet(exp) => {
|
||||||
|
write!(f, "{}", Formatter::from(translator, &**exp))
|
||||||
|
},
|
||||||
|
| Self::IterateInRange(exp1, exp2) => write!(
|
||||||
|
f,
|
||||||
|
"{}..{}",
|
||||||
|
Formatter::from(translator, &**exp1),
|
||||||
|
Formatter::from(translator, &**exp2)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrintableWithTranslator for PositiveUnary {
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
translator: &Translator,
|
||||||
|
) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Not => write!(f, "not"),
|
||||||
|
| Self::Rand => write!(f, "rand"),
|
||||||
|
| Self::Empty => write!(f, ".empty"),
|
||||||
|
| Self::Length => write!(f, ".length"),
|
||||||
|
| Self::ToStr => write!(f, ".tostr"),
|
||||||
|
| Self::ToEl => write!(f, ".toel"),
|
||||||
|
| Self::Qualifier(q) => {
|
||||||
|
write!(f, ".{}", Formatter::from(translator, q))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrintableWithTranslator for QualifierRestricted {
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
_translator: &Translator,
|
||||||
|
) -> fmt::Result {
|
||||||
|
write!(f, "{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrintableWithTranslator for QualifierLabel {
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
_translator: &Translator,
|
||||||
|
) -> fmt::Result {
|
||||||
|
write!(f, "{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrintableWithTranslator for QualifierSystem {
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
_translator: &Translator,
|
||||||
|
) -> fmt::Result {
|
||||||
|
write!(f, "{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrintableWithTranslator for QualifierEdge {
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
_translator: &Translator,
|
||||||
|
) -> fmt::Result {
|
||||||
|
write!(f, "{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrintableWithTranslator for QualifierNode {
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
_translator: &Translator,
|
||||||
|
) -> fmt::Result {
|
||||||
|
write!(f, "{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrintableWithTranslator for PositiveQualifier {
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
translator: &Translator,
|
||||||
|
) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Label(q) => write!(f, "{}", Formatter::from(translator, q)),
|
||||||
|
| Self::Restricted(q) => {
|
||||||
|
write!(f, "{}", Formatter::from(translator, q))
|
||||||
|
},
|
||||||
|
| Self::System(q) => {
|
||||||
|
write!(f, "{}", Formatter::from(translator, q))
|
||||||
|
},
|
||||||
|
| Self::Edge(q) => write!(f, "{}", Formatter::from(translator, q)),
|
||||||
|
| Self::Node(q) => write!(f, "{}", Formatter::from(translator, q)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrintableWithTranslator for PositiveBinary {
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
_translator: &Translator,
|
||||||
|
) -> fmt::Result {
|
||||||
|
write!(f, "{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrintableWithTranslator for PositiveAssertReturnValue {
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
translator: &Translator,
|
||||||
|
) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Boolean(b) => write!(f, "{b}"),
|
||||||
|
| Self::Integer(i) => write!(f, "{i}"),
|
||||||
|
| Self::String(s) => write!(f, r#""{s}""#),
|
||||||
|
| Self::Label(l) => write!(f, "{}", Formatter::from(translator, l)),
|
||||||
|
| Self::Set(set) => {
|
||||||
|
write!(f, "{}", Formatter::from(translator, set))
|
||||||
|
},
|
||||||
|
| Self::PositiveElement(el) => {
|
||||||
|
write!(f, "{}", Formatter::from(translator, el))
|
||||||
|
},
|
||||||
|
| Self::Edge(edge) => write!(f, "{{edge: {edge:?}}}"),
|
||||||
|
| Self::Node(node) => write!(f, "{{node: {node:?}}}"),
|
||||||
|
| Self::Neighbours(node) => {
|
||||||
|
write!(f, "{{node: {node:?}}}.neighbours")
|
||||||
|
},
|
||||||
|
| Self::System(sys) => {
|
||||||
|
write!(f, "{}", Formatter::from(translator, sys))
|
||||||
|
},
|
||||||
|
| Self::Context(ctx) => {
|
||||||
|
write!(f, "{}", Formatter::from(translator, ctx))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrintableWithTranslator for PositiveAssertionTypes {
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
_translator: &Translator,
|
||||||
|
) -> fmt::Result {
|
||||||
|
write!(f, "{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,11 +4,15 @@ use rsprocess::translator::PrintableWithTranslator;
|
|||||||
use rsprocess::{graph, label, set, system, translator};
|
use rsprocess::{graph, label, set, system, translator};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::dsl::*;
|
use super::{dsl, positivedsl};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Specific Assert Implementation
|
// Specific Assert Implementation
|
||||||
// ----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// System
|
||||||
|
|
||||||
/// Module that has all types and structures for bisimilarity relabeler.
|
/// Module that has all types and structures for bisimilarity relabeler.
|
||||||
pub mod useful_types_edge_relabeler {
|
pub mod useful_types_edge_relabeler {
|
||||||
@ -59,19 +63,19 @@ enum EdgeRelablerInputValues {
|
|||||||
Edge(petgraph::graph::EdgeIndex),
|
Edge(petgraph::graph::EdgeIndex),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecialVariables<EdgeRelablerInputValues> for EdgeRelablerInput {
|
impl dsl::SpecialVariables<EdgeRelablerInputValues> for EdgeRelablerInput {
|
||||||
fn type_of(&self) -> AssertionTypes {
|
fn type_of(&self) -> dsl::AssertionTypes {
|
||||||
match self {
|
match self {
|
||||||
| Self::Edge => AssertionTypes::Edge,
|
| Self::Edge => dsl::AssertionTypes::Edge,
|
||||||
| Self::Label => AssertionTypes::Label,
|
| Self::Label => dsl::AssertionTypes::Label,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_qualified(&self, q: &Qualifier) -> Result<AssertionTypes, String> {
|
fn type_qualified(&self, q: &dsl::Qualifier) -> Result<dsl::AssertionTypes, String> {
|
||||||
match (self, q) {
|
match (self, q) {
|
||||||
| (Self::Label, Qualifier::Label(_))
|
| (Self::Label, dsl::Qualifier::Label(_))
|
||||||
| (Self::Label, Qualifier::Restricted(_)) =>
|
| (Self::Label, dsl::Qualifier::Restricted(_)) =>
|
||||||
Ok(AssertionTypes::Set),
|
Ok(dsl::AssertionTypes::Set),
|
||||||
| (s, q) =>
|
| (s, q) =>
|
||||||
Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")),
|
Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")),
|
||||||
}
|
}
|
||||||
@ -79,22 +83,22 @@ impl SpecialVariables<EdgeRelablerInputValues> for EdgeRelablerInput {
|
|||||||
|
|
||||||
fn new_context(
|
fn new_context(
|
||||||
input: HashMap<Self, EdgeRelablerInputValues>,
|
input: HashMap<Self, EdgeRelablerInputValues>,
|
||||||
) -> HashMap<Self, AssertReturnValue> {
|
) -> HashMap<Self, dsl::AssertReturnValue> {
|
||||||
input
|
input
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(key, value)| match value {
|
.map(|(key, value)| match value {
|
||||||
| EdgeRelablerInputValues::Edge(e) =>
|
| EdgeRelablerInputValues::Edge(e) =>
|
||||||
(*key, AssertReturnValue::Edge(*e)),
|
(*key, dsl::AssertReturnValue::Edge(*e)),
|
||||||
| EdgeRelablerInputValues::Label(l) =>
|
| EdgeRelablerInputValues::Label(l) =>
|
||||||
(*key, AssertReturnValue::Label(l.clone())),
|
(*key, dsl::AssertReturnValue::Label(l.clone())),
|
||||||
})
|
})
|
||||||
.collect::<HashMap<Self, AssertReturnValue>>()
|
.collect::<HashMap<Self, dsl::AssertReturnValue>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn correct_type(&self, other: &AssertReturnValue) -> bool {
|
fn correct_type(&self, other: &dsl::AssertReturnValue) -> bool {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
| (Self::Edge, AssertReturnValue::Edge(_))
|
| (Self::Edge, dsl::AssertReturnValue::Edge(_))
|
||||||
| (Self::Label, AssertReturnValue::Label(_)) => true,
|
| (Self::Label, dsl::AssertReturnValue::Label(_)) => true,
|
||||||
| (_, _) => false,
|
| (_, _) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,27 +123,27 @@ impl PrintableWithTranslator for EdgeRelablerInput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Assert<EdgeRelablerInput> {
|
impl dsl::Assert<EdgeRelablerInput> {
|
||||||
pub fn typecheck(&self) -> Result<(), String> {
|
pub fn typecheck(&self) -> Result<(), String> {
|
||||||
let mut context = TypeContext::new();
|
let mut context = dsl::TypeContext::new();
|
||||||
let ty = typecheck(&self.tree, &mut context)?;
|
let ty = dsl::typecheck(&self.tree, &mut context)?;
|
||||||
match ty {
|
match ty {
|
||||||
| AssertionTypes::Boolean
|
| dsl::AssertionTypes::Boolean
|
||||||
| AssertionTypes::Integer
|
| dsl::AssertionTypes::Integer
|
||||||
| AssertionTypes::String
|
| dsl::AssertionTypes::String
|
||||||
| AssertionTypes::Label
|
| dsl::AssertionTypes::Label
|
||||||
| AssertionTypes::Set
|
| dsl::AssertionTypes::Set
|
||||||
| AssertionTypes::Element
|
| dsl::AssertionTypes::Element
|
||||||
| AssertionTypes::Edge
|
| dsl::AssertionTypes::Edge
|
||||||
| AssertionTypes::Node
|
| dsl::AssertionTypes::Node
|
||||||
| AssertionTypes::System
|
| dsl::AssertionTypes::System
|
||||||
| AssertionTypes::Context => Ok(()),
|
| dsl::AssertionTypes::Context => Ok(()),
|
||||||
| AssertionTypes::NoType =>
|
| dsl::AssertionTypes::NoType =>
|
||||||
Err("No return type, at least one return statement required."
|
Err("No return type, at least one return statement required."
|
||||||
.into()),
|
.into()),
|
||||||
| AssertionTypes::RangeInteger
|
| dsl::AssertionTypes::RangeInteger
|
||||||
| AssertionTypes::RangeSet
|
| dsl::AssertionTypes::RangeSet
|
||||||
| AssertionTypes::RangeNeighbours =>
|
| dsl::AssertionTypes::RangeNeighbours =>
|
||||||
Err(format!("Returned type {ty:?} is not a valid return type.")),
|
Err(format!("Returned type {ty:?} is not a valid return type.")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,7 +153,7 @@ impl Assert<EdgeRelablerInput> {
|
|||||||
graph: &graph::SystemGraph,
|
graph: &graph::SystemGraph,
|
||||||
edge: &<graph::SystemGraph as petgraph::visit::GraphBase>::EdgeId,
|
edge: &<graph::SystemGraph as petgraph::visit::GraphBase>::EdgeId,
|
||||||
translator: &mut translator::Translator,
|
translator: &mut translator::Translator,
|
||||||
) -> Result<AssertReturnValue, String> {
|
) -> Result<dsl::AssertReturnValue, String> {
|
||||||
let label = graph
|
let label = graph
|
||||||
.edge_weight(*edge)
|
.edge_weight(*edge)
|
||||||
.ok_or("Missing edge {{debug: {edge:?}}}")?;
|
.ok_or("Missing edge {{debug: {edge:?}}}")?;
|
||||||
@ -164,8 +168,8 @@ impl Assert<EdgeRelablerInput> {
|
|||||||
EdgeRelablerInputValues::Label(label.clone()),
|
EdgeRelablerInputValues::Label(label.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut context = Context::new(input_vals);
|
let mut context = dsl::Context::new(input_vals);
|
||||||
if let Some(v) = execute(&self.tree, &mut context, translator, graph)? {
|
if let Some(v) = dsl::execute(&self.tree, &mut context, translator, graph)? {
|
||||||
Ok(v)
|
Ok(v)
|
||||||
} else {
|
} else {
|
||||||
Err("No value returned.".into())
|
Err("No value returned.".into())
|
||||||
@ -224,20 +228,20 @@ enum NodeRelablerInputValues {
|
|||||||
Node(petgraph::graph::NodeIndex),
|
Node(petgraph::graph::NodeIndex),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecialVariables<NodeRelablerInputValues> for NodeRelablerInput {
|
impl dsl::SpecialVariables<NodeRelablerInputValues> for NodeRelablerInput {
|
||||||
fn type_of(&self) -> AssertionTypes {
|
fn type_of(&self) -> dsl::AssertionTypes {
|
||||||
match self {
|
match self {
|
||||||
| Self::Entities => AssertionTypes::Set,
|
| Self::Entities => dsl::AssertionTypes::Set,
|
||||||
| Self::Node => AssertionTypes::Node,
|
| Self::Node => dsl::AssertionTypes::Node,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_qualified(&self, q: &Qualifier) -> Result<AssertionTypes, String> {
|
fn type_qualified(&self, q: &dsl::Qualifier) -> Result<dsl::AssertionTypes, String> {
|
||||||
match (self, q) {
|
match (self, q) {
|
||||||
| (Self::Node, Qualifier::Node(QualifierNode::System)) =>
|
| (Self::Node, dsl::Qualifier::Node(dsl::QualifierNode::System)) =>
|
||||||
Ok(AssertionTypes::System),
|
Ok(dsl::AssertionTypes::System),
|
||||||
| (Self::Node, Qualifier::Node(QualifierNode::Neighbours)) =>
|
| (Self::Node, dsl::Qualifier::Node(dsl::QualifierNode::Neighbours)) =>
|
||||||
Ok(AssertionTypes::RangeNeighbours),
|
Ok(dsl::AssertionTypes::RangeNeighbours),
|
||||||
| (s, q) =>
|
| (s, q) =>
|
||||||
Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")),
|
Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")),
|
||||||
}
|
}
|
||||||
@ -245,22 +249,22 @@ impl SpecialVariables<NodeRelablerInputValues> for NodeRelablerInput {
|
|||||||
|
|
||||||
fn new_context(
|
fn new_context(
|
||||||
input: HashMap<Self, NodeRelablerInputValues>,
|
input: HashMap<Self, NodeRelablerInputValues>,
|
||||||
) -> HashMap<Self, AssertReturnValue> {
|
) -> HashMap<Self, dsl::AssertReturnValue> {
|
||||||
input
|
input
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(key, value)| match value {
|
.map(|(key, value)| match value {
|
||||||
| NodeRelablerInputValues::Entities(e) =>
|
| NodeRelablerInputValues::Entities(e) =>
|
||||||
(*key, AssertReturnValue::Set(e.clone())),
|
(*key, dsl::AssertReturnValue::Set(e.clone())),
|
||||||
| NodeRelablerInputValues::Node(n) =>
|
| NodeRelablerInputValues::Node(n) =>
|
||||||
(*key, AssertReturnValue::Node(*n)),
|
(*key, dsl::AssertReturnValue::Node(*n)),
|
||||||
})
|
})
|
||||||
.collect::<HashMap<Self, AssertReturnValue>>()
|
.collect::<HashMap<Self, dsl::AssertReturnValue>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn correct_type(&self, other: &AssertReturnValue) -> bool {
|
fn correct_type(&self, other: &dsl::AssertReturnValue) -> bool {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
| (Self::Entities, AssertReturnValue::Set(_))
|
| (Self::Entities, dsl::AssertReturnValue::Set(_))
|
||||||
| (Self::Node, AssertReturnValue::Node(_)) => true,
|
| (Self::Node, dsl::AssertReturnValue::Node(_)) => true,
|
||||||
| (_, _) => false,
|
| (_, _) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -285,27 +289,27 @@ impl PrintableWithTranslator for NodeRelablerInput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Assert<NodeRelablerInput> {
|
impl dsl::Assert<NodeRelablerInput> {
|
||||||
pub fn typecheck(&self) -> Result<(), String> {
|
pub fn typecheck(&self) -> Result<(), String> {
|
||||||
let mut context = TypeContext::new();
|
let mut context = dsl::TypeContext::new();
|
||||||
let ty = typecheck(&self.tree, &mut context)?;
|
let ty = dsl::typecheck(&self.tree, &mut context)?;
|
||||||
match ty {
|
match ty {
|
||||||
| AssertionTypes::Boolean
|
| dsl::AssertionTypes::Boolean
|
||||||
| AssertionTypes::Integer
|
| dsl::AssertionTypes::Integer
|
||||||
| AssertionTypes::String
|
| dsl::AssertionTypes::String
|
||||||
| AssertionTypes::Label
|
| dsl::AssertionTypes::Label
|
||||||
| AssertionTypes::Set
|
| dsl::AssertionTypes::Set
|
||||||
| AssertionTypes::Element
|
| dsl::AssertionTypes::Element
|
||||||
| AssertionTypes::Edge
|
| dsl::AssertionTypes::Edge
|
||||||
| AssertionTypes::Node
|
| dsl::AssertionTypes::Node
|
||||||
| AssertionTypes::System
|
| dsl::AssertionTypes::System
|
||||||
| AssertionTypes::Context => Ok(()),
|
| dsl::AssertionTypes::Context => Ok(()),
|
||||||
| AssertionTypes::NoType =>
|
| dsl::AssertionTypes::NoType =>
|
||||||
Err("No return type, at least one return statement required."
|
Err("No return type, at least one return statement required."
|
||||||
.into()),
|
.into()),
|
||||||
| AssertionTypes::RangeInteger
|
| dsl::AssertionTypes::RangeInteger
|
||||||
| AssertionTypes::RangeSet
|
| dsl::AssertionTypes::RangeSet
|
||||||
| AssertionTypes::RangeNeighbours =>
|
| dsl::AssertionTypes::RangeNeighbours =>
|
||||||
Err(format!("Returned type {ty:?} is not a valid return type.")),
|
Err(format!("Returned type {ty:?} is not a valid return type.")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -315,7 +319,7 @@ impl Assert<NodeRelablerInput> {
|
|||||||
graph: &graph::SystemGraph,
|
graph: &graph::SystemGraph,
|
||||||
node: &<graph::SystemGraph as petgraph::visit::GraphBase>::NodeId,
|
node: &<graph::SystemGraph as petgraph::visit::GraphBase>::NodeId,
|
||||||
translator: &mut translator::Translator,
|
translator: &mut translator::Translator,
|
||||||
) -> Result<AssertReturnValue, String> {
|
) -> Result<dsl::AssertReturnValue, String> {
|
||||||
let system::System {
|
let system::System {
|
||||||
available_entities: entities,
|
available_entities: entities,
|
||||||
..
|
..
|
||||||
@ -333,8 +337,359 @@ impl Assert<NodeRelablerInput> {
|
|||||||
NodeRelablerInputValues::Node(*node),
|
NodeRelablerInputValues::Node(*node),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut context = Context::new(input_vals);
|
let mut context = dsl::Context::new(input_vals);
|
||||||
if let Some(v) = execute(&self.tree, &mut context, translator, graph)? {
|
if let Some(v) = dsl::execute(&self.tree, &mut context, translator, graph)? {
|
||||||
|
Ok(v)
|
||||||
|
} else {
|
||||||
|
Err("No value returned.".into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Positive System
|
||||||
|
|
||||||
|
|
||||||
|
/// Module that has all types and structures for bisimilarity relabeler.
|
||||||
|
pub mod useful_types_positive_edge_relabeler {
|
||||||
|
macro_rules! export_types {
|
||||||
|
( $( $x:ident ),* ) => {
|
||||||
|
$(
|
||||||
|
pub type $x = super::super::positivedsl::$x<super::PositiveEdgeRelablerInput>;
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! export_types_no_parameter {
|
||||||
|
( $( $x:ident ),* ) => {
|
||||||
|
$(
|
||||||
|
pub type $x = super::super::positivedsl::$x;
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export_types!(
|
||||||
|
PositiveAssert,
|
||||||
|
PositiveTree,
|
||||||
|
PositiveVariable,
|
||||||
|
PositiveExpression,
|
||||||
|
PositiveRange
|
||||||
|
);
|
||||||
|
|
||||||
|
export_types_no_parameter!(
|
||||||
|
PositiveUnary,
|
||||||
|
QualifierRestricted,
|
||||||
|
QualifierLabel,
|
||||||
|
QualifierSystem,
|
||||||
|
QualifierEdge,
|
||||||
|
QualifierNode,
|
||||||
|
PositiveQualifier,
|
||||||
|
PositiveBinary,
|
||||||
|
PositiveAssertReturnValue
|
||||||
|
);
|
||||||
|
|
||||||
|
pub type Special = super::PositiveEdgeRelablerInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
|
pub enum PositiveEdgeRelablerInput {
|
||||||
|
Label,
|
||||||
|
Edge,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
enum PositiveEdgeRelablerInputValues {
|
||||||
|
Label(label::PositiveLabel),
|
||||||
|
Edge(petgraph::graph::EdgeIndex),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl positivedsl::SpecialVariables<PositiveEdgeRelablerInputValues> for PositiveEdgeRelablerInput {
|
||||||
|
fn type_of(&self) -> positivedsl::PositiveAssertionTypes {
|
||||||
|
match self {
|
||||||
|
| Self::Edge => positivedsl::PositiveAssertionTypes::Edge,
|
||||||
|
| Self::Label => positivedsl::PositiveAssertionTypes::Label,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_qualified(&self, q: &positivedsl::PositiveQualifier) -> Result<positivedsl::PositiveAssertionTypes, String> {
|
||||||
|
match (self, q) {
|
||||||
|
| (Self::Label, positivedsl::PositiveQualifier::Label(_))
|
||||||
|
| (Self::Label, positivedsl::PositiveQualifier::Restricted(_)) =>
|
||||||
|
Ok(positivedsl::PositiveAssertionTypes::Set),
|
||||||
|
| (s, q) =>
|
||||||
|
Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_context(
|
||||||
|
input: HashMap<Self, PositiveEdgeRelablerInputValues>,
|
||||||
|
) -> HashMap<Self, positivedsl::PositiveAssertReturnValue> {
|
||||||
|
input
|
||||||
|
.iter()
|
||||||
|
.map(|(key, value)| match value {
|
||||||
|
| PositiveEdgeRelablerInputValues::Edge(e) =>
|
||||||
|
(*key, positivedsl::PositiveAssertReturnValue::Edge(*e)),
|
||||||
|
| PositiveEdgeRelablerInputValues::Label(l) =>
|
||||||
|
(*key, positivedsl::PositiveAssertReturnValue::Label(l.clone())),
|
||||||
|
})
|
||||||
|
.collect::<HashMap<Self, positivedsl::PositiveAssertReturnValue>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn correct_type(&self, other: &positivedsl::PositiveAssertReturnValue) -> bool {
|
||||||
|
match (self, other) {
|
||||||
|
| (Self::Edge, positivedsl::PositiveAssertReturnValue::Edge(_))
|
||||||
|
| (Self::Label, positivedsl::PositiveAssertReturnValue::Label(_)) => true,
|
||||||
|
| (_, _) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for PositiveEdgeRelablerInput {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Label => write!(f, "label"),
|
||||||
|
| Self::Edge => write!(f, "edge"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrintableWithTranslator for PositiveEdgeRelablerInput {
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut std::fmt::Formatter,
|
||||||
|
_translator: &translator::Translator,
|
||||||
|
) -> std::fmt::Result {
|
||||||
|
write!(f, "{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl positivedsl::PositiveAssert<PositiveEdgeRelablerInput> {
|
||||||
|
pub fn typecheck(&self) -> Result<(), String> {
|
||||||
|
let mut context = positivedsl::TypeContext::new();
|
||||||
|
let ty = positivedsl::typecheck(&self.tree, &mut context)?;
|
||||||
|
match ty {
|
||||||
|
| positivedsl::PositiveAssertionTypes::Boolean
|
||||||
|
| positivedsl::PositiveAssertionTypes::Integer
|
||||||
|
| positivedsl::PositiveAssertionTypes::String
|
||||||
|
| positivedsl::PositiveAssertionTypes::Label
|
||||||
|
| positivedsl::PositiveAssertionTypes::Set
|
||||||
|
| positivedsl::PositiveAssertionTypes::PositiveElement
|
||||||
|
| positivedsl::PositiveAssertionTypes::Edge
|
||||||
|
| positivedsl::PositiveAssertionTypes::Node
|
||||||
|
| positivedsl::PositiveAssertionTypes::System
|
||||||
|
| positivedsl::PositiveAssertionTypes::Context => Ok(()),
|
||||||
|
| positivedsl::PositiveAssertionTypes::NoType =>
|
||||||
|
Err("No return type, at least one return statement required."
|
||||||
|
.into()),
|
||||||
|
| positivedsl::PositiveAssertionTypes::RangeInteger
|
||||||
|
| positivedsl::PositiveAssertionTypes::RangeSet
|
||||||
|
| positivedsl::PositiveAssertionTypes::RangeNeighbours =>
|
||||||
|
Err(format!("Returned type {ty:?} is not a valid return type.")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execute(
|
||||||
|
&self,
|
||||||
|
graph: &graph::PositiveSystemGraph,
|
||||||
|
edge: &<graph::PositiveSystemGraph as petgraph::visit::GraphBase>::EdgeId,
|
||||||
|
translator: &mut translator::Translator,
|
||||||
|
) -> Result<positivedsl::PositiveAssertReturnValue, String> {
|
||||||
|
let label = graph
|
||||||
|
.edge_weight(*edge)
|
||||||
|
.ok_or("Missing edge {{debug: {edge:?}}}")?;
|
||||||
|
|
||||||
|
let mut input_vals = HashMap::new();
|
||||||
|
input_vals.insert(
|
||||||
|
PositiveEdgeRelablerInput::Edge,
|
||||||
|
PositiveEdgeRelablerInputValues::Edge(*edge),
|
||||||
|
);
|
||||||
|
input_vals.insert(
|
||||||
|
PositiveEdgeRelablerInput::Label,
|
||||||
|
PositiveEdgeRelablerInputValues::Label(label.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut context = positivedsl::Context::new(input_vals);
|
||||||
|
if let Some(v) = positivedsl::execute(&self.tree, &mut context, translator, graph)? {
|
||||||
|
Ok(v)
|
||||||
|
} else {
|
||||||
|
Err("No value returned.".into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Positive node grouping
|
||||||
|
|
||||||
|
pub mod useful_types_positive_node_relabeler {
|
||||||
|
macro_rules! export_types {
|
||||||
|
( $( $x:ident ),* ) => {
|
||||||
|
$(
|
||||||
|
pub type $x = super::super::positivedsl::$x<super::PositiveNodeRelablerInput>;
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! export_types_no_parameter {
|
||||||
|
( $( $x:ident ),* ) => {
|
||||||
|
$(
|
||||||
|
pub type $x = super::super::positivedsl::$x;
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export_types!(
|
||||||
|
PositiveAssert,
|
||||||
|
PositiveTree,
|
||||||
|
PositiveVariable,
|
||||||
|
PositiveExpression,
|
||||||
|
PositiveRange
|
||||||
|
);
|
||||||
|
|
||||||
|
export_types_no_parameter!(
|
||||||
|
PositiveUnary,
|
||||||
|
QualifierRestricted,
|
||||||
|
QualifierLabel,
|
||||||
|
QualifierSystem,
|
||||||
|
QualifierEdge,
|
||||||
|
QualifierNode,
|
||||||
|
PositiveQualifier,
|
||||||
|
PositiveBinary,
|
||||||
|
PositiveAssertReturnValue
|
||||||
|
);
|
||||||
|
|
||||||
|
pub type Special = super::PositiveNodeRelablerInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
|
pub enum PositiveNodeRelablerInput {
|
||||||
|
Entities,
|
||||||
|
Node,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
enum PositiveNodeRelablerInputValues {
|
||||||
|
Entities(set::PositiveSet),
|
||||||
|
Node(petgraph::graph::NodeIndex),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl positivedsl::SpecialVariables<PositiveNodeRelablerInputValues> for PositiveNodeRelablerInput {
|
||||||
|
fn type_of(&self) -> positivedsl::PositiveAssertionTypes {
|
||||||
|
match self {
|
||||||
|
| Self::Entities => positivedsl::PositiveAssertionTypes::Set,
|
||||||
|
| Self::Node => positivedsl::PositiveAssertionTypes::Node,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_qualified(&self, q: &positivedsl::PositiveQualifier) -> Result<positivedsl::PositiveAssertionTypes, String> {
|
||||||
|
match (self, q) {
|
||||||
|
| (Self::Node, positivedsl::PositiveQualifier::Node(positivedsl::QualifierNode::System)) =>
|
||||||
|
Ok(positivedsl::PositiveAssertionTypes::System),
|
||||||
|
| (Self::Node, positivedsl::PositiveQualifier::Node(positivedsl::QualifierNode::Neighbours)) =>
|
||||||
|
Ok(positivedsl::PositiveAssertionTypes::RangeNeighbours),
|
||||||
|
| (s, q) =>
|
||||||
|
Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_context(
|
||||||
|
input: HashMap<Self, PositiveNodeRelablerInputValues>,
|
||||||
|
) -> HashMap<Self, positivedsl::PositiveAssertReturnValue> {
|
||||||
|
input
|
||||||
|
.iter()
|
||||||
|
.map(|(key, value)| match value {
|
||||||
|
| PositiveNodeRelablerInputValues::Entities(e) =>
|
||||||
|
(*key, positivedsl::PositiveAssertReturnValue::Set(e.clone())),
|
||||||
|
| PositiveNodeRelablerInputValues::Node(n) =>
|
||||||
|
(*key, positivedsl::PositiveAssertReturnValue::Node(*n)),
|
||||||
|
})
|
||||||
|
.collect::<HashMap<Self, positivedsl::PositiveAssertReturnValue>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn correct_type(&self, other: &positivedsl::PositiveAssertReturnValue) -> bool {
|
||||||
|
match (self, other) {
|
||||||
|
| (Self::Entities, positivedsl::PositiveAssertReturnValue::Set(_))
|
||||||
|
| (Self::Node, positivedsl::PositiveAssertReturnValue::Node(_)) => true,
|
||||||
|
| (_, _) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl std::fmt::Debug for PositiveNodeRelablerInput {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
| Self::Entities => write!(f, "entities"),
|
||||||
|
| Self::Node => write!(f, "node"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrintableWithTranslator for PositiveNodeRelablerInput {
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut std::fmt::Formatter,
|
||||||
|
_translator: &translator::Translator,
|
||||||
|
) -> std::fmt::Result {
|
||||||
|
write!(f, "{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl positivedsl::PositiveAssert<PositiveNodeRelablerInput> {
|
||||||
|
pub fn typecheck(&self) -> Result<(), String> {
|
||||||
|
let mut context = positivedsl::TypeContext::new();
|
||||||
|
let ty = positivedsl::typecheck(&self.tree, &mut context)?;
|
||||||
|
match ty {
|
||||||
|
| positivedsl::PositiveAssertionTypes::Boolean
|
||||||
|
| positivedsl::PositiveAssertionTypes::Integer
|
||||||
|
| positivedsl::PositiveAssertionTypes::String
|
||||||
|
| positivedsl::PositiveAssertionTypes::Label
|
||||||
|
| positivedsl::PositiveAssertionTypes::Set
|
||||||
|
| positivedsl::PositiveAssertionTypes::PositiveElement
|
||||||
|
| positivedsl::PositiveAssertionTypes::Edge
|
||||||
|
| positivedsl::PositiveAssertionTypes::Node
|
||||||
|
| positivedsl::PositiveAssertionTypes::System
|
||||||
|
| positivedsl::PositiveAssertionTypes::Context => Ok(()),
|
||||||
|
| positivedsl::PositiveAssertionTypes::NoType =>
|
||||||
|
Err("No return type, at least one return statement required."
|
||||||
|
.into()),
|
||||||
|
| positivedsl::PositiveAssertionTypes::RangeInteger
|
||||||
|
| positivedsl::PositiveAssertionTypes::RangeSet
|
||||||
|
| positivedsl::PositiveAssertionTypes::RangeNeighbours =>
|
||||||
|
Err(format!("Returned type {ty:?} is not a valid return type.")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execute(
|
||||||
|
&self,
|
||||||
|
graph: &graph::PositiveSystemGraph,
|
||||||
|
node: &<graph::PositiveSystemGraph as petgraph::visit::GraphBase>::NodeId,
|
||||||
|
translator: &mut translator::Translator,
|
||||||
|
) -> Result<positivedsl::PositiveAssertReturnValue, String> {
|
||||||
|
let system::PositiveSystem {
|
||||||
|
available_entities: entities,
|
||||||
|
..
|
||||||
|
} = graph
|
||||||
|
.node_weight(*node)
|
||||||
|
.ok_or("Missing node {{debug: {node:?}}}")?;
|
||||||
|
|
||||||
|
let mut input_vals = HashMap::new();
|
||||||
|
input_vals.insert(
|
||||||
|
PositiveNodeRelablerInput::Entities,
|
||||||
|
PositiveNodeRelablerInputValues::Entities(entities.clone()),
|
||||||
|
);
|
||||||
|
input_vals.insert(
|
||||||
|
PositiveNodeRelablerInput::Node,
|
||||||
|
PositiveNodeRelablerInputValues::Node(*node),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut context = positivedsl::Context::new(input_vals);
|
||||||
|
if let Some(v) = positivedsl::execute(&self.tree, &mut context, translator, graph)? {
|
||||||
Ok(v)
|
Ok(v)
|
||||||
} else {
|
} else {
|
||||||
Err("No value returned.".into())
|
Err("No value returned.".into())
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use petgraph::{Directed, Graph};
|
use petgraph::{Directed, Graph};
|
||||||
use rsprocess::graph::SystemGraph;
|
use rsprocess::graph::{PositiveSystemGraph, SystemGraph};
|
||||||
use rsprocess::label::Label;
|
use rsprocess::label::{Label, PositiveLabel};
|
||||||
use rsprocess::system::System;
|
use rsprocess::system::{PositiveSystem, System};
|
||||||
use rsprocess::translator;
|
use rsprocess::translator;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -58,3 +58,158 @@ impl<'a> MapEdges<'a, System, Label, Directed, u32> for SystemGraph {
|
|||||||
Ok(g)
|
Ok(g)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Very inelegant way to provide our graph with a map method where the edges
|
||||||
|
/// are mapped until the first error.
|
||||||
|
pub trait PositiveMapEdges<'a, N: 'a, E, Ty, Ix>
|
||||||
|
where
|
||||||
|
Ty: petgraph::EdgeType,
|
||||||
|
Ix: petgraph::graph::IndexType,
|
||||||
|
{
|
||||||
|
fn map_edges(
|
||||||
|
&self,
|
||||||
|
edge_map: &assert::positive_relabel::PositiveAssert,
|
||||||
|
translator: &mut translator::Translator,
|
||||||
|
) -> Result<Graph<PositiveSystem, assert::positive_relabel::PositiveAssertReturnValue, Ty, Ix>, String>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> PositiveMapEdges<'a, PositiveSystem, PositiveLabel, Directed, u32> for PositiveSystemGraph {
|
||||||
|
fn map_edges(
|
||||||
|
&self,
|
||||||
|
edge_map: &assert::positive_relabel::PositiveAssert,
|
||||||
|
translator: &mut translator::Translator,
|
||||||
|
) -> Result<Graph<PositiveSystem, assert::positive_relabel::PositiveAssertReturnValue, Directed, u32>, String>
|
||||||
|
{
|
||||||
|
use petgraph::graph::EdgeIndex;
|
||||||
|
|
||||||
|
let mut g = Graph::with_capacity(self.node_count(), self.edge_count());
|
||||||
|
let nodes = self.raw_nodes();
|
||||||
|
let edges = self.raw_edges();
|
||||||
|
|
||||||
|
let edges = edges
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, edge)| {
|
||||||
|
match edge_map.execute(self, &EdgeIndex::new(i), translator) {
|
||||||
|
| Err(e) => Err(e),
|
||||||
|
| Ok(val) => Ok((edge.source(), edge.target(), val)),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
nodes.iter().for_each(|node| {
|
||||||
|
g.add_node(node.weight.clone());
|
||||||
|
});
|
||||||
|
|
||||||
|
edges.into_iter().for_each(|(source, target, v)| {
|
||||||
|
g.add_edge(source, target, v);
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Given a graph and a function that identifies nodes of the graph, merges
|
||||||
|
/// nodes with the same identifier.
|
||||||
|
pub fn grouping(
|
||||||
|
graph: &mut Graph<System, Label>,
|
||||||
|
group: &assert::grouping::Assert,
|
||||||
|
translator: &mut rsprocess::translator::Translator
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let mut buckets = std::collections::HashMap::new();
|
||||||
|
let mut leader: std::collections::HashMap<petgraph::prelude::NodeIndex, _> = std::collections::HashMap::new();
|
||||||
|
|
||||||
|
for node in graph.node_indices() {
|
||||||
|
let val = group.execute(graph, &node, translator)?;
|
||||||
|
buckets.entry(val.clone()).or_insert(vec![]).push(node);
|
||||||
|
let l = buckets.get(&val).unwrap().first().unwrap();
|
||||||
|
leader.insert(node, (*l, val));
|
||||||
|
}
|
||||||
|
|
||||||
|
for node in graph.node_indices().rev() {
|
||||||
|
let (origin, val) = leader.get(&node).unwrap();
|
||||||
|
if *origin == node {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if buckets.get(val).unwrap().len() <= 1 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut edges =
|
||||||
|
graph.neighbors_directed(node, petgraph::Outgoing).detach();
|
||||||
|
while let Some(edge) = edges.next_edge(graph) {
|
||||||
|
graph.add_edge(
|
||||||
|
*origin,
|
||||||
|
graph.edge_endpoints(edge).unwrap().1,
|
||||||
|
graph.edge_weight(edge).unwrap().clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let mut edges =
|
||||||
|
graph.neighbors_directed(node, petgraph::Incoming).detach();
|
||||||
|
while let Some(edge) = edges.next_edge(graph) {
|
||||||
|
graph.add_edge(
|
||||||
|
graph.edge_endpoints(edge).unwrap().0,
|
||||||
|
*origin,
|
||||||
|
graph.edge_weight(edge).unwrap().clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
graph
|
||||||
|
.remove_node(node)
|
||||||
|
.ok_or(format!("Could not remove node {node:?}"))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given a graph and a function that identifies nodes of the graph, merges
|
||||||
|
/// nodes with the same identifier.
|
||||||
|
pub fn positive_grouping(
|
||||||
|
graph: &mut Graph<PositiveSystem, PositiveLabel>,
|
||||||
|
group: &assert::positive_grouping::PositiveAssert,
|
||||||
|
translator: &mut rsprocess::translator::Translator
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let mut buckets = std::collections::HashMap::new();
|
||||||
|
let mut leader: std::collections::HashMap<petgraph::prelude::NodeIndex, _> = std::collections::HashMap::new();
|
||||||
|
|
||||||
|
for node in graph.node_indices() {
|
||||||
|
let val = group.execute(graph, &node, translator)?;
|
||||||
|
buckets.entry(val.clone()).or_insert(vec![]).push(node);
|
||||||
|
let l = buckets.get(&val).unwrap().first().unwrap();
|
||||||
|
leader.insert(node, (*l, val));
|
||||||
|
}
|
||||||
|
|
||||||
|
for node in graph.node_indices().rev() {
|
||||||
|
let (origin, val) = leader.get(&node).unwrap();
|
||||||
|
if *origin == node {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if buckets.get(val).unwrap().len() <= 1 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut edges =
|
||||||
|
graph.neighbors_directed(node, petgraph::Outgoing).detach();
|
||||||
|
while let Some(edge) = edges.next_edge(graph) {
|
||||||
|
graph.add_edge(
|
||||||
|
*origin,
|
||||||
|
graph.edge_endpoints(edge).unwrap().1,
|
||||||
|
graph.edge_weight(edge).unwrap().clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let mut edges =
|
||||||
|
graph.neighbors_directed(node, petgraph::Incoming).detach();
|
||||||
|
while let Some(edge) = edges.next_edge(graph) {
|
||||||
|
graph.add_edge(
|
||||||
|
graph.edge_endpoints(edge).unwrap().0,
|
||||||
|
*origin,
|
||||||
|
graph.edge_weight(edge).unwrap().clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
graph
|
||||||
|
.remove_node(node)
|
||||||
|
.ok_or(format!("Could not remove node {node:?}"))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
//! Module that holds useful presets for interacting with other modules.
|
//! Module that holds useful presets for interacting with other modules.
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::{env, fs, io};
|
use std::{env, fs, io};
|
||||||
@ -629,7 +628,9 @@ where
|
|||||||
|
|
||||||
/// Computes the LTS.
|
/// Computes the LTS.
|
||||||
/// equivalent to main_do(digraph, Arcs) or to main_do(advdigraph, Arcs)
|
/// equivalent to main_do(digraph, Arcs) or to main_do(advdigraph, Arcs)
|
||||||
pub fn digraph(system: &mut EvaluatedSystem) -> Result<(), String> {
|
pub fn digraph(
|
||||||
|
system: &mut EvaluatedSystem,
|
||||||
|
) -> Result<(), String> {
|
||||||
if let (Some(sys), true) = (&system.sys, system.graph.is_none()) {
|
if let (Some(sys), true) = (&system.sys, system.graph.is_none()) {
|
||||||
let graph = sys.digraph()?;
|
let graph = sys.digraph()?;
|
||||||
system.graph = Some(graph);
|
system.graph = Some(graph);
|
||||||
@ -642,57 +643,16 @@ pub fn digraph(system: &mut EvaluatedSystem) -> Result<(), String> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a graph and a function that identifies nodes of the graph, merges
|
|
||||||
/// nodes with the same identifier.
|
|
||||||
pub fn grouping(
|
pub fn grouping(
|
||||||
system: &mut EvaluatedSystem,
|
system: &mut EvaluatedSystem,
|
||||||
group: &assert::grouping::Assert,
|
group: &assert::grouping::Assert,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let mut buckets = HashMap::new();
|
if system.graph.is_some() {
|
||||||
let mut leader: HashMap<petgraph::prelude::NodeIndex, _> = HashMap::new();
|
super::data::grouping(
|
||||||
|
system.graph.as_mut().unwrap(),
|
||||||
if let Some(graph) = &mut system.graph {
|
group,
|
||||||
for node in graph.node_indices() {
|
&mut system.translator
|
||||||
let val = group.execute(graph, &node, &mut system.translator)?;
|
)
|
||||||
println!("node: {node:?} -> val: {val:?}");
|
|
||||||
buckets.entry(val.clone()).or_insert(vec![]).push(node);
|
|
||||||
let l = buckets.get(&val).unwrap().first().unwrap();
|
|
||||||
leader.insert(node, (*l, val));
|
|
||||||
}
|
|
||||||
|
|
||||||
for node in graph.node_indices().rev() {
|
|
||||||
let (origin, val) = leader.get(&node).unwrap();
|
|
||||||
if *origin == node {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if buckets.get(val).unwrap().len() <= 1 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut edges =
|
|
||||||
graph.neighbors_directed(node, petgraph::Outgoing).detach();
|
|
||||||
while let Some(edge) = edges.next_edge(graph) {
|
|
||||||
graph.add_edge(
|
|
||||||
*origin,
|
|
||||||
graph.edge_endpoints(edge).unwrap().1,
|
|
||||||
graph.edge_weight(edge).unwrap().clone(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let mut edges =
|
|
||||||
graph.neighbors_directed(node, petgraph::Incoming).detach();
|
|
||||||
while let Some(edge) = edges.next_edge(graph) {
|
|
||||||
graph.add_edge(
|
|
||||||
graph.edge_endpoints(edge).unwrap().0,
|
|
||||||
*origin,
|
|
||||||
graph.edge_weight(edge).unwrap().clone(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
graph
|
|
||||||
.remove_node(node)
|
|
||||||
.ok_or(format!("Could not remove node {node:?}"))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
} else {
|
} else {
|
||||||
Err("Grouping can be done only on graphs.".into())
|
Err("Grouping can be done only on graphs.".into())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -140,8 +140,7 @@ AssertTree2: relabel::Tree = {
|
|||||||
"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)),
|
||||||
|
|
||||||
"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)),
|
||||||
|
|
||||||
"return" <e: AssertExpression> ";" =>
|
"return" <e: AssertExpression> ";" =>
|
||||||
|
|||||||
@ -1,13 +1,9 @@
|
|||||||
use std::rc::Rc;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use lalrpop_util::ParseError;
|
use lalrpop_util::ParseError;
|
||||||
|
|
||||||
use assert::{relabel, grouping};
|
use assert::grouping;
|
||||||
use rsprocess::{set, reaction, process, environment, system, label};
|
use rsprocess::{set, label};
|
||||||
use rsprocess::element::IdType;
|
|
||||||
use rsprocess::translator::Translator;
|
use rsprocess::translator::Translator;
|
||||||
use execution::presets;
|
|
||||||
use rsprocess::graph;
|
|
||||||
use crate::custom_error;
|
use crate::custom_error;
|
||||||
|
|
||||||
grammar(translator: &mut Translator);
|
grammar(translator: &mut Translator);
|
||||||
@ -23,7 +19,14 @@ extern {
|
|||||||
|
|
||||||
// order
|
// order
|
||||||
match {
|
match {
|
||||||
"!",
|
"!", "!=", "%", "&&", "'", "(", ")", "*", "+", ",", "-", "..", "/", ":",
|
||||||
|
"::", ";", "<", "<=", "=", "==", ">", ">=", "AllInhibitors", "AllReactants",
|
||||||
|
"AvailableEntities", "Context", "Entities", "Inhibitors",
|
||||||
|
"InhibitorsPresent", "Products", "Reactants", "ReactantsAbsent",
|
||||||
|
"SystemContext", "SystemEntities", "[", "\"", "]", "^", "^^", "edge",
|
||||||
|
"else", "empty", "false", "for", "if", "in", "label", "length", "let",
|
||||||
|
"neighbours", "not", "rand", "return", "source", "system", "target", "then",
|
||||||
|
"toel", "tostr", "true", "{", "||", "}", "node",
|
||||||
} else {
|
} else {
|
||||||
r"[0-9]+" => NUMBER
|
r"[0-9]+" => NUMBER
|
||||||
} else {
|
} else {
|
||||||
@ -90,9 +93,9 @@ Separated_Empty<LP, T, C, RP>: Vec<T> = {
|
|||||||
// SetParser
|
// SetParser
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
pub Set: set::Set = {
|
Set: set::Set = {
|
||||||
<s: Separated_Empty<"{", Literal, ",", "}">> =>
|
<s: Separated_Empty<"{", Literal, ",", "}">> =>
|
||||||
set::Set::from(t.into_iter().map(|t| translator.encode(t))
|
set::Set::from(s.into_iter().map(|t| translator.encode(t))
|
||||||
.collect::<Vec<_>>())
|
.collect::<Vec<_>>())
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -100,7 +103,7 @@ pub Set: set::Set = {
|
|||||||
// LabelParser
|
// LabelParser
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
pub Label: label::Label = {
|
Label: label::Label = {
|
||||||
"["
|
"["
|
||||||
"Entities" ":" <e: Set> ","
|
"Entities" ":" <e: Set> ","
|
||||||
"Context" ":" <c: Set> ","
|
"Context" ":" <c: Set> ","
|
||||||
@ -116,8 +119,8 @@ pub Label: label::Label = {
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// GroupingParser
|
// GroupingParser
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
Group: Box<grouping::Assert> = {
|
pub Group: Box<grouping::Assert> = {
|
||||||
">" "node" "{" <f: GroupTree> "}" =>
|
"node" "{" <f: GroupTree> "}" =>
|
||||||
Box::new(grouping::Assert{tree: f}),
|
Box::new(grouping::Assert{tree: f}),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -202,7 +205,6 @@ GroupTerm: grouping::Expression = {
|
|||||||
"(" <e: GroupExpression> ")" => e,
|
"(" <e: GroupExpression> ")" => e,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
GroupRange: grouping::Range = {
|
GroupRange: grouping::Range = {
|
||||||
"{" <e: GroupExpression> "}" =>
|
"{" <e: GroupExpression> "}" =>
|
||||||
grouping::Range::IterateOverSet(Box::new(e)),
|
grouping::Range::IterateOverSet(Box::new(e)),
|
||||||
@ -210,13 +212,11 @@ GroupRange: grouping::Range = {
|
|||||||
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,
|
||||||
@ -228,7 +228,6 @@ 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,
|
||||||
@ -239,32 +238,27 @@ 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),
|
||||||
@ -273,7 +267,6 @@ 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,
|
||||||
@ -293,7 +286,6 @@ 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,
|
||||||
|
|||||||
@ -26,6 +26,39 @@ pub mod assert {
|
|||||||
include!(concat!(env!("OUT_DIR"), "/src/assert.rs"));
|
include!(concat!(env!("OUT_DIR"), "/src/assert.rs"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
#[allow(clippy::extra_unused_lifetimes)]
|
||||||
|
#[allow(clippy::needless_lifetimes)]
|
||||||
|
#[allow(clippy::let_unit_value)]
|
||||||
|
#[allow(clippy::just_underscores_and_digits)]
|
||||||
|
#[allow(clippy::uninlined_format_args)]
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
pub mod positive_assert {
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/src/positive_assert.rs"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
#[allow(clippy::extra_unused_lifetimes)]
|
||||||
|
#[allow(clippy::needless_lifetimes)]
|
||||||
|
#[allow(clippy::let_unit_value)]
|
||||||
|
#[allow(clippy::just_underscores_and_digits)]
|
||||||
|
#[allow(clippy::uninlined_format_args)]
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
pub mod grouping {
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/src/grouping.rs"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
#[allow(clippy::extra_unused_lifetimes)]
|
||||||
|
#[allow(clippy::needless_lifetimes)]
|
||||||
|
#[allow(clippy::let_unit_value)]
|
||||||
|
#[allow(clippy::just_underscores_and_digits)]
|
||||||
|
#[allow(clippy::uninlined_format_args)]
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
pub mod positive_grouping {
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/src/positive_grouping.rs"));
|
||||||
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
#[allow(clippy::extra_unused_lifetimes)]
|
#[allow(clippy::extra_unused_lifetimes)]
|
||||||
#[allow(clippy::needless_lifetimes)]
|
#[allow(clippy::needless_lifetimes)]
|
||||||
|
|||||||
297
grammar_separated/src/positive_assert.lalrpop
Normal file
297
grammar_separated/src/positive_assert.lalrpop
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
use lalrpop_util::ParseError;
|
||||||
|
|
||||||
|
use assert::positive_relabel;
|
||||||
|
use rsprocess::{set, label};
|
||||||
|
use rsprocess::translator::Translator;
|
||||||
|
use crate::custom_error;
|
||||||
|
|
||||||
|
grammar(translator: &mut Translator);
|
||||||
|
|
||||||
|
extern {
|
||||||
|
type Error = custom_error::UserError;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Helpers
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// order
|
||||||
|
match {
|
||||||
|
"!", "!=", "%", "&&", "'", "(", ")", "*", "+", ",", "-", "..", "/", ":",
|
||||||
|
"::", ";", "<", "<=", "=", "==", ">", ">=", "AllInhibitors", "AllReactants",
|
||||||
|
"AvailableEntities", "Context", "Entities", "Inhibitors",
|
||||||
|
"InhibitorsPresent", "Products", "Reactants", "ReactantsAbsent",
|
||||||
|
"SystemContext", "SystemEntities", "[", "\"", "]", "^", "^^", "edge",
|
||||||
|
"else", "empty", "false", "for", "if", "in", "label", "length", "let",
|
||||||
|
"neighbours", "not", "rand", "return", "source", "system", "target", "then",
|
||||||
|
"toel", "tostr", "true", "{", "||", "}",
|
||||||
|
} else {
|
||||||
|
r"[0-9]+" => NUMBER
|
||||||
|
} else {
|
||||||
|
r"([[:alpha:]])([[:word:]])*" => WORD
|
||||||
|
// r"(\p{L}|\p{Emoji})(\p{L}|\p{Emoji}|\p{Dash}|\p{N})*" => WORD,
|
||||||
|
} else {
|
||||||
|
r#""[^"]+""# => PATH, // " <- ignore comment, its for the linter in emacs
|
||||||
|
} else {
|
||||||
|
_
|
||||||
|
}
|
||||||
|
|
||||||
|
// matches words (letter followed by numbers, letters or _)
|
||||||
|
Literal: String = {
|
||||||
|
WORD => <>.into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Num: i64 = {
|
||||||
|
<sign: "-"?> <start: @L> <n: NUMBER> <end: @R> =>? {
|
||||||
|
if sign.is_some() {
|
||||||
|
i64::from_str(n)
|
||||||
|
.map(|n| -n)
|
||||||
|
.map_err(|_| ParseError::User {
|
||||||
|
error: custom_error::UserError {
|
||||||
|
token: (start, n.into(), end),
|
||||||
|
error: custom_error::UserErrorTypes::NumberTooBigi64
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
i64::from_str(n)
|
||||||
|
.map_err(|_| ParseError::User {
|
||||||
|
error: custom_error::UserError {
|
||||||
|
token: (start, n.into(), end),
|
||||||
|
error: custom_error::UserErrorTypes::NumberTooBigi64
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// macro for matching sequence of patterns with C as separator
|
||||||
|
Separated<T, C>: Vec<T> = {
|
||||||
|
<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
|
||||||
|
}
|
||||||
|
|
||||||
|
Separated_Empty<LP, T, C, RP>: Vec<T> = {
|
||||||
|
LP RP => vec![],
|
||||||
|
LP <v: T> RP => vec![v],
|
||||||
|
LP <v: Separated<T, C>> RP => v
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// SetParser
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PositiveSet: set::PositiveSet = {
|
||||||
|
<s: Separated_Empty<"{", PositiveLiteral, ",", "}">> =>
|
||||||
|
set::PositiveSet::from(s)
|
||||||
|
};
|
||||||
|
|
||||||
|
PositiveLiteral: (rsprocess::element::IdType, rsprocess::element::IdState) = {
|
||||||
|
"+" <t: Literal> => (translator.encode(t), rsprocess::element::IdState::Positive),
|
||||||
|
"-" <t: Literal> => (translator.encode(t), rsprocess::element::IdState::Negative),
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// LabelParser
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Label: label::PositiveLabel = {
|
||||||
|
"["
|
||||||
|
"Entities" ":" <e: PositiveSet> ","
|
||||||
|
"Context" ":" <c: PositiveSet> ","
|
||||||
|
"Reactants" ":" <r: PositiveSet> ","
|
||||||
|
"ReactantsAbsent" ":" <r_a: PositiveSet> ","
|
||||||
|
"Inhibitors" ":" <i: PositiveSet> ","
|
||||||
|
"InhibitorsPresent" ":" <i_p: PositiveSet> ","
|
||||||
|
"Products" ":" <p: PositiveSet> ","?
|
||||||
|
"]" => label::PositiveLabel::create(e, c, r, r_a, i, i_p, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// AssertParser
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
pub Assert: Box<positive_relabel::PositiveAssert> = {
|
||||||
|
"label" "{" <f: AssertTree> "}" =>
|
||||||
|
Box::new(positive_relabel::PositiveAssert{tree: f}),
|
||||||
|
};
|
||||||
|
|
||||||
|
AssertTree: positive_relabel::PositiveTree = {
|
||||||
|
<t1: AssertTree2> <t2: AssertTree> =>
|
||||||
|
positive_relabel::PositiveTree::Concat(Box::new(t1), Box::new(t2)),
|
||||||
|
<t: AssertTree2> => t,
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertTree2: positive_relabel::PositiveTree = {
|
||||||
|
#[precedence(level="1")]
|
||||||
|
"if" <e: AssertExpression>
|
||||||
|
"then" "{" <t: AssertTree> "}" ";"? =>
|
||||||
|
positive_relabel::PositiveTree::If(Box::new(e), Box::new(t)),
|
||||||
|
|
||||||
|
#[precedence(level="0")]
|
||||||
|
"if" <e: AssertExpression>
|
||||||
|
"then" "{" <t1: AssertTree> "}"
|
||||||
|
"else" "{" <t2: AssertTree> "}" ";"? =>
|
||||||
|
positive_relabel::PositiveTree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)),
|
||||||
|
|
||||||
|
"let" <v: AssertVariable> <q: AssertQualifier?> "=" <e: AssertExpression>";"
|
||||||
|
=> positive_relabel::PositiveTree::Assignment(v, q, Box::new(e)),
|
||||||
|
|
||||||
|
"return" <e: AssertExpression> ";" =>
|
||||||
|
positive_relabel::PositiveTree::Return(Box::new(e)),
|
||||||
|
|
||||||
|
"for" <v: AssertVariable> "in" <r: AssertRange> "{" <t: AssertTree> "}" ";"?
|
||||||
|
=> positive_relabel::PositiveTree::For(v, r, Box::new(t)),
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertVariable: positive_relabel::PositiveVariable = {
|
||||||
|
#[precedence(level="0")]
|
||||||
|
"label" => positive_relabel::PositiveVariable::Special(positive_relabel::Special::Label),
|
||||||
|
"edge" => positive_relabel::PositiveVariable::Special(positive_relabel::Special::Edge),
|
||||||
|
#[precedence(level="1")]
|
||||||
|
<v: Literal> => positive_relabel::PositiveVariable::Id(v),
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertExpression: positive_relabel::PositiveExpression = {
|
||||||
|
#[precedence(level="100")]
|
||||||
|
<unp: AssertUnaryPrefix> "(" <e: AssertExpression> ")" =>
|
||||||
|
positive_relabel::PositiveExpression::Unary(unp, Box::new(e)),
|
||||||
|
|
||||||
|
#[precedence(level="50")]
|
||||||
|
<e: AssertExpression> "." <uns: AssertUnarySuffix> =>
|
||||||
|
positive_relabel::PositiveExpression::Unary(uns, Box::new(e)),
|
||||||
|
|
||||||
|
#[precedence(level="100")] #[assoc(side="left")]
|
||||||
|
"(" <e1: AssertExpression> <b: AssertBinary> <e2: AssertExpression> ")" =>
|
||||||
|
positive_relabel::PositiveExpression::Binary(b, Box::new(e1), Box::new(e2)),
|
||||||
|
|
||||||
|
#[precedence(level="100")]
|
||||||
|
<b: AssertBinaryPrefix>
|
||||||
|
"(" <e1: AssertExpression> "," <e2: AssertExpression> ")" =>
|
||||||
|
positive_relabel::PositiveExpression::Binary(b, Box::new(e1), Box::new(e2)),
|
||||||
|
|
||||||
|
#[precedence(level="0")]
|
||||||
|
<t: AssertTerm> => t,
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertTerm: positive_relabel::PositiveExpression = {
|
||||||
|
"true" => positive_relabel::PositiveExpression::True,
|
||||||
|
"false" => positive_relabel::PositiveExpression::False,
|
||||||
|
|
||||||
|
<v: AssertVariable> => positive_relabel::PositiveExpression::Var(v),
|
||||||
|
|
||||||
|
// If changing IntegerType in assert.rs, also change from Num to another
|
||||||
|
// similar parser with different return type
|
||||||
|
<i: Num> => positive_relabel::PositiveExpression::Integer(i),
|
||||||
|
|
||||||
|
<lab: Label> => positive_relabel::PositiveExpression::Label(Box::new(lab)),
|
||||||
|
<set: PositiveSet> => positive_relabel::PositiveExpression::Set(set),
|
||||||
|
"'" <el: PositiveLiteral> "'" =>
|
||||||
|
positive_relabel::PositiveExpression::PositiveElement(el.into()),
|
||||||
|
|
||||||
|
// strings
|
||||||
|
PATH => positive_relabel::PositiveExpression::String(<>.trim_end_matches("\"")
|
||||||
|
.trim_start_matches("\"")
|
||||||
|
.to_string()),
|
||||||
|
|
||||||
|
// allow arbitrary parenthesis
|
||||||
|
"(" <e: AssertExpression> ")" => e,
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertRange: positive_relabel::PositiveRange = {
|
||||||
|
"{" <e: AssertExpression> "}" =>
|
||||||
|
positive_relabel::PositiveRange::IterateOverSet(Box::new(e)),
|
||||||
|
"{" <e1: AssertExpression> ".." <e2: AssertExpression> "}" =>
|
||||||
|
positive_relabel::PositiveRange::IterateInRange(Box::new(e1), Box::new(e2)),
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertUnaryPrefix: positive_relabel::PositiveUnary = {
|
||||||
|
"not" => positive_relabel::PositiveUnary::Not,
|
||||||
|
"rand" => positive_relabel::PositiveUnary::Rand,
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertUnarySuffix: positive_relabel::PositiveUnary = {
|
||||||
|
#[precedence(level="0")]
|
||||||
|
"empty" => positive_relabel::PositiveUnary::Empty,
|
||||||
|
"length" => positive_relabel::PositiveUnary::Length,
|
||||||
|
"tostr" => positive_relabel::PositiveUnary::ToStr,
|
||||||
|
"toel" => positive_relabel::PositiveUnary::ToEl,
|
||||||
|
|
||||||
|
#[precedence(level="1")]
|
||||||
|
<q: AssertQualifier> => positive_relabel::PositiveUnary::Qualifier(q),
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertQualifierRestricted: positive_relabel::QualifierRestricted = {
|
||||||
|
"Entities" => positive_relabel::QualifierRestricted::Entities,
|
||||||
|
"Context" => positive_relabel::QualifierRestricted::Context,
|
||||||
|
"Reactants" => positive_relabel::QualifierRestricted::Reactants,
|
||||||
|
"ReactantsAbsent" => positive_relabel::QualifierRestricted::ReactantsAbsent,
|
||||||
|
"Inhibitors" => positive_relabel::QualifierRestricted::Inhibitors,
|
||||||
|
"InhibitorsPresent" => positive_relabel::QualifierRestricted::InhibitorsPresent,
|
||||||
|
"Products" => positive_relabel::QualifierRestricted::Products,
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertQualifierLabel: positive_relabel::QualifierLabel = {
|
||||||
|
"AvailableEntities" => positive_relabel::QualifierLabel::AvailableEntities,
|
||||||
|
"AllReactants" => positive_relabel::QualifierLabel::AllReactants,
|
||||||
|
"AllInhibitors" => positive_relabel::QualifierLabel::AllInhibitors,
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertQualifierSystem: positive_relabel::QualifierSystem = {
|
||||||
|
"SystemEntities" => positive_relabel::QualifierSystem::Entities,
|
||||||
|
"SystemContext" => positive_relabel::QualifierSystem::Context,
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertQualifierEdge: positive_relabel::QualifierEdge = {
|
||||||
|
"source" => positive_relabel::QualifierEdge::Source,
|
||||||
|
"target" => positive_relabel::QualifierEdge::Target,
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertQualifierNode: positive_relabel::QualifierNode = {
|
||||||
|
"neighbours" => positive_relabel::QualifierNode::Neighbours,
|
||||||
|
"system" => positive_relabel::QualifierNode::System,
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertQualifier: positive_relabel::PositiveQualifier = {
|
||||||
|
<q: AssertQualifierSystem> => positive_relabel::PositiveQualifier::System(q),
|
||||||
|
<q: AssertQualifierLabel> => positive_relabel::PositiveQualifier::Label(q),
|
||||||
|
<q: AssertQualifierRestricted> => positive_relabel::PositiveQualifier::Restricted(q),
|
||||||
|
<q: AssertQualifierEdge> => positive_relabel::PositiveQualifier::Edge(q),
|
||||||
|
<q: AssertQualifierNode> => positive_relabel::PositiveQualifier::Node(q),
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertBinary: positive_relabel::PositiveBinary = {
|
||||||
|
"&&" => positive_relabel::PositiveBinary::And,
|
||||||
|
"||" => positive_relabel::PositiveBinary::Or,
|
||||||
|
"^^" => positive_relabel::PositiveBinary::Xor,
|
||||||
|
"<" => positive_relabel::PositiveBinary::Less,
|
||||||
|
"<=" => positive_relabel::PositiveBinary::LessEq,
|
||||||
|
">" => positive_relabel::PositiveBinary::More,
|
||||||
|
">=" => positive_relabel::PositiveBinary::MoreEq,
|
||||||
|
"==" => positive_relabel::PositiveBinary::Eq,
|
||||||
|
"!=" => positive_relabel::PositiveBinary::NotEq,
|
||||||
|
"+" => positive_relabel::PositiveBinary::Plus,
|
||||||
|
"-" => positive_relabel::PositiveBinary::Minus,
|
||||||
|
"*" => positive_relabel::PositiveBinary::Times,
|
||||||
|
"^" => positive_relabel::PositiveBinary::Exponential,
|
||||||
|
"/" => positive_relabel::PositiveBinary::Quotient,
|
||||||
|
"%" => positive_relabel::PositiveBinary::Reminder,
|
||||||
|
"::" => positive_relabel::PositiveBinary::Concat,
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertBinaryPrefix: positive_relabel::PositiveBinary = {
|
||||||
|
"substr" => positive_relabel::PositiveBinary::SubStr,
|
||||||
|
"min" => positive_relabel::PositiveBinary::Min,
|
||||||
|
"max" => positive_relabel::PositiveBinary::Max,
|
||||||
|
"commonsubstr" => positive_relabel::PositiveBinary::CommonSubStr,
|
||||||
|
}
|
||||||
298
grammar_separated/src/positive_grouping.lalrpop
Normal file
298
grammar_separated/src/positive_grouping.lalrpop
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
use lalrpop_util::ParseError;
|
||||||
|
|
||||||
|
use assert::positive_grouping;
|
||||||
|
use rsprocess::{set, label};
|
||||||
|
use rsprocess::translator::Translator;
|
||||||
|
use crate::custom_error;
|
||||||
|
|
||||||
|
grammar(translator: &mut Translator);
|
||||||
|
|
||||||
|
extern {
|
||||||
|
type Error = custom_error::UserError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Helpers
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// order
|
||||||
|
match {
|
||||||
|
"!", "!=", "%", "&&", "'", "(", ")", "*", "+", ",", "-", "..", "/", ":",
|
||||||
|
"::", ";", "<", "<=", "=", "==", ">", ">=", "AllInhibitors", "AllReactants",
|
||||||
|
"AvailableEntities", "Context", "Entities", "Inhibitors",
|
||||||
|
"InhibitorsPresent", "Products", "Reactants", "ReactantsAbsent",
|
||||||
|
"SystemContext", "SystemEntities", "[", "\"", "]", "^", "^^", "edge",
|
||||||
|
"else", "empty", "false", "for", "if", "in", "label", "length", "let",
|
||||||
|
"neighbours", "not", "rand", "return", "source", "system", "target", "then",
|
||||||
|
"toel", "tostr", "true", "{", "||", "}", "node",
|
||||||
|
} else {
|
||||||
|
r"[0-9]+" => NUMBER
|
||||||
|
} else {
|
||||||
|
r"([[:alpha:]])([[:word:]])*" => WORD
|
||||||
|
// r"(\p{L}|\p{Emoji})(\p{L}|\p{Emoji}|\p{Dash}|\p{N})*" => WORD,
|
||||||
|
} else {
|
||||||
|
r#""[^"]+""# => PATH, // " <- ignore comment, its for the linter in emacs
|
||||||
|
} else {
|
||||||
|
_
|
||||||
|
}
|
||||||
|
|
||||||
|
// matches words (letter followed by numbers, letters or _)
|
||||||
|
Literal: String = {
|
||||||
|
WORD => <>.into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Num: i64 = {
|
||||||
|
<sign: "-"?> <start: @L> <n: NUMBER> <end: @R> =>? {
|
||||||
|
if sign.is_some() {
|
||||||
|
i64::from_str(n)
|
||||||
|
.map(|n| -n)
|
||||||
|
.map_err(|_| ParseError::User {
|
||||||
|
error: custom_error::UserError {
|
||||||
|
token: (start, n.into(), end),
|
||||||
|
error: custom_error::UserErrorTypes::NumberTooBigi64
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
i64::from_str(n)
|
||||||
|
.map_err(|_| ParseError::User {
|
||||||
|
error: custom_error::UserError {
|
||||||
|
token: (start, n.into(), end),
|
||||||
|
error: custom_error::UserErrorTypes::NumberTooBigi64
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// macro for matching sequence of patterns with C as separator
|
||||||
|
Separated<T, C>: Vec<T> = {
|
||||||
|
<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
|
||||||
|
}
|
||||||
|
|
||||||
|
Separated_Empty<LP, T, C, RP>: Vec<T> = {
|
||||||
|
LP RP => vec![],
|
||||||
|
LP <v: T> RP => vec![v],
|
||||||
|
LP <v: Separated<T, C>> RP => v
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// SetParser
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PositiveSet: set::PositiveSet = {
|
||||||
|
<s: Separated_Empty<"{", PositiveLiteral, ",", "}">> =>
|
||||||
|
set::PositiveSet::from(s)
|
||||||
|
};
|
||||||
|
|
||||||
|
PositiveLiteral: (rsprocess::element::IdType, rsprocess::element::IdState) = {
|
||||||
|
"+" <t: Literal> => (translator.encode(t), rsprocess::element::IdState::Positive),
|
||||||
|
"-" <t: Literal> => (translator.encode(t), rsprocess::element::IdState::Negative),
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// LabelParser
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Label: label::PositiveLabel = {
|
||||||
|
"["
|
||||||
|
"Entities" ":" <e: PositiveSet> ","
|
||||||
|
"Context" ":" <c: PositiveSet> ","
|
||||||
|
"Reactants" ":" <r: PositiveSet> ","
|
||||||
|
"ReactantsAbsent" ":" <r_a: PositiveSet> ","
|
||||||
|
"Inhibitors" ":" <i: PositiveSet> ","
|
||||||
|
"InhibitorsPresent" ":" <i_p: PositiveSet> ","
|
||||||
|
"Products" ":" <p: PositiveSet> ","?
|
||||||
|
"]" => label::PositiveLabel::create(e, c, r, r_a, i, i_p, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// GroupingParser
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
pub Group: Box<positive_grouping::PositiveAssert> = {
|
||||||
|
"node" "{" <f: GroupTree> "}" =>
|
||||||
|
Box::new(positive_grouping::PositiveAssert{tree: f}),
|
||||||
|
};
|
||||||
|
|
||||||
|
GroupTree: positive_grouping::PositiveTree = {
|
||||||
|
<t1: GroupTree2> <t2: GroupTree> =>
|
||||||
|
positive_grouping::PositiveTree::Concat(Box::new(t1), Box::new(t2)),
|
||||||
|
<t: GroupTree2> => t,
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupTree2: positive_grouping::PositiveTree = {
|
||||||
|
#[precedence(level="1")]
|
||||||
|
"if" <e: GroupExpression>
|
||||||
|
"then" "{" <t: GroupTree> "}" ";"? =>
|
||||||
|
positive_grouping::PositiveTree::If(Box::new(e), Box::new(t)),
|
||||||
|
|
||||||
|
#[precedence(level="0")]
|
||||||
|
"if" <e: GroupExpression>
|
||||||
|
"then" "{" <t1: GroupTree> "}"
|
||||||
|
"else" "{" <t2: GroupTree> "}" ";"? =>
|
||||||
|
positive_grouping::PositiveTree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)),
|
||||||
|
|
||||||
|
"let" <v: GroupVariable> <q: GroupQualifier?> "=" <e: GroupExpression> ";"
|
||||||
|
=> positive_grouping::PositiveTree::Assignment(v, q, Box::new(e)),
|
||||||
|
|
||||||
|
"return" <e: GroupExpression> ";" =>
|
||||||
|
positive_grouping::PositiveTree::Return(Box::new(e)),
|
||||||
|
|
||||||
|
"for" <v: GroupVariable> "in" <r: GroupRange> "{" <t: GroupTree> "}" ";"? =>
|
||||||
|
positive_grouping::PositiveTree::For(v, r, Box::new(t)),
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupVariable: positive_grouping::PositiveVariable = {
|
||||||
|
#[precedence(level="0")]
|
||||||
|
"entities" => positive_grouping::PositiveVariable::Special(positive_grouping::Special::Entities),
|
||||||
|
"node" => positive_grouping::PositiveVariable::Special(positive_grouping::Special::Node),
|
||||||
|
#[precedence(level="1")]
|
||||||
|
<v: Literal> => positive_grouping::PositiveVariable::Id(v),
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupExpression: positive_grouping::PositiveExpression = {
|
||||||
|
#[precedence(level="100")]
|
||||||
|
<unp: GroupUnaryPrefix> "(" <e: GroupExpression> ")" =>
|
||||||
|
positive_grouping::PositiveExpression::Unary(unp, Box::new(e)),
|
||||||
|
|
||||||
|
#[precedence(level="50")]
|
||||||
|
<e: GroupExpression> "." <uns: GroupUnarySuffix> =>
|
||||||
|
positive_grouping::PositiveExpression::Unary(uns, Box::new(e)),
|
||||||
|
|
||||||
|
#[precedence(level="100")] #[assoc(side="left")]
|
||||||
|
<e1: GroupExpression> <b: GroupBinary> <e2: GroupExpression> =>
|
||||||
|
positive_grouping::PositiveExpression::Binary(b, Box::new(e1), Box::new(e2)),
|
||||||
|
|
||||||
|
#[precedence(level="100")]
|
||||||
|
<b: GroupBinaryPrefix>
|
||||||
|
"(" <e1: GroupExpression> "," <e2: GroupExpression> ")" =>
|
||||||
|
positive_grouping::PositiveExpression::Binary(b, Box::new(e1), Box::new(e2)),
|
||||||
|
|
||||||
|
#[precedence(level="0")]
|
||||||
|
<t: GroupTerm> => t,
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupTerm: positive_grouping::PositiveExpression = {
|
||||||
|
"true" => positive_grouping::PositiveExpression::True,
|
||||||
|
"false" => positive_grouping::PositiveExpression::False,
|
||||||
|
|
||||||
|
<v: GroupVariable> => positive_grouping::PositiveExpression::Var(v),
|
||||||
|
|
||||||
|
// If changing IntegerType in assert.rs, also change from Num to another
|
||||||
|
// similar parser with different return type
|
||||||
|
<i: Num> => positive_grouping::PositiveExpression::Integer(i),
|
||||||
|
|
||||||
|
<lab: Label> => positive_grouping::PositiveExpression::Label(Box::new(lab)),
|
||||||
|
<set: PositiveSet> => positive_grouping::PositiveExpression::Set(set),
|
||||||
|
"'" <el: PositiveLiteral> "'" =>
|
||||||
|
positive_grouping::PositiveExpression::PositiveElement(el.into()),
|
||||||
|
|
||||||
|
// strings
|
||||||
|
PATH => positive_grouping::PositiveExpression::String(<>.trim_end_matches("\"")
|
||||||
|
.trim_start_matches("\"")
|
||||||
|
.to_string()),
|
||||||
|
// allow arbitrary parenthesis
|
||||||
|
"(" <e: GroupExpression> ")" => e,
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupRange: positive_grouping::PositiveRange = {
|
||||||
|
"{" <e: GroupExpression> "}" =>
|
||||||
|
positive_grouping::PositiveRange::IterateOverSet(Box::new(e)),
|
||||||
|
"{" <e1: GroupExpression> ".." <e2: GroupExpression> "}" =>
|
||||||
|
positive_grouping::PositiveRange::IterateInRange(Box::new(e1), Box::new(e2)),
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupUnaryPrefix: positive_grouping::PositiveUnary = {
|
||||||
|
"not" => positive_grouping::PositiveUnary::Not,
|
||||||
|
"rand" => positive_grouping::PositiveUnary::Rand,
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupUnarySuffix: positive_grouping::PositiveUnary = {
|
||||||
|
#[precedence(level="0")]
|
||||||
|
"empty" => positive_grouping::PositiveUnary::Empty,
|
||||||
|
"length" => positive_grouping::PositiveUnary::Length,
|
||||||
|
"tostr" => positive_grouping::PositiveUnary::ToStr,
|
||||||
|
"toel" => positive_grouping::PositiveUnary::ToEl,
|
||||||
|
|
||||||
|
#[precedence(level="1")]
|
||||||
|
<q: GroupQualifier> => positive_grouping::PositiveUnary::Qualifier(q),
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupQualifierRestricted: positive_grouping::QualifierRestricted = {
|
||||||
|
"Entities" => positive_grouping::QualifierRestricted::Entities,
|
||||||
|
"Context" => positive_grouping::QualifierRestricted::Context,
|
||||||
|
"Reactants" => positive_grouping::QualifierRestricted::Reactants,
|
||||||
|
"ReactantsAbsent" => positive_grouping::QualifierRestricted::ReactantsAbsent,
|
||||||
|
"Inhibitors" => positive_grouping::QualifierRestricted::Inhibitors,
|
||||||
|
"InhibitorsPresent" => positive_grouping::QualifierRestricted::InhibitorsPresent,
|
||||||
|
"Products" => positive_grouping::QualifierRestricted::Products,
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupQualifierLabel: positive_grouping::QualifierLabel = {
|
||||||
|
"AvailableEntities" => positive_grouping::QualifierLabel::AvailableEntities,
|
||||||
|
"AllReactants" => positive_grouping::QualifierLabel::AllReactants,
|
||||||
|
"AllInhibitors" => positive_grouping::QualifierLabel::AllInhibitors,
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupQualifierSystem: positive_grouping::QualifierSystem = {
|
||||||
|
"SystemEntities" => positive_grouping::QualifierSystem::Entities,
|
||||||
|
"SystemContext" => positive_grouping::QualifierSystem::Context,
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupQualifierEdge: positive_grouping::QualifierEdge = {
|
||||||
|
"source" => positive_grouping::QualifierEdge::Source,
|
||||||
|
"target" => positive_grouping::QualifierEdge::Target,
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupQualifierNode: positive_grouping::QualifierNode = {
|
||||||
|
"neighbours" => positive_grouping::QualifierNode::Neighbours,
|
||||||
|
"system" => positive_grouping::QualifierNode::System,
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupQualifier: positive_grouping::PositiveQualifier = {
|
||||||
|
<q: GroupQualifierSystem> => positive_grouping::PositiveQualifier::System(q),
|
||||||
|
<q: GroupQualifierLabel> => positive_grouping::PositiveQualifier::Label(q),
|
||||||
|
<q: GroupQualifierRestricted> => positive_grouping::PositiveQualifier::Restricted(q),
|
||||||
|
<q: GroupQualifierEdge> => positive_grouping::PositiveQualifier::Edge(q),
|
||||||
|
<q: GroupQualifierNode> => positive_grouping::PositiveQualifier::Node(q),
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupBinary: positive_grouping::PositiveBinary = {
|
||||||
|
"&&" => positive_grouping::PositiveBinary::And,
|
||||||
|
"||" => positive_grouping::PositiveBinary::Or,
|
||||||
|
"^^" => positive_grouping::PositiveBinary::Xor,
|
||||||
|
"<" => positive_grouping::PositiveBinary::Less,
|
||||||
|
"<=" => positive_grouping::PositiveBinary::LessEq,
|
||||||
|
">" => positive_grouping::PositiveBinary::More,
|
||||||
|
">=" => positive_grouping::PositiveBinary::MoreEq,
|
||||||
|
"==" => positive_grouping::PositiveBinary::Eq,
|
||||||
|
"!=" => positive_grouping::PositiveBinary::NotEq,
|
||||||
|
"+" => positive_grouping::PositiveBinary::Plus,
|
||||||
|
"-" => positive_grouping::PositiveBinary::Minus,
|
||||||
|
"*" => positive_grouping::PositiveBinary::Times,
|
||||||
|
"^" => positive_grouping::PositiveBinary::Exponential,
|
||||||
|
"/" => positive_grouping::PositiveBinary::Quotient,
|
||||||
|
"%" => positive_grouping::PositiveBinary::Reminder,
|
||||||
|
"::" => positive_grouping::PositiveBinary::Concat,
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupBinaryPrefix: positive_grouping::PositiveBinary = {
|
||||||
|
"substr" => positive_grouping::PositiveBinary::SubStr,
|
||||||
|
"min" => positive_grouping::PositiveBinary::Min,
|
||||||
|
"max" => positive_grouping::PositiveBinary::Max,
|
||||||
|
"commonsubstr" => positive_grouping::PositiveBinary::CommonSubStr,
|
||||||
|
}
|
||||||
@ -7,13 +7,16 @@ use petgraph::{Directed, Graph};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::element::IdType;
|
use super::element::IdType;
|
||||||
use super::label::Label;
|
use super::label::{Label, PositiveLabel};
|
||||||
use super::set::{BasicSet, Set};
|
use super::set::{BasicSet, Set};
|
||||||
use super::system::System;
|
use super::system::{PositiveSystem, System};
|
||||||
use super::translator;
|
use super::translator;
|
||||||
|
|
||||||
pub type SystemGraph = Graph<System, Label, Directed, u32>;
|
pub type SystemGraph = Graph<System, Label, Directed, u32>;
|
||||||
|
|
||||||
|
pub type PositiveSystemGraph = Graph<PositiveSystem, PositiveLabel, Directed, u32>;
|
||||||
|
|
||||||
|
|
||||||
fn common_system_entities(graph: &SystemGraph) -> Set {
|
fn common_system_entities(graph: &SystemGraph) -> Set {
|
||||||
graph
|
graph
|
||||||
.node_references()
|
.node_references()
|
||||||
|
|||||||
Reference in New Issue
Block a user