Added named numbers (hundred, quadrillion etc)
This commit is contained in:
parent
34de6af711
commit
961daae9d5
@ -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
|
||||
|
||||
@ -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))?;
|
||||
|
||||
26
src/lexer.rs
26
src/lexer.rs
@ -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)),
|
||||
|
||||
|
||||
30
src/lib.rs
30
src/lib.rs
@ -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),
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user