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 {
|
||||
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::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)
|
||||
)?;
|
||||
|
||||
Reference in New Issue
Block a user