diff --git a/src/main.rs b/src/main.rs index eea4fdf..912121c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,11 @@ +use reactionsystems::rsprocess::presets; + fn main() { // let now = std::time::Instant::now(); // println!("{}", now.elapsed().as_micros()); - let (g, t) = reactionsystems::rsprocess::presets::digraph("testing/first.system".into()).unwrap(); - - reactionsystems::rsprocess::presets::dot(&g, &t, "testing/first.dot".into()).unwrap(); + match presets::run("testing/first.system".into()) { + Ok(_) => {}, + Err(e) => {println!("{e}")} + } } diff --git a/src/rsprocess/grammar.lalrpop b/src/rsprocess/grammar.lalrpop index bbc8673..bfbc82d 100644 --- a/src/rsprocess/grammar.lalrpop +++ b/src/rsprocess/grammar.lalrpop @@ -10,6 +10,8 @@ use crate::rsprocess::structure::{RSset, RSsystem, RSreaction}; use crate::rsprocess::translator::{Translator, IdType}; +use crate::rsprocess::presets::Instructions; +use crate::rsprocess::presets; grammar(translator: &mut Translator); @@ -19,6 +21,7 @@ grammar(translator: &mut Translator); // order match { + ".", ",", ";", "nill", "{", "}", "[", "]", @@ -27,12 +30,21 @@ match { "r:", "i:", "p:", "-", "^", "true", "false", - "inW", "inR", "inI", "inP" + "inW", "inR", "inI", "inP", + "Environment", "Initial Entities", "Context", "Reactions", + "Weights", "Sets", + "Print", "Save", + "Dot", "GraphML", "Serialize", + "Stats", "Target", "Run", "Loop", "Frequency", "LimitFrequency", + "FastFrequency", "Digraph", + "Deserialize" } else { r"[0-9]+" => NUMBER } else { // r"([[:alpha:]]|\p{Emoji})([[:word:]]|\p{Emoji})*" => WORD - r"(\p{L}|\p{Emoji})(\p{L}|\p{Emoji}|\p{Dash}|\p{N})*" => WORD + r"(\p{L}|\p{Emoji})(\p{L}|\p{Emoji}|\p{Dash}|\p{N})*" => WORD, +} else { + r#"".*""# => PATH, } else { _ } @@ -49,6 +61,10 @@ Num: i64 = { .map_err(|_| ParseError::User { error: "Number is too big" }) }; +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 { @@ -181,18 +197,19 @@ Formula_BHML: RSBHML = { }; -// ----------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- // File Parsing -// ----------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- + // system // a system is an environment, a set of entities as initial state, a context and // a set of reaction rules. pub System: RSsystem = { - "Environment:" - "Initial Entities:" - "Context:" - "Reactions:" + "Environment" ":" + "Initial Entities" ":" + "Context" ":" + "Reactions" ":" => RSsystem::from(delta.into(), available_entities, context_process, @@ -204,7 +221,68 @@ pub System: RSsystem = { // entities of equal length. pub Experiment: (Vec, Vec) = { - "Weights:" > - "Sets:" > + "Weights" ":" > + "Sets" ":" > => (w.into_iter().map(|x| x as u32).collect::>(), s), } + + + +// Instruction Parsing + +Helper_SO: presets::SaveOptions = { + "Print" => + presets::SaveOptions {print: true, save: None}, + "Save" "(" ")" => + presets::SaveOptions {print: false, save: Some(vec![p])} +} + +SaveOptions: presets::SaveOptions = { + > => { + if let Some(a) = + p.into_iter() + .reduce(|mut acc, mut e| {acc.combine(&mut e); acc}) { + a + } else { + presets::SaveOptions::default() + } + } +} + +GraphSaveOptions: presets::GraphSaveOptions = { + "Dot" ">" => + presets::GraphSaveOptions::Dot { so }, + "GraphML" ">" => + presets::GraphSaveOptions::GraphML { so }, + "Serialize" "(" ")" => + presets::GraphSaveOptions::Serialize { path }, +} + + +Instruction: presets::Instruction = { + "Stats" ">" => + presets::Instruction::Stats { so }, + "Target" ">" => + presets::Instruction::Target { so }, + "Run" ">" => + presets::Instruction::Run { so }, + "Loop" "(" ")" ">" => + presets::Instruction::Loop { symbol, so }, + "Frequency" "(" ")" ">" => + presets::Instruction::Frequency { experiment: p, so }, + "LimitFrequency" "(" ")" ">" => + presets::Instruction::LimitFrequency { experiment: p, so }, + "FastFrequency" "(" ")" ">" => + presets::Instruction::FastFrequency { experiment: p, so }, + "Digraph" ">" > => + presets::Instruction::Digraph { gso }, +} + +pub Run: presets::Instructions = { + > => + Instructions { system: presets::System::RSsystem { sys }, + instructions: instr }, + "Deserialize" "(" ")" > => + Instructions { system: presets::System::Deserialize { path }, + instructions: instr }, +} diff --git a/src/rsprocess/presets.rs b/src/rsprocess/presets.rs index 252b9b0..a1be429 100644 --- a/src/rsprocess/presets.rs +++ b/src/rsprocess/presets.rs @@ -1,6 +1,7 @@ //! Module that holds useful presets for interacting with other modules. use std::env; +use std::fmt::Display; use std::fs; use std::io; use std::io::prelude::*; @@ -18,6 +19,75 @@ use super::structure::{RSset, RSsystem}; use super::translator::Translator; use super::*; + +// ----------------------------------------------------------------------------- +// Structures +// ----------------------------------------------------------------------------- + +#[derive(Debug)] +pub struct SaveOptions { + pub print: bool, + pub save: Option> +} + +impl SaveOptions { + pub fn combine(&mut self, other: &mut Self) { + self.print = self.print || other.print; + match (self.save.is_some(), other.save.is_some()) { + (false, false) | + (true, false) => {} + (false, true) => { + self.save = other.save.to_owned(); + }, + (true, true) => { + self.save + .as_mut() + .unwrap() + .append(other.save.as_mut().unwrap());} + } + } + pub fn new() -> Self { + SaveOptions { print: false, save: None } + } +} + +impl Default for SaveOptions { + fn default() -> Self { + SaveOptions::new() + } +} + +#[derive(Debug)] +pub enum GraphSaveOptions { + Dot { so: SaveOptions }, + GraphML { so: SaveOptions }, + Serialize { path: String } +} + +#[derive(Debug)] +pub enum Instruction { + Stats { so: SaveOptions }, + Target { so: SaveOptions }, + Run { so: SaveOptions }, + Loop { symbol: String, so: SaveOptions }, + Frequency { experiment: String, so: SaveOptions }, + LimitFrequency { experiment: String, so: SaveOptions }, + FastFrequency { experiment: String, so: SaveOptions }, + Digraph { gso: Vec }, +} + +#[derive(Debug)] +pub enum System { + Deserialize { path: String }, + RSsystem { sys: RSsystem } +} + +#[derive(Debug)] +pub struct Instructions { + pub system: System, + pub instructions: Vec +} + // ----------------------------------------------------------------------------- // Helper Functions // ----------------------------------------------------------------------------- @@ -55,6 +125,77 @@ where Ok(result) } +fn reformat_error( + e: ParseError +) -> Result +where + T: Display +{ + match e { + ParseError::ExtraToken { token: (l, t, r) } => { + Err(format!( + "Unexpected token \"{t}\" \ + between positions {l} and {r}." + )) + }, + ParseError::UnrecognizedEof { location: _, expected: _ } => { + Err("End of file encountered while parsing.".into()) + }, + ParseError::InvalidToken { location } => { + Err(format!("Invalid token at position {location}.")) + }, + ParseError::UnrecognizedToken { token: (l, t, r), expected } + => { + Err(format!( + "Unrecognized token \"{t}\" \ + between positions {l} and {r}. Expected: {expected:?}" + )) + }, + ParseError::User { error } => { + Err(error.to_string()) + } + } +} + +fn parser_system( + translator: &mut Translator, + contents: String +) -> Result +{ + match grammar::SystemParser::new() + .parse(translator, &contents) + { + Ok(sys) => Ok(sys), + Err(e) => reformat_error(e) + } +} + +fn parser_experiment( + translator: &mut Translator, + contents: String +) -> Result<(Vec, Vec), String> +{ + match grammar::ExperimentParser::new() + .parse(translator, &contents) + { + Ok(sys) => Ok(sys), + Err(e) => reformat_error(e) + } +} + +fn parser_instructions( + translator: &mut Translator, + contents: String +) -> Result +{ + match grammar::RunParser::new() + .parse(translator, &contents) + { + Ok(sys) => Ok(sys), + Err(e) => reformat_error(e) + } +} + fn save_file( contents: String, path_string: String, @@ -81,85 +222,9 @@ fn save_file( Ok(()) } -fn parser_system( - translator: &mut Translator, - contents: String -) -> Result -{ - match grammar::SystemParser::new() - .parse(translator, &contents) - { - Ok(sys) => Ok(sys), - Err(e) => { - match e { - ParseError::ExtraToken { token: (l, t, r) } => { - Err(format!( - "Unexpected token \"{t}\" \ - between positions {l} and {r}." - )) - }, - ParseError::UnrecognizedEof { location: _, expected: _ } => { - Err("End of file encountered while parsing.".into()) - }, - ParseError::InvalidToken { location } => { - Err(format!("Invalid token at position {location}.")) - }, - ParseError::UnrecognizedToken { token: (l, t, r), expected: _ } - => { - Err(format!( - "Unexpected token \"{t}\" \ - between positions {l} and {r}." - )) - }, - ParseError::User { error } => { - Err(error.to_string()) - } - } - } - } -} - -fn parser_experiment( - translator: &mut Translator, - contents: String -) -> Result<(Vec, Vec), String> -{ - match grammar::ExperimentParser::new() - .parse(translator, &contents) - { - Ok(sys) => Ok(sys), - Err(e) => { - match e { - ParseError::ExtraToken { token: (l, t, r) } => { - Err(format!( - "Unexpected token \"{t}\" \ - between positions {l} and {r}." - )) - }, - ParseError::UnrecognizedEof { location: _, expected: _ } => { - Err("End of file encountered while parsing.".into()) - }, - ParseError::InvalidToken { location } => { - Err(format!("Invalid token at position {location}.")) - }, - ParseError::UnrecognizedToken { token: (l, t, r), expected: _ } - => { - Err(format!( - "Unexpected token \"{t}\" \ - between positions {l} and {r}." - )) - }, - ParseError::User { error } => { - Err(error.to_string()) - } - } - } - } -} - // ----------------------------------------------------------------------------- -// Methods +// main_do // ----------------------------------------------------------------------------- /// Prints statistics of the system. @@ -195,10 +260,11 @@ pub fn target(path_string: String) -> Result<(), String> { Ok(()) } + /// Finds the list of traversed states in a (deterministic) terminating /// reaction. /// equivalent to main_do(run,Es) -pub fn run(path_string: String) -> Result<(), String> { +pub fn traversed(path_string: String) -> Result<(), String> { let mut translator = Translator::new(); let system = read_file(&mut translator, path_string, parser_system)?; @@ -217,7 +283,7 @@ pub fn run(path_string: String) -> Result<(), String> { /// Finds the looping list of states in a reaction system with a perpetual -/// context IMPORTANT: for loops, we assume Delta defines the process constant +/// context. IMPORTANT: for loops, we assume Delta defines the process constant /// x = Q.x and the context process is x . /// equivalent to main_do(loop,Es) pub fn hoop(path_string: String) -> Result<(), String> { @@ -347,9 +413,9 @@ pub fn digraph( } -// ---------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // Output Functions -// ---------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- /// Writes the specified graph to a file in .dot format. pub fn dot( @@ -486,3 +552,18 @@ pub fn deserialize( Err(_) => Err("Error during deserialization.".into()) } } + + +//------------------------------------------------------------------------------ +// Interpreting Instructions +//------------------------------------------------------------------------------ + +pub fn run(path: String) -> Result<(), String> { + let mut translator = Translator::new(); + + let instructions = read_file(&mut translator, path, parser_instructions)?; + + println!("{:?}", instructions); + + Ok(()) +} diff --git a/testing/first.system b/testing/first.system index bc19b3a..9f486e0 100644 --- a/testing/first.system +++ b/testing/first.system @@ -1,4 +1,9 @@ -Environment: [x = {a}.y, y =({a}.x + {b}.y)] +Environment: [x = {a}.y, y =({a}.x + {b}.y) ] Initial Entities: {a, b} Context: [({a,b}.{a}.{a,c}.x + {a,b}.{a}.{a}.nill)] Reactions: ([{a,b}, {c}, {b}]) + +Run > Print; Save("testing/asd"), +LimitFrequency("testing/first.experiment") > Print, +Digraph > Dot > Save("testing/asddd") + | Serialize("testing/asdd")