Use rustfmt for some files

This commit is contained in:
Kasper 2022-09-12 00:45:29 +02:00
parent a64081ac73
commit 1bb3819350
No known key found for this signature in database
GPG Key ID: 356D5C59EDCEC2D1
5 changed files with 223 additions and 184 deletions

1
rustfmt.toml Normal file
View File

@ -0,0 +1 @@
tab_spaces=2

View File

@ -1,13 +1,13 @@
use decimal::d128;
use crate::{Token, Number};
use crate::units::{Unit, UnitType, convert, add, subtract, multiply, divide, modulo, pow};
use crate::parser::AstNode;
use crate::Operator::{Caret, Divide, Minus, Modulo, Multiply, Plus};
use crate::Constant::{Pi, E};
use crate::UnaryOperator::{Percent, Factorial};
use crate::TextOperator::{To, Of};
use crate::FunctionIdentifier::*;
use crate::lookup::{lookup_factorial, lookup_named_number}; use crate::lookup::{lookup_factorial, lookup_named_number};
use crate::parser::AstNode;
use crate::units::{add, convert, divide, modulo, multiply, pow, subtract, Unit, UnitType};
use crate::Constant::{Pi, E};
use crate::FunctionIdentifier::*;
use crate::Operator::{Caret, Divide, Minus, Modulo, Multiply, Plus};
use crate::TextOperator::{Of, To};
use crate::UnaryOperator::{Factorial, Percent};
use crate::{Number, Token};
use decimal::d128;
/// Evaluate an [`AstNode`] into a [`Number`] /// Evaluate an [`AstNode`] into a [`Number`]
pub fn evaluate(ast: &AstNode) -> Result<Number, String> { pub fn evaluate(ast: &AstNode) -> Result<Number, String> {
@ -29,7 +29,7 @@ pub fn sqrt(input: d128) -> d128 {
let mut n = d128!(1); let mut n = d128!(1);
let half = d128!(0.5); let half = d128!(0.5);
for _ in 0..10 { for _ in 0..10 {
n = (n + input/n) * half; n = (n + input / n) * half;
} }
n n
} }
@ -40,8 +40,8 @@ pub fn cbrt(input: d128) -> d128 {
// hope that 20 iterations makes it accurate enough // hope that 20 iterations makes it accurate enough
let three = d128!(3); let three = d128!(3);
for _ in 0..20 { for _ in 0..20 {
let z2 = n*n; let z2 = n * n;
n = n - ((n*z2 - input) / (three*z2)); n = n - ((n * z2 - input) / (three * z2));
} }
n n
} }
@ -68,12 +68,11 @@ pub fn sin(mut input: d128) -> d128 {
let mut result = d128!(0); let mut result = d128!(0);
for i_int in 0..precision { for i_int in 0..precision {
let i = d128::from(i_int); let i = d128::from(i_int);
let calc_result = two*i+one; let calc_result = two * i + one;
result += neg_one.pow(i) * (input.pow(calc_result) / factorial(calc_result)); result += neg_one.pow(i) * (input.pow(calc_result) / factorial(calc_result));
} }
negative_correction * result negative_correction * result
} }
/// Returns the cosine of a [`struct@d128`] /// Returns the cosine of a [`struct@d128`]
@ -92,18 +91,16 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
let token = &ast_node.token; let token = &ast_node.token;
let children = &ast_node.children; let children = &ast_node.children;
match token { match token {
Token::Number(number) => { Token::Number(number) => Ok(Number::new(*number, Unit::NoUnit)),
Ok(Number::new(*number, Unit::NoUnit)) Token::Constant(constant) => match constant {
}, Pi => Ok(Number::new(
Token::Constant(constant) => { d128!(3.141592653589793238462643383279503),
match constant { Unit::NoUnit,
Pi => { )),
Ok(Number::new(d128!(3.141592653589793238462643383279503), Unit::NoUnit)) E => Ok(Number::new(
}, d128!(2.718281828459045235360287471352662),
E => { Unit::NoUnit,
Ok(Number::new(d128!(2.718281828459045235360287471352662), Unit::NoUnit)) )),
},
}
}, },
Token::FunctionIdentifier(function) => { Token::FunctionIdentifier(function) => {
let child_node = children.get(0).ok_or("Paren has no child[0]")?; let child_node = children.get(0).ok_or("Paren has no child[0]")?;
@ -116,7 +113,7 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
} else { } else {
Err("log() only accepts UnitType::NoType".to_string()) Err("log() only accepts UnitType::NoType".to_string())
} }
}, }
Sqrt => { Sqrt => {
if child_answer.unit.category() == UnitType::NoType { if child_answer.unit.category() == UnitType::NoType {
let result = sqrt(child_answer.value); let result = sqrt(child_answer.value);
@ -124,7 +121,7 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
} else { } else {
Err("log() only accepts UnitType::NoType".to_string()) Err("log() only accepts UnitType::NoType".to_string())
} }
}, }
Log => { Log => {
if child_answer.unit.category() == UnitType::NoType { if child_answer.unit.category() == UnitType::NoType {
let result = child_answer.value.log10(); let result = child_answer.value.log10();
@ -132,7 +129,7 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
} else { } else {
Err("log() only accepts UnitType::NoType".to_string()) Err("log() only accepts UnitType::NoType".to_string())
} }
}, }
Ln => { Ln => {
if child_answer.unit.category() == UnitType::NoType { if child_answer.unit.category() == UnitType::NoType {
let result = child_answer.value.ln(); let result = child_answer.value.ln();
@ -140,7 +137,7 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
} else { } else {
Err("ln() only accepts UnitType::NoType".to_string()) Err("ln() only accepts UnitType::NoType".to_string())
} }
}, }
Exp => { Exp => {
if child_answer.unit.category() == UnitType::NoType { if child_answer.unit.category() == UnitType::NoType {
let result = child_answer.value.exp(child_answer.value); let result = child_answer.value.exp(child_answer.value);
@ -148,79 +145,92 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
} else { } else {
Err("exp() only accepts UnitType::NoType".to_string()) Err("exp() only accepts UnitType::NoType".to_string())
} }
}, }
Round => { Round => {
// .quantize() rounds .5 to nearest even integer, so we correct that // .quantize() rounds .5 to nearest even integer, so we correct that
let mut result = child_answer.value.quantize(d128!(1)); let mut result = child_answer.value.quantize(d128!(1));
let rounding_change = result - child_answer.value; let rounding_change = result - child_answer.value;
// If the result was rounded down by 0.5, correct by +1 // If the result was rounded down by 0.5, correct by +1
if rounding_change == d128!(-0.5) { result += d128!(1); } if rounding_change == d128!(-0.5) {
result += d128!(1);
}
Ok(Number::new(result, child_answer.unit)) Ok(Number::new(result, child_answer.unit))
}, }
Ceil => { Ceil => {
let mut result = child_answer.value.quantize(d128!(1)); let mut result = child_answer.value.quantize(d128!(1));
let rounding_change = result - child_answer.value; let rounding_change = result - child_answer.value;
if rounding_change.is_negative() { result += d128!(1); } if rounding_change.is_negative() {
result += d128!(1);
}
Ok(Number::new(result, child_answer.unit)) Ok(Number::new(result, child_answer.unit))
}, }
Floor => { Floor => {
let mut result = child_answer.value.quantize(d128!(1)); let mut result = child_answer.value.quantize(d128!(1));
let rounding_change = result - child_answer.value; let rounding_change = result - child_answer.value;
if !rounding_change.is_negative() { result -= d128!(1); } if !rounding_change.is_negative() {
result -= d128!(1);
}
Ok(Number::new(result, child_answer.unit)) Ok(Number::new(result, child_answer.unit))
}, }
Abs => { Abs => {
let mut result = child_answer.value.abs(); let mut result = child_answer.value.abs();
let rounding_change = result - child_answer.value; let rounding_change = result - child_answer.value;
if rounding_change == d128!(-0.5) { result += d128!(1); } if rounding_change == d128!(-0.5) {
result += d128!(1);
}
Ok(Number::new(result, child_answer.unit)) Ok(Number::new(result, child_answer.unit))
}, }
Sin => { Sin => {
let result = sin(child_answer.value); let result = sin(child_answer.value);
Ok(Number::new(result, child_answer.unit)) Ok(Number::new(result, child_answer.unit))
}, }
Cos => { Cos => {
let result = cos(child_answer.value); let result = cos(child_answer.value);
Ok(Number::new(result, child_answer.unit)) Ok(Number::new(result, child_answer.unit))
}, }
Tan => { Tan => {
let result = tan(child_answer.value); let result = tan(child_answer.value);
Ok(Number::new(result, child_answer.unit)) Ok(Number::new(result, child_answer.unit))
}, }
} }
} }
Token::Unit(unit) => { Token::Unit(unit) => {
let child_node = children.get(0).ok_or("Unit has no child[0]")?; let child_node = children.get(0).ok_or("Unit has no child[0]")?;
let child_answer = evaluate_node(child_node)?; let child_answer = evaluate_node(child_node)?;
Ok(Number::new(child_answer.value, *unit)) Ok(Number::new(child_answer.value, *unit))
}, }
Token::Negative => { Token::Negative => {
let child_node = children.get(0).ok_or("Negative has no child[0]")?; let child_node = children.get(0).ok_or("Negative has no child[0]")?;
let child_answer = evaluate_node(child_node)?; let child_answer = evaluate_node(child_node)?;
Ok(Number::new(-child_answer.value, child_answer.unit)) Ok(Number::new(-child_answer.value, child_answer.unit))
}, }
Token::Paren => { Token::Paren => {
let child_node = children.get(0).ok_or("Paren has no child[0]")?; let child_node = children.get(0).ok_or("Paren has no child[0]")?;
evaluate_node(child_node) evaluate_node(child_node)
}, }
Token::UnaryOperator(operator) => { Token::UnaryOperator(operator) => {
let child_node = children.get(0).ok_or(format!("Token {:?} has no child[0]", token))?; let child_node = children
.get(0)
.ok_or(format!("Token {:?} has no child[0]", token))?;
let child_answer = evaluate_node(child_node)?; let child_answer = evaluate_node(child_node)?;
match operator { match operator {
Percent => { Percent => Ok(Number::new(
Ok(Number::new(child_answer.value / d128!(100), child_answer.unit)) child_answer.value / d128!(100),
}, child_answer.unit,
)),
Factorial => { Factorial => {
let result = factorial(child_answer.value); let result = factorial(child_answer.value);
if result.is_nan() { if result.is_nan() {
return Err("Can only perform factorial on integers from 0 to 1000".to_string()); return Err("Can only perform factorial on integers from 0 to 1000".to_string());
} }
Ok(Number::new(result, child_answer.unit)) Ok(Number::new(result, child_answer.unit))
}, }
} }
}, }
Token::NamedNumber(named_number) => { Token::NamedNumber(named_number) => {
let child_node = children.get(0).ok_or(format!("Token {:?} has no child[0]", token))?; let child_node = children
.get(0)
.ok_or(format!("Token {:?} has no child[0]", token))?;
let named_number_value = lookup_named_number(named_number); let named_number_value = lookup_named_number(named_number);
if let Token::NamedNumber(child_nn) = &child_node.token { if let Token::NamedNumber(child_nn) = &child_node.token {
let child_nn_value = lookup_named_number(child_nn); let child_nn_value = lookup_named_number(child_nn);
@ -233,8 +243,12 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
Ok(Number::new(result, child_answer.unit)) 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
let right_child = children.get(1).ok_or(format!("Token {:?} has no child[1]", token))?; .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))?;
match operator { match operator {
To => { To => {
@ -245,7 +259,7 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
} else { } else {
Err("Right side of To operator needs to be a unit".to_string()) Err("Right side of To operator needs to be a unit".to_string())
} }
}, }
Of => { Of => {
let left = evaluate_node(left_child)?; let left = evaluate_node(left_child)?;
let right = evaluate_node(right_child)?; let right = evaluate_node(right_child)?;
@ -254,44 +268,40 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
} else { } else {
Err("Left side of the Of operator must be NoUnit".to_string()) Err("Left side of the Of operator must be NoUnit".to_string())
} }
}, }
} }
}, }
Token::Operator(operator) => { Token::Operator(operator) => {
let left_child = children.get(0).ok_or(format!("Token {:?} has no child[0]", token))?; let left_child = children
let right_child = children.get(1).ok_or(format!("Token {:?} has no child[1]", token))?; .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 left = evaluate_node(left_child)?; let left = evaluate_node(left_child)?;
let right = evaluate_node(right_child)?; let right = evaluate_node(right_child)?;
match operator { match operator {
Plus => { Plus => Ok(add(left, right)?),
Ok(add(left, right)?) Minus => Ok(subtract(left, right)?),
},
Minus => {
Ok(subtract(left, right)?)
},
Multiply => { Multiply => {
Ok(multiply(left, right)?) Ok(multiply(left, right)?)
// } // }
}, }
Divide => { Divide => {
Ok(divide(left, right)?) Ok(divide(left, right)?)
// } // }
}, }
Modulo => { Modulo => {
Ok(modulo(left, right)?) Ok(modulo(left, right)?)
// } // }
}, }
Caret => { Caret => {
Ok(pow(left, right)?) Ok(pow(left, right)?)
// } // }
},
_ => {
Err(format!("Unexpected operator {:?}", operator))
} }
_ => Err(format!("Unexpected operator {:?}", operator)),
} }
},
_ => {
Err(format!("Unexpected token {:?}", token))
} }
_ => Err(format!("Unexpected token {:?}", token)),
} }
} }

