diff --git a/grammar_separated/src/boolean.lalrpop b/grammar_separated/src/boolean.lalrpop new file mode 100644 index 0000000..eb4bedd --- /dev/null +++ b/grammar_separated/src/boolean.lalrpop @@ -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 = { + =>? { + 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 = { + =>? 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: Vec = { + C)+> => match e { + None => v, + Some(e) => { + v.push(e); + v + } + } +}; + +Separated_Or: Vec = { + => vec![v], + > => v +} + +Separated_Empty: Vec = { + LP RP => vec![], + LP RP => vec![v], + LP > RP => v +} + +// ----------------------------------------------------------------------------- +// BooleanNetwork Parser +// ----------------------------------------------------------------------------- + +pub BooleanFunction: BooleanFunction = { + => + if o { BooleanFunction::And(Box::new(b1), Box::new(b2)) } + else { BooleanFunction::Or(Box::new(b1), Box::new(b2)) }, + + => b +} + +BoolOperator: bool = { + "AND" => true, + "OR" => false, +} + +BooleanFunctionTerm: BooleanFunction = { + "True" => BooleanFunction::True, + "False" => BooleanFunction::False, + => BooleanFunction::Variable(translator.encode(v)), + + "NOT" => BooleanFunction::Not(Box::new(b)), + + "(" ")" => b +} + + +pub BooleanNetwork: BooleanNetwork = { + => BooleanNetwork { + initial_state: Default::default(), + update_rules: BTreeMap::from_iter(ass), + } +} + +BooleanAssignment: (IdType, BooleanFunction) = { + "=" => (translator.encode(v), b), +} diff --git a/grammar_separated/src/lib.rs b/grammar_separated/src/lib.rs index bbdf6a4..31f10fd 100644 --- a/grammar_separated/src/lib.rs +++ b/grammar_separated/src/lib.rs @@ -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")); +} diff --git a/rsprocess/src/boolean.rs b/rsprocess/src/boolean.rs index 5999b4e..535ab95 100644 --- a/rsprocess/src/boolean.rs +++ b/rsprocess/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, pub update_rules: BTreeMap, @@ -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) )?;