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