View File

@ -1,9 +1,9 @@
#![cfg_attr( #![cfg_attr(
feature = "cargo-clippy", feature = "cargo-clippy",
allow( allow(
clippy::comparison_chain, clippy::comparison_chain,
clippy::if_same_then_else, clippy::if_same_then_else,
clippy::match_like_matches_macro, clippy::match_like_matches_macro,
) )
)] )]
//! calculation + conversion //! calculation + conversion
@ -30,20 +30,23 @@
//! } //! }
//! ``` //! ```
use crate::units::Unit;
use decimal::d128;
use std::fmt::{self, Display}; use std::fmt::{self, Display};
use std::time::Instant; use std::time::Instant;
use decimal::d128;
use crate::units::Unit;
/// Units, and functions you can use with them
pub mod units;
/// Turns a string into [`Token`]s
pub mod lexer;
/// Turns [`Token`]s into an [`AstNode`](parser::AstNode)
pub mod parser;
/// Turns an [`AstNode`](parser::AstNode) into a [`Number`] /// Turns an [`AstNode`](parser::AstNode) into a [`Number`]
pub mod evaluator; pub mod evaluator;
/// Turns a string into [`Token`]s
#[rustfmt::skip]
pub mod lexer;
#[rustfmt::skip]
mod lookup; mod lookup;
/// Turns [`Token`]s into an [`AstNode`](parser::AstNode)
pub mod parser;
/// Units, and functions you can use with them
#[rustfmt::skip]
pub mod units;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
/// A number with a `Unit`. /// A number with a `Unit`.
@ -92,7 +95,7 @@ pub enum Operator {
Divide, Divide,
Modulo, Modulo,
Caret, Caret,
LeftParen, // lexer only LeftParen, // lexer only
RightParen, // lexer only RightParen, // lexer only
} }
@ -213,7 +216,7 @@ pub enum Token {
macro_rules! numtok { macro_rules! numtok {
( $num:literal ) => { ( $num:literal ) => {
Token::Number(d128!($num)) Token::Number(d128!($num))
} };
} }
/// Evaluates a string into a resulting [`Number`]. /// Evaluates a string into a resulting [`Number`].
@ -233,20 +236,28 @@ macro_rules! numtok {
/// } /// }
/// } /// }
/// ``` /// ```
pub fn eval(input: &str, allow_trailing_operators: bool, default_degree: Unit, verbose: bool) -> Result<Number, String> { pub fn eval(
input: &str,
allow_trailing_operators: bool,
default_degree: Unit,
verbose: bool,
) -> Result<Number, String> {
let lex_start = Instant::now(); let lex_start = Instant::now();
match lexer::lex(input, allow_trailing_operators, default_degree) { match lexer::lex(input, allow_trailing_operators, default_degree) {
Ok(tokens) => { Ok(tokens) => {
let lex_time = Instant::now().duration_since(lex_start).as_nanos() as f32; let lex_time = Instant::now().duration_since(lex_start).as_nanos() as f32;
if verbose { println!("Lexed TokenVector: {:?}", tokens); } if verbose {
println!("Lexed TokenVector: {:?}", tokens);
}
let parse_start = Instant::now(); let parse_start = Instant::now();
match parser::parse(&tokens) { match parser::parse(&tokens) {
Ok(ast) => { Ok(ast) => {
let parse_time = Instant::now().duration_since(parse_start).as_nanos() as f32; let parse_time = Instant::now().duration_since(parse_start).as_nanos() as f32;
if verbose { println!("Parsed AstNode: {:#?}", ast); } if verbose {
println!("Parsed AstNode: {:#?}", ast);
}
let eval_start = Instant::now(); let eval_start = Instant::now();
match evaluator::evaluate(&ast) { match evaluator::evaluate(&ast) {
@ -255,19 +266,19 @@ pub fn eval(input: &str, allow_trailing_operators: bool, default_degree: Unit, v
if verbose { if verbose {
println!("Evaluated value: {} {:?}", answer.value, answer.unit); println!("Evaluated value: {} {:?}", answer.value, answer.unit);
println!("\u{23f1} {:.3}ms lexing", lex_time/1000.0/1000.0); println!("\u{23f1} {:.3}ms lexing", lex_time / 1000.0 / 1000.0);
println!("\u{23f1} {:.3}ms parsing", parse_time/1000.0/1000.0); println!("\u{23f1} {:.3}ms parsing", parse_time / 1000.0 / 1000.0);
println!("\u{23f1} {:.3}ms evaluation", eval_time/1000.0/1000.0); println!("\u{23f1} {:.3}ms evaluation", eval_time / 1000.0 / 1000.0);
} }
Ok(answer) Ok(answer)
}, }
Err(e) => Err(format!("Eval error: {}", e)), Err(e) => Err(format!("Eval error: {}", e)),
} }
}, }
Err(e) => Err(format!("Parsing error: {}", e)), Err(e) => Err(format!("Parsing error: {}", e)),
} }
}, }
Err(e) => Err(format!("Lexing error: {}", e)), Err(e) => Err(format!("Lexing error: {}", e)),
} }
} }

View File

@ -1,7 +1,7 @@
use cpc::eval; use cpc::eval;
use cpc::units::Unit; use cpc::units::Unit;
use std::process::exit;
use std::env; use std::env;
use std::process::exit;
const VERSION: &str = env!("CARGO_PKG_VERSION"); const VERSION: &str = env!("CARGO_PKG_VERSION");
@ -30,12 +30,12 @@ fn main() {
"--version" => { "--version" => {
println!("{}", VERSION); println!("{}", VERSION);
exit(0); exit(0);
}, }
"--help" => { "--help" => {
print_help(); print_help();
exit(0); exit(0);
}, }
_ => {}, _ => {}
} }
} }
let mut verbose = false; let mut verbose = false;
@ -58,7 +58,7 @@ fn main() {
None => { None => {
print_help(); print_help();
exit(0); exit(0);
}, }
}; };
match eval(&expression, true, Unit::Celsius, verbose) { match eval(&expression, true, Unit::Celsius, verbose) {
@ -66,10 +66,10 @@ fn main() {
if !verbose { if !verbose {
println!("{}", answer); println!("{}", answer);
} }
}, }
Err(e) => { Err(e) => {
eprintln!("{}", e); eprintln!("{}", e);
exit(1); exit(1);
}, }
} }
} }

