99 lines
2.3 KiB
Markdown
99 lines
2.3 KiB
Markdown
# Dendi
|
|
|
|
```{.rust file=main.rs}
|
|
fn main() {
|
|
println!("Hello, Rust!");
|
|
}
|
|
```
|
|
|
|
```{.rust file=lib.rs}
|
|
use ndm::RollSet;
|
|
use std::str::FromStr;
|
|
|
|
<<sheetentry>>
|
|
<<sheetentry-methods>>
|
|
<<entryvalue>>
|
|
<<entryvalue-fromstr>>
|
|
```
|
|
|
|
```{.rust #sheetentry}
|
|
#[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.
|
|
|
|
```{.rust #entryvalue}
|
|
#[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.
|
|
|
|
```{.rust #entryvalue-fromstr}
|
|
#[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)
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
```{.rust #sheetentry-methods}
|
|
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!(),
|
|
}
|
|
}
|
|
}
|
|
```
|