Parser for Boolean Networks
This commit is contained in:
145
grammar_separated/src/boolean.lalrpop
Normal file
145
grammar_separated/src/boolean.lalrpop
Normal 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),
|
||||||
|
}
|
||||||
@ -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"));
|
||||||
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
)?;
|
)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user