Parser for Boolean Networks

This commit is contained in:
elvis
2025-12-22 14:47:38 +01:00
parent 25dfe9147d
commit 7062135a61
3 changed files with 171 additions and 15 deletions

View File

@ -0,0 +1,145 @@
use std::collections::BTreeMap;
use std::str::FromStr;
use lalrpop_util::ParseError;
use rsprocess::translator::Translator;
use rsprocess::element::IdType;
use rsprocess::boolean::{BooleanFunction, BooleanNetwork};
use crate::custom_error;
grammar(translator: &mut Translator);
extern {
type Error = custom_error::UserError;
}
// -----------------------------------------------------------------------------
// Helpers
// -----------------------------------------------------------------------------
// order
match {
"\"", "True", "False", "(", ")", "NOT", "AND", "OR",
} 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(),
};
LiteralProcess: String = {
Literal => <>,
"True" => <>.into(),
"False" => <>.into(),
"NOT" => <>.into(),
"AND" => <>.into(),
"OR" => <>.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
}
})
}
}
};
NumUsize: usize = {
<start: @L> <n: NUMBER> <end: @R> =>? usize::from_str(n)
.map_err(|_| ParseError::User {
error: custom_error::UserError {
token: (start, n.into(), end),
error: custom_error::UserErrorTypes::NumberTooBigUsize
}
})
};
Path: String = {
PATH => <>.trim_end_matches("\"").trim_start_matches("\"").to_string()
};
// 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
}
// -----------------------------------------------------------------------------
// BooleanNetwork Parser
// -----------------------------------------------------------------------------
pub BooleanFunction: BooleanFunction = {
<b1: BooleanFunction> <o: BoolOperator> <b2: BooleanFunctionTerm> =>
if o { BooleanFunction::And(Box::new(b1), Box::new(b2)) }
else { BooleanFunction::Or(Box::new(b1), Box::new(b2)) },
<b: BooleanFunctionTerm> => b
}
BoolOperator: bool = {
"AND" => true,
"OR" => false,
}
BooleanFunctionTerm: BooleanFunction = {
"True" => BooleanFunction::True,
"False" => BooleanFunction::False,
<v: Literal> => BooleanFunction::Variable(translator.encode(v)),
"NOT" <b: BooleanFunctionTerm> => BooleanFunction::Not(Box::new(b)),
"(" <b: BooleanFunction> ")" => b
}
pub BooleanNetwork: BooleanNetwork = {
<ass: BooleanAssignment*> => BooleanNetwork {
initial_state: Default::default(),
update_rules: BTreeMap::from_iter(ass),
}
}
BooleanAssignment: (IdType, BooleanFunction) = {
<v: Literal> "=" <b: BooleanFunction> => (translator.encode(v), b),
}

View File

@ -69,3 +69,14 @@ pub mod positive_grouping {
pub mod instructions { pub mod instructions {
include!(concat!(env!("OUT_DIR"), "/src/instructions.rs")); include!(concat!(env!("OUT_DIR"), "/src/instructions.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 boolean {
include!(concat!(env!("OUT_DIR"), "/src/boolean.rs"));
}

View File

@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
use crate::element::IdType; use crate::element::IdType;
use crate::translator::{Formatter, PrintableWithTranslator}; use crate::translator::{Formatter, PrintableWithTranslator};
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Default, Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum BooleanFunction { pub enum BooleanFunction {
#[default] #[default]
False, False,
@ -78,17 +78,17 @@ impl PrintableWithTranslator for BooleanFunction {
| False => write!(f, "False"), | False => write!(f, "False"),
| True => write!(f, "True"), | True => write!(f, "True"),
| Not(next) => | Not(next) =>
write!(f, "Not({})", Formatter::from(translator, &**next)), write!(f, "NOT({})", Formatter::from(translator, &**next)),
| Variable(x) => write!(f, "{})", Formatter::from(translator, x)), | Variable(x) => write!(f, "{}", Formatter::from(translator, x)),
| And(next1, next2) => write!( | And(next1, next2) => write!(
f, f,
"And({}, {})", "({} AND {})",
Formatter::from(translator, &**next1), Formatter::from(translator, &**next1),
Formatter::from(translator, &**next2) Formatter::from(translator, &**next2)
), ),
| Or(next1, next2) => write!( | Or(next1, next2) => write!(
f, f,
"Or({}, {})", "({} OR {})",
Formatter::from(translator, &**next1), Formatter::from(translator, &**next1),
Formatter::from(translator, &**next2) Formatter::from(translator, &**next2)
), ),
@ -151,13 +151,13 @@ impl PrintableWithTranslator for CNFLiteral {
) -> std::fmt::Result { ) -> std::fmt::Result {
use CNFLiteral::*; use CNFLiteral::*;
match self { match self {
| False => write!(f, "F"), | False => write!(f, "False"),
| True => write!(f, "T"), | True => write!(f, "True"),
| Variable { positive, variable } => | Variable { positive, variable } =>
if *positive { if *positive {
write!(f, "{}", Formatter::from(translator, variable)) write!(f, "{}", Formatter::from(translator, variable))
} else { } else {
write!(f, "-{}", Formatter::from(translator, variable)) write!(f, "NOT({})", Formatter::from(translator, variable))
}, },
} }
} }
@ -362,13 +362,13 @@ impl PrintableWithTranslator for DNFLiteral {
) -> std::fmt::Result { ) -> std::fmt::Result {
use DNFLiteral::*; use DNFLiteral::*;
match self { match self {
| False => write!(f, "F"), | False => write!(f, "False"),
| True => write!(f, "T"), | True => write!(f, "True"),
| Variable { positive, variable } => | Variable { positive, variable } =>
if *positive { if *positive {
write!(f, "{}", Formatter::from(translator, variable)) write!(f, "{}", Formatter::from(translator, variable))
} else { } else {
write!(f, "-{}", Formatter::from(translator, variable)) write!(f, "NOT({})", Formatter::from(translator, variable))
}, },
} }
} }
@ -522,7 +522,7 @@ impl DNFBooleanFunction {
// Boolean Networks // Boolean Networks
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#[derive(Default, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Default, Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct BooleanNetwork { pub struct BooleanNetwork {
pub initial_state: BTreeMap<IdType, bool>, pub initial_state: BTreeMap<IdType, bool>,
pub update_rules: BTreeMap<IdType, BooleanFunction>, pub update_rules: BTreeMap<IdType, BooleanFunction>,
@ -553,7 +553,7 @@ impl PrintableWithTranslator for BooleanNetwork {
write!(f, "Initial State: ")?; write!(f, "Initial State: ")?;
let mut it = self.initial_state.iter().peekable(); let mut it = self.initial_state.iter().peekable();
while let Some((x, b)) = it.next() { while let Some((x, b)) = it.next() {
write!(f, "({} -> {})", Formatter::from(translator, x), b)?; write!(f, "({} = {})", Formatter::from(translator, x), b)?;
if it.peek().is_some() { if it.peek().is_some() {
write!(f, ",")?; write!(f, ",")?;
} }
@ -564,9 +564,9 @@ impl PrintableWithTranslator for BooleanNetwork {
writeln!(f, "Update Rules:")?; writeln!(f, "Update Rules:")?;
for (x, bf) in self.update_rules.iter() { for (x, bf) in self.update_rules.iter() {
write!( writeln!(
f, f,
"\t{} -> {}", "\t{} = {}",
Formatter::from(translator, x), Formatter::from(translator, x),
Formatter::from(translator, bf) Formatter::from(translator, bf)
)?; )?;