View File

@ -1,8 +1,8 @@
use crate::Token;
use crate::Operator::{Caret, Divide, LeftParen, Minus, Modulo, Multiply, Plus, RightParen};
use crate::UnaryOperator::{Percent, Factorial};
use crate::TextOperator::{To, Of};
use crate::units::Unit::{Foot, Inch}; use crate::units::Unit::{Foot, Inch};
use crate::Operator::{Caret, Divide, LeftParen, Minus, Modulo, Multiply, Plus, RightParen};
use crate::TextOperator::{Of, To};
use crate::Token;
use crate::UnaryOperator::{Factorial, Percent};
#[derive(Debug)] #[derive(Debug)]
/// A struct with a [`Token`](AstNode::token) and [`AstNode`] [`children`](AstNode::children) /// A struct with a [`Token`](AstNode::token) and [`AstNode`] [`children`](AstNode::children)
@ -24,10 +24,15 @@ impl AstNode {
/// Parse [`Token`]s into an Abstract Syntax Tree ([`AstNode`]) /// Parse [`Token`]s into an Abstract Syntax Tree ([`AstNode`])
pub fn parse(tokens: &[Token]) -> Result<AstNode, String> { pub fn parse(tokens: &[Token]) -> Result<AstNode, String> {
parse_level_1(tokens, 0).and_then(|(ast, next_pos)| if next_pos == tokens.len() { parse_level_1(tokens, 0).and_then(|(ast, next_pos)| {
if next_pos == tokens.len() {
Ok(ast) Ok(ast)
} else { } else {
Err(format!("Expected end of input, found {:?} at {}", tokens[next_pos], next_pos)) Err(format!(
"Expected end of input, found {:?} at {}",
tokens[next_pos], next_pos
))
}
}) })
} }
@ -49,12 +54,12 @@ pub fn parse_level_1(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), S
new_node.children.push(right_node); new_node.children.push(right_node);
node = new_node; node = new_node;
pos = next_pos; pos = next_pos;
}, }
// if there's no match, we go down to a lower precedence (or, in this // if there's no match, we go down to a lower precedence (or, in this
// case, we're done) // case, we're done)
_ => { _ => {
return Ok((node, pos)); return Ok((node, pos));
}, }
} }
} }
} }
@ -73,10 +78,10 @@ pub fn parse_level_2(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), S
new_node.children.push(right_node); new_node.children.push(right_node);
node = new_node; node = new_node;
pos = next_pos; pos = next_pos;
}, }
_ => { _ => {
return Ok((node, pos)); return Ok((node, pos));
}, }
} }
} }
} }
@ -96,21 +101,17 @@ pub fn parse_level_3(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), S
let new_node = AstNode { let new_node = AstNode {
children: vec![ children: vec![
AstNode { AstNode {
children: vec![ children: vec![AstNode::new(token0.unwrap().clone())],
AstNode::new(token0.unwrap().clone()),
],
token: Token::Unit(Foot), token: Token::Unit(Foot),
}, },
AstNode { AstNode {
children: vec![ children: vec![AstNode::new(token2.unwrap().clone())],
AstNode::new(token2.unwrap().clone()),
],
token: Token::Unit(Inch), token: Token::Unit(Inch),
}, },
], ],
token: Token::Operator(Plus), token: Token::Operator(Plus),
}; };
return Ok((new_node, pos + 4)) return Ok((new_node, pos + 4));
} }
} }
} }
@ -121,14 +122,16 @@ pub fn parse_level_3(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), S
loop { loop {
let token = tokens.get(pos); let token = tokens.get(pos);
match token { match token {
Some(&Token::Operator(Multiply)) | Some(&Token::Operator(Divide)) | Some(&Token::Operator(Modulo)) => { Some(&Token::Operator(Multiply))
| Some(&Token::Operator(Divide))
| Some(&Token::Operator(Modulo)) => {
let (right_node, next_pos) = parse_level_4(tokens, pos + 1)?; let (right_node, next_pos) = parse_level_4(tokens, pos + 1)?;
let mut new_node = AstNode::new(token.unwrap().clone()); let mut new_node = AstNode::new(token.unwrap().clone());
new_node.children.push(node); new_node.children.push(node);
new_node.children.push(right_node); new_node.children.push(right_node);
node = new_node; node = new_node;
pos = next_pos; pos = next_pos;
}, }
// Below is implicative multiplication, for example '2pi'. Constants and // Below is implicative multiplication, for example '2pi'. Constants and
// such will only end up here if they were unable to be parsed as part of // such will only end up here if they were unable to be parsed as part of
@ -148,12 +151,12 @@ pub fn parse_level_3(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), S
new_node.children.push(right_node); new_node.children.push(right_node);
node = new_node; node = new_node;
pos = next_pos; pos = next_pos;
}, }
_ => { _ => {
return Ok((node, pos)); return Ok((node, pos));
}, }
} }
}, }
// 2pi, )pi // 2pi, )pi
Some(&Token::Constant(_)) => { Some(&Token::Constant(_)) => {
let last_token = tokens.get(pos - 1); let last_token = tokens.get(pos - 1);
@ -165,12 +168,12 @@ pub fn parse_level_3(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), S
new_node.children.push(right_node); new_node.children.push(right_node);
node = new_node; node = new_node;
pos = next_pos; pos = next_pos;
}, }
_ => { _ => {
return Ok((node, pos)); return Ok((node, pos));
}, }
} }
}, }
// 2log(1), )log(1) // 2log(1), )log(1)
Some(&Token::FunctionIdentifier(_)) => { Some(&Token::FunctionIdentifier(_)) => {
let last_token = tokens.get(pos - 1); let last_token = tokens.get(pos - 1);
@ -182,32 +185,34 @@ pub fn parse_level_3(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), S
new_node.children.push(right_node); new_node.children.push(right_node);
node = new_node; node = new_node;
pos = next_pos; pos = next_pos;
}, }
_ => { _ => {
return Ok((node, pos)); return Ok((node, pos));
}, }
} }
}, }
// 2(3), pi(3), )(3) // 2(3), pi(3), )(3)
Some(&Token::Operator(LeftParen)) => { Some(&Token::Operator(LeftParen)) => {
let last_token = tokens.get(pos - 1); let last_token = tokens.get(pos - 1);
match last_token { match last_token {
Some(&Token::Number(_)) | Some(&Token::Constant(_)) | Some(&Token::Operator(RightParen)) => { Some(&Token::Number(_))
| Some(&Token::Constant(_))
| Some(&Token::Operator(RightParen)) => {
let (right_node, next_pos) = parse_level_4(tokens, pos)?; let (right_node, next_pos) = parse_level_4(tokens, pos)?;
let mut new_node = AstNode::new(Token::Operator(Multiply)); let mut new_node = AstNode::new(Token::Operator(Multiply));
new_node.children.push(node); new_node.children.push(node);
new_node.children.push(right_node); new_node.children.push(right_node);
node = new_node; node = new_node;
pos = next_pos; pos = next_pos;
}, }
_ => { _ => {
return Ok((node, pos)); return Ok((node, pos));
}, }
} }
}, }
_ => { _ => {
return Ok((node, pos)); return Ok((node, pos));
}, }
} }
} }
} }
@ -226,10 +231,10 @@ pub fn parse_level_4(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), S
new_node.children.push(right_node); new_node.children.push(right_node);
node = new_node; node = new_node;
pos = next_pos; pos = next_pos;
}, }
_ => { _ => {
return Ok((node, pos)); return Ok((node, pos));
}, }
} }
} }
} }
@ -254,8 +259,8 @@ pub fn parse_level_5(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), S
let mut new_node = AstNode::new(Token::Negative); let mut new_node = AstNode::new(Token::Negative);
new_node.children.push(right_node); new_node.children.push(right_node);
Ok((new_node, next_pos)) Ok((new_node, next_pos))
}, }
_ => parse_level_6(tokens, pos) _ => parse_level_6(tokens, pos),
} }
} }
@ -266,7 +271,9 @@ pub fn parse_level_6(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), S
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::NamedNumber(_)) => { 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.
@ -274,19 +281,19 @@ pub fn parse_level_6(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), S
new_node.children.push(node); new_node.children.push(node);
node = new_node; node = new_node;
pos += 1; pos += 1;
}, }
Some(&Token::Unit(_unit)) => { Some(&Token::Unit(_unit)) => {
// We won't allow units to repeat, like "1min min", so we end the loop if it's found. // We won't allow units to repeat, like "1min min", so we end the loop if it's found.
let mut new_node = AstNode::new(token.unwrap().clone()); let mut new_node = AstNode::new(token.unwrap().clone());
new_node.children.push(node); new_node.children.push(node);
return Ok((new_node, pos + 1)); return Ok((new_node, pos + 1));
}, }
_ => { _ => {
// let's say we parse 1+2. parse_level_7 then returns 1, and token // let's say we parse 1+2. parse_level_7 then returns 1, and token
// is set to plus. Plus has lower precedence than level 4, so we // is set to plus. Plus has lower precedence than level 4, so we
// don't do anything, and pass the number down to a lower precedence. // don't do anything, and pass the number down to a lower precedence.
return Ok((node, pos)); return Ok((node, pos));
}, }
} }
} }
} }
@ -298,20 +305,22 @@ pub fn parse_level_6(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), S
/// [`FunctionIdentifier`](Token::FunctionIdentifier), /// [`FunctionIdentifier`](Token::FunctionIdentifier),
/// [`Paren`](Token::Paren) /// [`Paren`](Token::Paren)
pub fn parse_level_7(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), String> { pub fn parse_level_7(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), String> {
let token: &Token = tokens.get(pos).ok_or(format!("Unexpected end of input at {}", pos))?; let token: &Token = tokens
.get(pos)
.ok_or(format!("Unexpected end of input at {}", pos))?;
match token { match token {
&Token::Number(_number) => { &Token::Number(_number) => {
let node = AstNode::new(token.clone()); let node = AstNode::new(token.clone());
Ok((node, pos + 1)) Ok((node, pos + 1))
}, }
&Token::Unit(_unit) => { &Token::Unit(_unit) => {
let node = AstNode::new(token.clone()); let node = AstNode::new(token.clone());
Ok((node, pos + 1)) Ok((node, pos + 1))
}, }
Token::Constant(_constant) => { Token::Constant(_constant) => {
let node = AstNode::new(token.clone()); let node = AstNode::new(token.clone());
Ok((node, pos + 1)) Ok((node, pos + 1))
}, }
Token::FunctionIdentifier(_function_identifier) => { Token::FunctionIdentifier(_function_identifier) => {
let left_paren_pos = pos + 1; let left_paren_pos = pos + 1;
let left_paren_token = tokens.get(left_paren_pos); let left_paren_token = tokens.get(left_paren_pos);
@ -326,28 +335,36 @@ pub fn parse_level_7(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), S
function_node.children.push(node); function_node.children.push(node);
Ok((function_node, next_pos + 1)) Ok((function_node, next_pos + 1))
} else { } else {
Err(format!("Expected closing paren at {} but found {:?}", next_pos, tokens.get(next_pos))) Err(format!(
"Expected closing paren at {} but found {:?}",
next_pos,
tokens.get(next_pos)
))
} }
}) })
},
_ => {
Err(format!("Expected ( after {} at {:?} but found {:?}", left_paren_pos, token, left_paren_token))
} }
_ => Err(format!(
"Expected ( after {} at {:?} but found {:?}",
left_paren_pos, token, left_paren_token
)),
} }
}, }
Token::Operator(LeftParen) => { Token::Operator(LeftParen) => parse_level_1(tokens, pos + 1).and_then(|(node, next_pos)| {
parse_level_1(tokens, pos + 1).and_then(|(node, next_pos)| { if let Some(&Token::Operator(RightParen)) = tokens.get(next_pos) {
if let Some(&Token::Operator(RightParen)) = tokens.get(next_pos) { let mut paren_node = AstNode::new(Token::Paren);
let mut paren_node = AstNode::new(Token::Paren); paren_node.children.push(node);
paren_node.children.push(node); Ok((paren_node, next_pos + 1))
Ok((paren_node, next_pos + 1)) } else {
} else { Err(format!(
Err(format!("Expected closing paren at {} but found {:?}", next_pos, tokens.get(next_pos))) "Expected closing paren at {} but found {:?}",
} next_pos,
}) tokens.get(next_pos)
}, ))
_ => { }
Err(format!("Unexpected token {:?}, expected paren or number", token)) }),
}, _ => Err(format!(
"Unexpected token {:?}, expected paren or number",
token
)),
} }
} }