use crate::rll::error::RllError;
#[derive(Debug, Clone, PartialEq)]
pub struct Rung {
pub raw_text: String,
pub content: Option<RungContent>,
pub error: Option<RllError>,
}
impl Rung {
pub fn ok(raw_text: String, content: RungContent) -> Self {
Self {
raw_text,
content: Some(content),
error: None,
}
}
pub fn err(raw_text: String, error: RllError) -> Self {
Self {
raw_text,
content: None,
error: Some(error),
}
}
pub fn is_parsed(&self) -> bool {
self.content.is_some()
}
pub fn tag_references(&self) -> Vec<TagReference> {
match &self.content {
Some(content) => content.tag_references(),
None => Vec::new(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct RungContent {
pub elements: Vec<RungElement>,
}
impl RungContent {
pub fn new(elements: Vec<RungElement>) -> Self {
Self { elements }
}
pub fn tag_references(&self) -> Vec<TagReference> {
let mut refs = Vec::new();
for element in &self.elements {
element.collect_tag_references(&mut refs);
}
refs
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum RungElement {
Instruction(Instruction),
Parallel(Vec<Branch>),
}
impl RungElement {
fn collect_tag_references(&self, refs: &mut Vec<TagReference>) {
match self {
RungElement::Instruction(instr) => {
instr.collect_tag_references(refs);
}
RungElement::Parallel(branches) => {
for branch in branches {
for element in &branch.elements {
element.collect_tag_references(refs);
}
}
}
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Branch {
pub elements: Vec<RungElement>,
}
impl Branch {
pub fn new(elements: Vec<RungElement>) -> Self {
Self { elements }
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Instruction {
pub mnemonic: String,
pub operands: Vec<Operand>,
}
impl Instruction {
pub fn new(mnemonic: impl Into<String>, operands: Vec<Operand>) -> Self {
Self {
mnemonic: mnemonic.into(),
operands,
}
}
fn collect_tag_references(&self, refs: &mut Vec<TagReference>) {
for (index, operand) in self.operands.iter().enumerate() {
if let Operand::Value(value) = operand {
let parsed = crate::rll::operand::parse_operand_value(value);
for tag in parsed.all_tags() {
refs.push(TagReference {
name: tag,
full_operand: value.clone(),
instruction: self.mnemonic.clone(),
operand_index: index,
});
}
}
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Operand {
Inferred,
Value(String),
}
impl Operand {
pub fn inferred() -> Self {
Self::Inferred
}
pub fn value(s: impl Into<String>) -> Self {
Self::Value(s.into())
}
pub fn is_inferred(&self) -> bool {
matches!(self, Self::Inferred)
}
pub fn as_value(&self) -> Option<&str> {
match self {
Self::Value(v) => Some(v),
Self::Inferred => None,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct TagReference {
pub name: String,
pub full_operand: String,
pub instruction: String,
pub operand_index: usize,
}