2.3 KiB
Dendi
fn main() {
println!("Hello, Rust!");
}
use ndm::RollSet;
use std::str::FromStr;
<<sheetentry>>
<<sheetentry-methods>>
<<entryvalue>>
<<entryvalue-fromstr>>
#[derive(Debug, PartialEq, Clone)]
struct SheetEntry {
description: String,
display_name: String,
unique_name: String,
value: EntryValue,
value_text: Option<String>,
}
EntryValue
An EntryValue can either be a flat number, a roll formula, a calculated constant (which is just a flat number), not yet calculated, or simply not present.
#[derive(Debug, PartialEq, Clone)]
enum EntryValue {
Num(i32),
Roll(RollSet),
CalculateMe,
None,
}
Parsing EntryValue
On first pass, parsing an EntryValue
is pretty simple. If
it parses as a number, it's a Num(i32)
. Otherwise, if it
parses as a RollSet
, then that's what it is. Otherwise, it's
something special that we'll have to determine later, once
all of the other EntryValues
have been parsed.
TODO
It's possible that something requiring additional processing
will parse as a RollSet
, due to ndm's permissive approach
to allowing plaintext comments in roll strings. As a result,
we should check if the string contains any valid
value-reference tokens (with the format $unique_name
), and
take that as a sign that further work is needed to get at
the value.
#[derive(Debug, PartialEq)]
enum EntryValueError {
NoValue(SheetEntry),
InvalidFormula(String),
}
impl FromStr for EntryValue {
type Err = EntryValueError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.is_empty() {
Ok(Self::None)
} else if let Ok(n) = s.parse::<i32>() {
Ok(Self::Num(n))
} else if let Ok(rs) = s.parse::<RollSet>() {
Ok(Self::Roll(rs))
} else {
Ok(Self::CalculateMe)
}
}
}
impl SheetEntry {
fn evaluate(&self) -> Result<String, EntryValueError> {
match &self.value {
EntryValue::Num(n) => Ok(n.to_string()),
EntryValue::Roll(r) => Ok(r.to_string()),
EntryValue::None => Err(EntryValueError::NoValue(self.clone())),
_ => todo!(),
}
}
}