feat: add "e" as a constant

this is not great, because due to lacking whitespace-awareness
`e sin(1)` evaluates as `esin(1)` which does not exist.
This commit is contained in:
electria 2026-10-04 16:04:25 -07:00
commit d8dc549954
Signed by: electria
SSH key fingerprint: SHA256:8LlB3ucPbBHqozqkhsNbaV5oG3SlzzqUj8FZDL6IPQs

View file

@ -13,6 +13,7 @@ impl Node {
"pi" => Self::Number(Float::with_val(PREC, f64::consts::PI)),
// Planck's constant, in J*s (joule-seconds)
"h" => Self::Number(Float::with_val(PREC, 6.62607015e-34)),
"e" => Self::Number(Float::with_val(PREC, f64::consts::E)),
_ => Self::Function(s.parse()?),
})
}
@ -70,10 +71,14 @@ impl FromStr for Nodes {
fn from_str(s: &str) -> Result<Self, Self::Err> {
/// A superset of `char::is_numeric`
/// that includes other characters parseable into numbers,
/// such as `.` (for decimal) and `e` for scientific notation.
/// now only `.` (for decimals)
///
/// since including `e` makes it not parsable as a constant,
/// this function effectively only checks if the character can *start* a number
/// (since a number cannot start with `e`)
fn is_number_char(c: char) -> bool {
match c {
'.' | 'e' => true,
'.' => true,
c => c.is_numeric(),
}
}
@ -114,8 +119,10 @@ impl FromStr for Nodes {
}
ParsingState::ReadingNumber(start_index) => {
if !is_number_char(c)
// don't stop reading number on a special case, eg "1e-1"
&& !(filtered_string.chars().nth(i - 1) == Some('e') && c == '-')
&& !(c == 'e' && filtered_string.chars().nth(i + 1).is_some_and(char::is_numeric))
// don't stop reading number on special case eg "1e-1"
&& !(c == 'e' && filtered_string.chars().nth(i + 1).is_some_and(|c| c == '-'))
&& !(c == '-' && filtered_string.chars().nth(i - 1).is_some_and(|c| c == 'e'))
{
nodes.push(Node::Number(
Float::parse(&filtered_string[start_index..i])
@ -203,3 +210,16 @@ fn test() {
],
)
}
#[test]
fn test_e() {
assert_eq!(
Nodes::from_str("5e * 5").unwrap().as_ref(),
&[
Node::Number(Float::with_val(PREC, 5)),
Node::Operator(Operator::Mult),
Node::Number(Float::with_val(PREC, f64::consts::E)),
Node::Operator(Operator::Mult),
Node::Number(Float::with_val(PREC, 5))
],
)
}