dendi/src/dendi.md

99 lines
2.3 KiB
Markdown
Raw Permalink Normal View History

2024-02-14 23:55:29 +00:00
# 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!(),
}
}
}
```