Added named numbers (hundred, quadrillion etc)

This commit is contained in:
Kasper 2020-11-14 04:08:27 +01:00
parent 34de6af711
commit 961daae9d5
6 changed files with 97 additions and 3 deletions

View File

@ -166,7 +166,6 @@ match string {
### Potential Improvements
#### General
- Support for math in `6'4"` syntax, like `3'+2'4"`. Currently needs to be written like `3'+3'+4"`
- The functions in units.rs have a lot of manual if statements. This could probably be replaced with a pretty advanced macro.
- Support for lexing words, like `one billion`
#### Potential unit types

View File

@ -7,7 +7,7 @@ use crate::Constant::{Pi, E};
use crate::UnaryOperator::{Percent, Factorial};
use crate::TextOperator::{To, Of};
use crate::FunctionIdentifier::*;
use crate::lookup::lookup_factorial;
use crate::lookup::{lookup_factorial, lookup_named_number};
/// Evaluate an [`AstNode`](struct.AstNode.html) into a [`Number`](struct.Number.html)
pub fn evaluate(ast: &AstNode) -> Result<Number, String> {
@ -219,6 +219,13 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
},
}
},
Token::NamedNumber(named_number) => {
let child_node = children.get(0).ok_or(format!("Token {:?} has no child[0]", token))?;
let child_answer = evaluate_node(child_node)?;
let named_number_value = lookup_named_number(named_number);
let result = child_answer.value * named_number_value;
Ok(Number::new(result, child_answer.unit))
}
Token::TextOperator(operator) => {
let left_child = children.get(0).ok_or(format!("Token {:?} has no child[0]", token))?;
let right_child = children.get(1).ok_or(format!("Token {:?} has no child[1]", token))?;

View File

@ -4,6 +4,7 @@ use crate::{Token, TokenVector};
use crate::Operator::{Caret, Divide, LeftParen, Minus, Modulo, Multiply, Plus, RightParen};
use crate::UnaryOperator::{Percent, Factorial};
use crate::TextOperator::{Of, To};
use crate::NamedNumber::*;
use crate::Constant::{E, Pi};
use crate::LexerKeyword::{In, PercentChar, Per, Mercury, Hg, PoundForce, PoundWord, Force, DoubleQuotes};
use crate::FunctionIdentifier::{Cbrt, Ceil, Cos, Exp, Abs, Floor, Ln, Log, Round, Sin, Sqrt, Tan};
@ -130,6 +131,31 @@ pub fn lex(input: &str, allow_trailing_operators: bool, default_degree: Unit) ->
"to" => tokens.push(Token::TextOperator(To)),
"of" => tokens.push(Token::TextOperator(Of)),
"hundred" => tokens.push(Token::NamedNumber(Hundred)),
"thousand" => tokens.push(Token::NamedNumber(Thousand)),
"mil" | "mill" | "million" => tokens.push(Token::NamedNumber(Million)),
"bil" | "bill" | "billion" => tokens.push(Token::NamedNumber(Billion)),
"tri" | "tril" | "trillion" => tokens.push(Token::NamedNumber(Trillion)),
"quadrillion" => tokens.push(Token::NamedNumber(Quadrillion)),
"quintillion" => tokens.push(Token::NamedNumber(Quintillion)),
"sextillion" => tokens.push(Token::NamedNumber(Sextillion)),
"septillion" => tokens.push(Token::NamedNumber(Septillion)),
"octillion" => tokens.push(Token::NamedNumber(Octillion)),
"nonillion" => tokens.push(Token::NamedNumber(Nonillion)),
"decillion" => tokens.push(Token::NamedNumber(Decillion)),
"undecillion" => tokens.push(Token::NamedNumber(Undecillion)),
"duodecillion" => tokens.push(Token::NamedNumber(Duodecillion)),
"tredecillion" => tokens.push(Token::NamedNumber(Tredecillion)),
"quattuordecillion" => tokens.push(Token::NamedNumber(Quattuordecillion)),
"quindecillion" => tokens.push(Token::NamedNumber(Quindecillion)),
"sexdecillion" => tokens.push(Token::NamedNumber(Sexdecillion)),
"septendecillion" => tokens.push(Token::NamedNumber(Septendecillion)),
"octodecillion" => tokens.push(Token::NamedNumber(Octodecillion)),
"novemdecillion" => tokens.push(Token::NamedNumber(Novemdecillion)),
"vigintillion" => tokens.push(Token::NamedNumber(Vigintillion)),
"centillion" => tokens.push(Token::NamedNumber(Centillion)),
"googol" => tokens.push(Token::NamedNumber(Googol)),
"pi" => tokens.push(Token::Constant(Pi)),
"e" => tokens.push(Token::Constant(E)),

View File

@ -93,6 +93,35 @@ pub enum TextOperator {
Of,
}
#[derive(Clone, Debug)]
/// A named number like [`Million`](enum.NamedNumber.html#variant.Million).
pub enum NamedNumber {
Hundred,
Thousand,
Million,
Billion,
Trillion,
Quadrillion,
Quintillion,
Sextillion,
Septillion,
Octillion,
Nonillion,
Decillion,
Undecillion,
Duodecillion,
Tredecillion,
Quattuordecillion,
Quindecillion,
Sexdecillion,
Septendecillion,
Octodecillion,
Novemdecillion,
Vigintillion,
Centillion,
Googol,
}
#[derive(Clone, Debug)]
/// A constants like [`Pi`](enum.Constant.html#variant.Pi) or [`E`](enum.Constant.html#variant.E).
pub enum Constant {
@ -157,6 +186,7 @@ pub enum Token {
/// Used by the parser only
LexerKeyword(LexerKeyword),
TextOperator(TextOperator),
NamedNumber(NamedNumber),
/// The `-` symbol, specifically when used as `-5` and not `5-5`. Used by the parser only
Negative,
Unit(units::Unit),

View File

@ -1,5 +1,37 @@
use crate::NamedNumber::*;
use crate::NamedNumber;
use decimal::d128;
/// Returns the number of a [`NamedNumber`](decimal/struct.d128.html) [`to`](../enum.NamedNumber.html) as a [`d128`](decimal/struct.d128.html)
pub fn lookup_named_number(named_number: &NamedNumber) -> d128 {
return match named_number {
Hundred => d128!(100),
Thousand => d128!(1000),
Million => d128!(1000000),
Billion => d128!(1000000000),
Trillion => d128!(1000000000000),
Quadrillion => d128!(1000000000000000),
Quintillion => d128!(1000000000000000000),
Sextillion => d128!(1000000000000000000000),
Septillion => d128!(1000000000000000000000000),
Octillion => d128!(1000000000000000000000000000),
Nonillion => d128!(1000000000000000000000000000000),
Decillion => d128!(1000000000000000000000000000000000),
Undecillion => d128!(1000000000000000000000000000000000000),
Duodecillion => d128!(10E+39),
Tredecillion => d128!(10E+42),
Quattuordecillion => d128!(10E+45),
Quindecillion => d128!(10E+48),
Sexdecillion => d128!(10E+51),
Septendecillion => d128!(10E+54),
Octodecillion => d128!(10E+57),
Novemdecillion => d128!(10E+60),
Vigintillion => d128!(10E+63),
Centillion => d128!(10E+303),
Googol => d128!(10E+100),
}
}
/// Returns the factorial of an `i32` as a [`d128`](decimal/struct.d128.html)
pub fn lookup_factorial(n: i32) -> d128 {
return match n {

View File

@ -269,7 +269,7 @@ pub fn parse_level_6(tokens: &TokenVector, pos: usize) -> Result<(AstNode, usize
loop {
let token = tokens.get(pos);
match token {
Some(&Token::UnaryOperator(Factorial)) | Some(&Token::UnaryOperator(Percent)) => {
Some(&Token::UnaryOperator(Factorial)) | Some(&Token::UnaryOperator(Percent)) | Some(&Token::NamedNumber(_)) => {
// Here we are handling unary operators, aka stuff written as
// "Number Operator" (3!) instead of "Number Operator Number" (3+3).
// Therefore, if we find a match, we don't parse what comes after it.