Added named numbers (hundred, quadrillion etc)
This commit is contained in:
parent
34de6af711
commit
961daae9d5
@ -166,7 +166,6 @@ match string {
|
|||||||
|
|
||||||
### Potential Improvements
|
### Potential Improvements
|
||||||
#### General
|
#### 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.
|
- 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`
|
- Support for lexing words, like `one billion`
|
||||||
#### Potential unit types
|
#### Potential unit types
|
||||||
|
|||||||
@ -7,7 +7,7 @@ use crate::Constant::{Pi, E};
|
|||||||
use crate::UnaryOperator::{Percent, Factorial};
|
use crate::UnaryOperator::{Percent, Factorial};
|
||||||
use crate::TextOperator::{To, Of};
|
use crate::TextOperator::{To, Of};
|
||||||
use crate::FunctionIdentifier::*;
|
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)
|
/// Evaluate an [`AstNode`](struct.AstNode.html) into a [`Number`](struct.Number.html)
|
||||||
pub fn evaluate(ast: &AstNode) -> Result<Number, String> {
|
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) => {
|
Token::TextOperator(operator) => {
|
||||||
let left_child = children.get(0).ok_or(format!("Token {:?} has no child[0]", token))?;
|
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))?;
|
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::Operator::{Caret, Divide, LeftParen, Minus, Modulo, Multiply, Plus, RightParen};
|
||||||
use crate::UnaryOperator::{Percent, Factorial};
|
use crate::UnaryOperator::{Percent, Factorial};
|
||||||
use crate::TextOperator::{Of, To};
|
use crate::TextOperator::{Of, To};
|
||||||
|
use crate::NamedNumber::*;
|
||||||
use crate::Constant::{E, Pi};
|
use crate::Constant::{E, Pi};
|
||||||
use crate::LexerKeyword::{In, PercentChar, Per, Mercury, Hg, PoundForce, PoundWord, Force, DoubleQuotes};
|
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};
|
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)),
|
"to" => tokens.push(Token::TextOperator(To)),
|
||||||
"of" => tokens.push(Token::TextOperator(Of)),
|
"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)),
|
"pi" => tokens.push(Token::Constant(Pi)),
|
||||||
"e" => tokens.push(Token::Constant(E)),
|
"e" => tokens.push(Token::Constant(E)),
|
||||||
|
|
||||||
|
|||||||
30
src/lib.rs
30
src/lib.rs
@ -93,6 +93,35 @@ pub enum TextOperator {
|
|||||||
Of,
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
/// A constants like [`Pi`](enum.Constant.html#variant.Pi) or [`E`](enum.Constant.html#variant.E).
|
/// A constants like [`Pi`](enum.Constant.html#variant.Pi) or [`E`](enum.Constant.html#variant.E).
|
||||||
pub enum Constant {
|
pub enum Constant {
|
||||||
@ -157,6 +186,7 @@ pub enum Token {
|
|||||||
/// Used by the parser only
|
/// Used by the parser only
|
||||||
LexerKeyword(LexerKeyword),
|
LexerKeyword(LexerKeyword),
|
||||||
TextOperator(TextOperator),
|
TextOperator(TextOperator),
|
||||||
|
NamedNumber(NamedNumber),
|
||||||
/// The `-` symbol, specifically when used as `-5` and not `5-5`. Used by the parser only
|
/// The `-` symbol, specifically when used as `-5` and not `5-5`. Used by the parser only
|
||||||
Negative,
|
Negative,
|
||||||
Unit(units::Unit),
|
Unit(units::Unit),
|
||||||
|
|||||||
@ -1,5 +1,37 @@
|
|||||||
|
use crate::NamedNumber::*;
|
||||||
|
use crate::NamedNumber;
|
||||||
use decimal::d128;
|
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)
|
/// Returns the factorial of an `i32` as a [`d128`](decimal/struct.d128.html)
|
||||||
pub fn lookup_factorial(n: i32) -> d128 {
|
pub fn lookup_factorial(n: i32) -> d128 {
|
||||||
return match n {
|
return match n {
|
||||||
|
|||||||
@ -269,7 +269,7 @@ pub fn parse_level_6(tokens: &TokenVector, pos: usize) -> Result<(AstNode, usize
|
|||||||
loop {
|
loop {
|
||||||
let token = tokens.get(pos);
|
let token = tokens.get(pos);
|
||||||
match token {
|
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
|
// Here we are handling unary operators, aka stuff written as
|
||||||
// "Number Operator" (3!) instead of "Number Operator Number" (3+3).
|
// "Number Operator" (3!) instead of "Number Operator Number" (3+3).
|
||||||
// Therefore, if we find a match, we don't parse what comes after it.
|
// Therefore, if we find a match, we don't parse what comes after it.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user