Files
ReactionSystems/src/rsprocess/grammar.lalrpop

289 lines
9.0 KiB
Plaintext
Raw Normal View History

2025-05-21 00:03:36 +02:00
use std::rc::Rc;
2025-05-14 11:42:19 +02:00
use std::str::FromStr;
use lalrpop_util::ParseError;
use crate::rsprocess::structure::{RSset,
RSprocess,
RSenvironment,
RSassert,
RSassertOp,
RSBHML,
RSsystem,
RSreaction};
2025-06-16 14:46:04 +02:00
use crate::rsprocess::translator::{Translator, IdType};
use crate::rsprocess::presets::Instructions;
use crate::rsprocess::presets;
2025-05-14 11:42:19 +02:00
2025-06-16 14:46:04 +02:00
grammar(translator: &mut Translator);
2025-05-14 11:42:19 +02:00
// -----------------------------------------------------------------------------
// Helpers
// -----------------------------------------------------------------------------
2025-07-03 16:28:28 +02:00
// order
match {
".", ",", ";",
2025-07-03 23:44:10 +02:00
"nill",
"{", "}",
"[", "]",
"(", ")",
"<", ">",
"r:", "i:", "p:",
"-", "^",
"true", "false",
"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"
2025-07-03 23:44:10 +02:00
} else {
2025-07-03 16:28:28 +02:00
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,
} else {
r#"".*""# => PATH,
2025-07-03 16:28:28 +02:00
} else {
_
}
2025-05-14 12:14:13 +02:00
// matches words (letter followed by numbers, letters or _)
2025-07-03 16:28:28 +02:00
Literal: String = {
WORD => <>.to_string()
};
2025-05-14 11:42:19 +02:00
2025-05-14 12:14:13 +02:00
// all numbers are i64
2025-05-14 11:42:19 +02:00
Num: i64 = {
2025-07-03 16:28:28 +02:00
NUMBER =>? i64::from_str(<>)
.map_err(|_| ParseError::User { error: "Number is too big" })
2025-05-14 11:42:19 +02:00
};
Path: String = {
PATH => <>.trim_end_matches("\"").trim_start_matches("\"").to_string()
};
2025-05-14 12:14:13 +02:00
// macro for matching sequence of patterns with C as separator
2025-07-02 17:27:36 +02:00
Separated<T, C>: Vec<T> = {
2025-05-14 11:42:19 +02:00
<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
}
// -----------------------------------------------------------------------------
// SetParser
// -----------------------------------------------------------------------------
2025-06-16 14:46:04 +02:00
pub Set: RSset = {
2025-05-14 11:42:19 +02:00
<s: Set_of_entities> => s
};
2025-06-16 14:46:04 +02:00
Set_of_entities: RSset = {
2025-05-19 00:10:23 +02:00
"{" "}" => RSset::from(vec![]),
"{" <t: Separated_Or<Literal, ",">> "}" =>
2025-06-18 11:28:04 +02:00
RSset::from(t.into_iter().map(|t| translator.encode(t)).collect::<Vec<_>>())
2025-05-19 00:10:23 +02:00
};
2025-06-12 16:23:39 +02:00
// -----------------------------------------------------------------------------
// ReactionParser
// -----------------------------------------------------------------------------
pub Reactions: Vec<RSreaction> = {
"(" ")" => vec![],
"(" <s: Separated_Or<Reaction, ";">> ")" => s
}
Reaction: RSreaction = {
"[" <r: Set> "," <i: Set> "," <p: Set> "]" => RSreaction::from(r, i, p),
2025-07-01 19:22:50 +02:00
"[" "r:" <r: Set> "," "i:" <i: Set> "," "p:" <p: Set> "]" =>
RSreaction::from(r, i, p),
}
// -----------------------------------------------------------------------------
// ContextParser
// -----------------------------------------------------------------------------
pub Context: RSprocess = {
"[" "]" => RSprocess::NondeterministicChoice{ children: vec![] },
"[" <t: Separated_Or<Boxed_CTX_process, ",">> "]" =>
RSprocess::NondeterministicChoice{ children: t }
2025-05-14 11:42:19 +02:00
};
2025-06-16 14:46:04 +02:00
Boxed_CTX_process: Rc<RSprocess> = {
2025-05-21 00:03:36 +02:00
<t: CTX_process> => Rc::new(t)
}
2025-06-16 14:46:04 +02:00
CTX_process: RSprocess = {
2025-07-03 23:44:10 +02:00
"nill" => RSprocess::Nill,
2025-05-19 00:10:23 +02:00
<c: Set_of_entities> "." <k: CTX_process> =>
2025-05-21 00:03:36 +02:00
RSprocess::EntitySet{ entities: c, next_process: Rc::new(k) },
2025-05-14 11:42:19 +02:00
"(" <k: CTX_process> ")" => k,
2025-07-02 17:27:36 +02:00
"(" <k: Separated<CTX_process, "+">> ")" =>
2025-07-01 19:22:50 +02:00
RSprocess::Summation{
children: k.into_iter().map(Rc::new).collect::<Vec<_>>()
},
2025-05-19 00:10:23 +02:00
"<" <n: Num> <k1: CTX_process> ">" "." <k: CTX_process> =>
RSprocess::WaitEntity{ repeat: n,
2025-05-21 00:03:36 +02:00
repeated_process: Rc::new(k1),
2025-07-01 19:22:50 +02:00
next_process: Rc::new(k) },
2025-05-19 00:10:23 +02:00
<identifier: Literal> =>
2025-07-01 19:22:50 +02:00
RSprocess::RecursiveIdentifier{
identifier: translator.encode(identifier)
}
2025-05-14 11:42:19 +02:00
};
// -----------------------------------------------------------------------------
// EnvironmentParser
// -----------------------------------------------------------------------------
2025-06-16 14:46:04 +02:00
pub Environment: Box<RSenvironment> = {
2025-05-14 11:42:19 +02:00
"[" "]" => Box::new(RSenvironment::new()),
"[" <t: Separated_Or<Env_term, ",">> "]" => Box::new(RSenvironment::from(t))
2025-05-14 11:42:19 +02:00
};
2025-06-16 14:46:04 +02:00
Env_term: (IdType, RSprocess) = {
<identifier: Literal> "=" <k: CTX_process> =>
2025-06-18 11:28:04 +02:00
(translator.encode(identifier), k)
2025-05-14 11:42:19 +02:00
};
// -----------------------------------------------------------------------------
// AssertParser
// -----------------------------------------------------------------------------
2025-06-16 14:46:04 +02:00
pub Assert: Box<RSassert> = {
2025-05-14 11:42:19 +02:00
<f: Formula_Assert> => Box::new(f)
};
2025-06-16 14:46:04 +02:00
Formula_Assert: RSassert = {
2025-05-14 11:42:19 +02:00
"-" <f: Formula_Assert> => RSassert::Not(Box::new(f)),
2025-05-19 00:10:23 +02:00
"(" <f1: Formula_Assert> "^" <f2: Formula_Assert> ")" =>
RSassert::Xor(Box::new(f1), Box::new(f2)),
2025-07-02 17:27:36 +02:00
"(" <f: Separated<Formula_Assert, "\\/">> ")" => RSassert::Or(f),
"(" <f: Separated<Formula_Assert, "/\\">> ")" => RSassert::And(f),
2025-05-14 11:42:19 +02:00
<c: Set_of_entities> "inW" => RSassert::Sub(c, RSassertOp::InW),
<c: Set_of_entities> "inR" => RSassert::Sub(c, RSassertOp::InR),
<c: Set_of_entities> "inI" => RSassert::Sub(c, RSassertOp::InI),
<c: Set_of_entities> "inP" => RSassert::Sub(c, RSassertOp::InP),
"?" "inW" => RSassert::NonEmpty(RSassertOp::InW),
"?" "inR" => RSassert::NonEmpty(RSassertOp::InR),
"?" "inI" => RSassert::NonEmpty(RSassertOp::InI),
"?" "inP" => RSassert::NonEmpty(RSassertOp::InP),
};
// -----------------------------------------------------------------------------
// BHMLParser
// -----------------------------------------------------------------------------
2025-06-16 14:46:04 +02:00
pub BHML: Box<RSBHML> = {
2025-05-14 11:42:19 +02:00
<g: Formula_BHML> => Box::new(g)
};
2025-06-16 14:46:04 +02:00
Formula_BHML: RSBHML = {
2025-05-14 11:42:19 +02:00
"true" => RSBHML::True,
"false" => RSBHML::False,
2025-07-02 17:27:36 +02:00
"(" <g: Separated<Formula_BHML, "\\/">> ")" => RSBHML::Or(g),
"(" <g: Separated<Formula_BHML, "/\\">> ")" => RSBHML::And(g),
2025-05-19 00:10:23 +02:00
"<" <f: Formula_Assert> ">" <g: Formula_BHML> =>
RSBHML::Diamond(Box::new(f), Box::new(g)),
"[" <f: Formula_Assert> "]" <g: Formula_BHML> =>
RSBHML::Box(Box::new(f), Box::new(g)),
2025-05-14 11:42:19 +02:00
};
// ----------------------------------------------------------------------------
// 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" ":" <delta: Environment>
"Initial Entities" ":" <available_entities: Set>
"Context" ":" <context_process: Context>
"Reactions" ":" <reaction_rules: Reactions>
2025-07-01 19:22:50 +02:00
=> RSsystem::from(delta.into(),
available_entities,
context_process,
Rc::new(reaction_rules))
}
2025-07-02 17:27:36 +02:00
// experiment
// an experiment is composed by a sequence of weights and a sequence of sets of
// entities of equal length.
pub Experiment: (Vec<u32>, Vec<RSset>) = {
"Weights" ":" <w: Separated_Or<Num, ",">>
"Sets" ":" <s: Separated_Or<Set_of_entities, ",">>
=> (w.into_iter().map(|x| x as u32).collect::<Vec<_>>(), s),
2025-07-02 17:27:36 +02:00
}
// Instruction Parsing
Helper_SO: presets::SaveOptions = {
"Print" =>
presets::SaveOptions {print: true, save: None},
"Save" "(" <p: Path> ")" =>
presets::SaveOptions {print: false, save: Some(vec![p])}
}
SaveOptions: presets::SaveOptions = {
<p: Separated_Or<Helper_SO, ";">> => {
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" ">" <so: SaveOptions> =>
presets::GraphSaveOptions::Dot { so },
"GraphML" ">" <so: SaveOptions> =>
presets::GraphSaveOptions::GraphML { so },
"Serialize" "(" <path: Path> ")" =>
presets::GraphSaveOptions::Serialize { path },
}
Instruction: presets::Instruction = {
"Stats" ">" <so: SaveOptions> =>
presets::Instruction::Stats { so },
"Target" ">" <so: SaveOptions> =>
presets::Instruction::Target { so },
"Run" ">" <so: SaveOptions> =>
presets::Instruction::Run { so },
"Loop" "(" <symbol: Literal> ")" ">" <so: SaveOptions> =>
presets::Instruction::Loop { symbol, so },
"Frequency" "(" <p: Path> ")" ">" <so: SaveOptions> =>
presets::Instruction::Frequency { experiment: p, so },
"LimitFrequency" "(" <p: Path> ")" ">" <so: SaveOptions> =>
presets::Instruction::LimitFrequency { experiment: p, so },
"FastFrequency" "(" <p: Path> ")" ">" <so: SaveOptions> =>
presets::Instruction::FastFrequency { experiment: p, so },
"Digraph" ">" <gso: Separated_Or<GraphSaveOptions, "|">> =>
presets::Instruction::Digraph { gso },
}
pub Run: presets::Instructions = {
<sys: System> <instr: Separated_Or<Instruction, ",">> =>
Instructions { system: presets::System::RSsystem { sys },
instructions: instr },
"Deserialize" "(" <path: Path> ")" <instr: Separated_Or<Instruction, ",">> =>
Instructions { system: presets::System::Deserialize { path },
instructions: instr },
}