Switch indentation to tabs

This commit is contained in:
Kasper 2022-09-12 00:47:20 +02:00
parent 1bb3819350
commit 4ac7e74c6b
No known key found for this signature in database
GPG Key ID: 356D5C59EDCEC2D1
8 changed files with 3800 additions and 3792 deletions

View File

@ -1 +1 @@
tab_spaces=2
hard_tabs=true

View File

@ -11,8 +11,8 @@ use decimal::d128;
/// Evaluate an [`AstNode`] into a [`Number`]
pub fn evaluate(ast: &AstNode) -> Result<Number, String> {
let answer = evaluate_node(ast)?;
Ok(answer)
let answer = evaluate_node(ast)?;
Ok(answer)
}
/// Returns the factorial of a [`struct@d128`] up to `1000!` without doing any math
@ -21,287 +21,289 @@ pub fn evaluate(ast: &AstNode) -> Result<Number, String> {
///
/// All return values of this function are hard-coded.
pub fn factorial(input: d128) -> d128 {
lookup_factorial(input.into())
lookup_factorial(input.into())
}
/// Returns the square root of a [`struct@d128`]
pub fn sqrt(input: d128) -> d128 {
let mut n = d128!(1);
let half = d128!(0.5);
for _ in 0..10 {
n = (n + input / n) * half;
}
n
let mut n = d128!(1);
let half = d128!(0.5);
for _ in 0..10 {
n = (n + input / n) * half;
}
n
}
/// Returns the cube root of a [`struct@d128`]
pub fn cbrt(input: d128) -> d128 {
let mut n: d128 = input;
// hope that 20 iterations makes it accurate enough
let three = d128!(3);
for _ in 0..20 {
let z2 = n * n;
n = n - ((n * z2 - input) / (three * z2));
}
n
let mut n: d128 = input;
// hope that 20 iterations makes it accurate enough
let three = d128!(3);
for _ in 0..20 {
let z2 = n * n;
n = n - ((n * z2 - input) / (three * z2));
}
n
}
/// Returns the sine of a [`struct@d128`]
pub fn sin(mut input: d128) -> d128 {
let pi = d128!(3.141592653589793238462643383279503);
let pi2 = d128!(6.283185307179586476925286766559006);
let pi = d128!(3.141592653589793238462643383279503);
let pi2 = d128!(6.283185307179586476925286766559006);
input %= pi2;
input %= pi2;
let negative_correction = if input.is_negative() {
input -= pi;
d128!(-1)
} else {
d128!(1)
};
let negative_correction = if input.is_negative() {
input -= pi;
d128!(-1)
} else {
d128!(1)
};
let one = d128!(1);
let two = d128!(2);
let neg_one = -one;
let one = d128!(1);
let two = d128!(2);
let neg_one = -one;
let precision = 37;
let mut result = d128!(0);
for i_int in 0..precision {
let i = d128::from(i_int);
let calc_result = two * i + one;
result += neg_one.pow(i) * (input.pow(calc_result) / factorial(calc_result));
}
let precision = 37;
let mut result = d128!(0);
for i_int in 0..precision {
let i = d128::from(i_int);
let calc_result = two * i + one;
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`]
pub fn cos(input: d128) -> d128 {
let half_pi = d128!(1.570796326794896619231321691639751);
sin(half_pi - input)
let half_pi = d128!(1.570796326794896619231321691639751);
sin(half_pi - input)
}
/// Returns the tangent of a [`struct@d128`]
pub fn tan(input: d128) -> d128 {
sin(input) / cos(input)
sin(input) / cos(input)
}
/// Evaluate an [`AstNode`] into a [`Number`]
fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
let token = &ast_node.token;
let children = &ast_node.children;
match token {
Token::Number(number) => Ok(Number::new(*number, Unit::NoUnit)),
Token::Constant(constant) => match constant {
Pi => Ok(Number::new(
d128!(3.141592653589793238462643383279503),
Unit::NoUnit,
)),
E => Ok(Number::new(
d128!(2.718281828459045235360287471352662),
Unit::NoUnit,
)),
},
Token::FunctionIdentifier(function) => {
let child_node = children.get(0).ok_or("Paren has no child[0]")?;
let child_answer = evaluate_node(child_node)?;
match function {
Cbrt => {
if child_answer.unit.category() == UnitType::NoType {
let result = cbrt(child_answer.value);
Ok(Number::new(result, child_answer.unit))
} else {
Err("log() only accepts UnitType::NoType".to_string())
}
}
Sqrt => {
if child_answer.unit.category() == UnitType::NoType {
let result = sqrt(child_answer.value);
Ok(Number::new(result, child_answer.unit))
} else {
Err("log() only accepts UnitType::NoType".to_string())
}
}
Log => {
if child_answer.unit.category() == UnitType::NoType {
let result = child_answer.value.log10();
Ok(Number::new(result, child_answer.unit))
} else {
Err("log() only accepts UnitType::NoType".to_string())
}
}
Ln => {
if child_answer.unit.category() == UnitType::NoType {
let result = child_answer.value.ln();
Ok(Number::new(result, child_answer.unit))
} else {
Err("ln() only accepts UnitType::NoType".to_string())
}
}
Exp => {
if child_answer.unit.category() == UnitType::NoType {
let result = child_answer.value.exp(child_answer.value);
Ok(Number::new(result, child_answer.unit))
} else {
Err("exp() only accepts UnitType::NoType".to_string())
}
}
Round => {
// .quantize() rounds .5 to nearest even integer, so we correct that
let mut result = child_answer.value.quantize(d128!(1));
let rounding_change = result - child_answer.value;
// If the result was rounded down by 0.5, correct by +1
if rounding_change == d128!(-0.5) {
result += d128!(1);
}
Ok(Number::new(result, child_answer.unit))
}
Ceil => {
let mut result = child_answer.value.quantize(d128!(1));
let rounding_change = result - child_answer.value;
if rounding_change.is_negative() {
result += d128!(1);
}
Ok(Number::new(result, child_answer.unit))
}
Floor => {
let mut result = child_answer.value.quantize(d128!(1));
let rounding_change = result - child_answer.value;
if !rounding_change.is_negative() {
result -= d128!(1);
}
Ok(Number::new(result, child_answer.unit))
}
Abs => {
let mut result = child_answer.value.abs();
let rounding_change = result - child_answer.value;
if rounding_change == d128!(-0.5) {
result += d128!(1);
}
Ok(Number::new(result, child_answer.unit))
}
Sin => {
let result = sin(child_answer.value);
Ok(Number::new(result, child_answer.unit))
}
Cos => {
let result = cos(child_answer.value);
Ok(Number::new(result, child_answer.unit))
}
Tan => {
let result = tan(child_answer.value);
Ok(Number::new(result, child_answer.unit))
}
}
}
Token::Unit(unit) => {
let child_node = children.get(0).ok_or("Unit has no child[0]")?;
let child_answer = evaluate_node(child_node)?;
Ok(Number::new(child_answer.value, *unit))
}
Token::Negative => {
let child_node = children.get(0).ok_or("Negative has no child[0]")?;
let child_answer = evaluate_node(child_node)?;
Ok(Number::new(-child_answer.value, child_answer.unit))
}
Token::Paren => {
let child_node = children.get(0).ok_or("Paren has no child[0]")?;
evaluate_node(child_node)
}
Token::UnaryOperator(operator) => {
let child_node = children
.get(0)
.ok_or(format!("Token {:?} has no child[0]", token))?;
let child_answer = evaluate_node(child_node)?;
match operator {
Percent => Ok(Number::new(
child_answer.value / d128!(100),
child_answer.unit,
)),
Factorial => {
let result = factorial(child_answer.value);
if result.is_nan() {
return Err("Can only perform factorial on integers from 0 to 1000".to_string());
}
Ok(Number::new(result, child_answer.unit))
}
}
}
Token::NamedNumber(named_number) => {
let child_node = children
.get(0)
.ok_or(format!("Token {:?} has no child[0]", token))?;
let named_number_value = lookup_named_number(named_number);
if let Token::NamedNumber(child_nn) = &child_node.token {
let child_nn_value = lookup_named_number(child_nn);
if child_nn_value > named_number_value {
return Err(format!("Unexpected smaller token {:?}", token));
}
}
let child_answer = evaluate_node(child_node)?;
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))?;
let token = &ast_node.token;
let children = &ast_node.children;
match token {
Token::Number(number) => Ok(Number::new(*number, Unit::NoUnit)),
Token::Constant(constant) => match constant {
Pi => Ok(Number::new(
d128!(3.141592653589793238462643383279503),
Unit::NoUnit,
)),
E => Ok(Number::new(
d128!(2.718281828459045235360287471352662),
Unit::NoUnit,
)),
},
Token::FunctionIdentifier(function) => {
let child_node = children.get(0).ok_or("Paren has no child[0]")?;
let child_answer = evaluate_node(child_node)?;
match function {
Cbrt => {
if child_answer.unit.category() == UnitType::NoType {
let result = cbrt(child_answer.value);
Ok(Number::new(result, child_answer.unit))
} else {
Err("log() only accepts UnitType::NoType".to_string())
}
}
Sqrt => {
if child_answer.unit.category() == UnitType::NoType {
let result = sqrt(child_answer.value);
Ok(Number::new(result, child_answer.unit))
} else {
Err("log() only accepts UnitType::NoType".to_string())
}
}
Log => {
if child_answer.unit.category() == UnitType::NoType {
let result = child_answer.value.log10();
Ok(Number::new(result, child_answer.unit))
} else {
Err("log() only accepts UnitType::NoType".to_string())
}
}
Ln => {
if child_answer.unit.category() == UnitType::NoType {
let result = child_answer.value.ln();
Ok(Number::new(result, child_answer.unit))
} else {
Err("ln() only accepts UnitType::NoType".to_string())
}
}
Exp => {
if child_answer.unit.category() == UnitType::NoType {
let result = child_answer.value.exp(child_answer.value);
Ok(Number::new(result, child_answer.unit))
} else {
Err("exp() only accepts UnitType::NoType".to_string())
}
}
Round => {
// .quantize() rounds .5 to nearest even integer, so we correct that
let mut result = child_answer.value.quantize(d128!(1));
let rounding_change = result - child_answer.value;
// If the result was rounded down by 0.5, correct by +1
if rounding_change == d128!(-0.5) {
result += d128!(1);
}
Ok(Number::new(result, child_answer.unit))
}
Ceil => {
let mut result = child_answer.value.quantize(d128!(1));
let rounding_change = result - child_answer.value;
if rounding_change.is_negative() {
result += d128!(1);
}
Ok(Number::new(result, child_answer.unit))
}
Floor => {
let mut result = child_answer.value.quantize(d128!(1));
let rounding_change = result - child_answer.value;
if !rounding_change.is_negative() {
result -= d128!(1);
}
Ok(Number::new(result, child_answer.unit))
}
Abs => {
let mut result = child_answer.value.abs();
let rounding_change = result - child_answer.value;
if rounding_change == d128!(-0.5) {
result += d128!(1);
}
Ok(Number::new(result, child_answer.unit))
}
Sin => {
let result = sin(child_answer.value);
Ok(Number::new(result, child_answer.unit))
}
Cos => {
let result = cos(child_answer.value);
Ok(Number::new(result, child_answer.unit))
}
Tan => {
let result = tan(child_answer.value);
Ok(Number::new(result, child_answer.unit))
}
}
}
Token::Unit(unit) => {
let child_node = children.get(0).ok_or("Unit has no child[0]")?;
let child_answer = evaluate_node(child_node)?;
Ok(Number::new(child_answer.value, *unit))
}
Token::Negative => {
let child_node = children.get(0).ok_or("Negative has no child[0]")?;
let child_answer = evaluate_node(child_node)?;
Ok(Number::new(-child_answer.value, child_answer.unit))
}
Token::Paren => {
let child_node = children.get(0).ok_or("Paren has no child[0]")?;
evaluate_node(child_node)
}
Token::UnaryOperator(operator) => {
let child_node = children
.get(0)
.ok_or(format!("Token {:?} has no child[0]", token))?;
let child_answer = evaluate_node(child_node)?;
match operator {
Percent => Ok(Number::new(
child_answer.value / d128!(100),
child_answer.unit,
)),
Factorial => {
let result = factorial(child_answer.value);
if result.is_nan() {
return Err(
"Can only perform factorial on integers from 0 to 1000".to_string()
);
}
Ok(Number::new(result, child_answer.unit))
}
}
}
Token::NamedNumber(named_number) => {
let child_node = children
.get(0)
.ok_or(format!("Token {:?} has no child[0]", token))?;
let named_number_value = lookup_named_number(named_number);
if let Token::NamedNumber(child_nn) = &child_node.token {
let child_nn_value = lookup_named_number(child_nn);
if child_nn_value > named_number_value {
return Err(format!("Unexpected smaller token {:?}", token));
}
}
let child_answer = evaluate_node(child_node)?;
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))?;
match operator {
To => {
if let Token::Unit(right_unit) = right_child.token {
let left = evaluate_node(left_child)?;
let result = convert(left, right_unit)?;
Ok(result)
} else {
Err("Right side of To operator needs to be a unit".to_string())
}
}
Of => {
let left = evaluate_node(left_child)?;
let right = evaluate_node(right_child)?;
if left.unit == Unit::NoUnit {
Ok(Number::new(left.value * right.value, right.unit))
} else {
Err("Left side of the Of operator must be NoUnit".to_string())
}
}
}
}
Token::Operator(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))?;
let left = evaluate_node(left_child)?;
let right = evaluate_node(right_child)?;
match operator {
Plus => Ok(add(left, right)?),
Minus => Ok(subtract(left, right)?),
Multiply => {
Ok(multiply(left, right)?)
// }
}
Divide => {
Ok(divide(left, right)?)
// }
}
Modulo => {
Ok(modulo(left, right)?)
// }
}
Caret => {
Ok(pow(left, right)?)
// }
}
_ => Err(format!("Unexpected operator {:?}", operator)),
}
}
_ => Err(format!("Unexpected token {:?}", token)),
}
match operator {
To => {
if let Token::Unit(right_unit) = right_child.token {
let left = evaluate_node(left_child)?;
let result = convert(left, right_unit)?;
Ok(result)
} else {
Err("Right side of To operator needs to be a unit".to_string())
}
}
Of => {
let left = evaluate_node(left_child)?;
let right = evaluate_node(right_child)?;
if left.unit == Unit::NoUnit {
Ok(Number::new(left.value * right.value, right.unit))
} else {
Err("Left side of the Of operator must be NoUnit".to_string())
}
}
}
}
Token::Operator(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))?;
let left = evaluate_node(left_child)?;
let right = evaluate_node(right_child)?;
match operator {
Plus => Ok(add(left, right)?),
Minus => Ok(subtract(left, right)?),
Multiply => {
Ok(multiply(left, right)?)
// }
}
Divide => {
Ok(divide(left, right)?)
// }
}
Modulo => {
Ok(modulo(left, right)?)
// }
}
Caret => {
Ok(pow(left, right)?)
// }
}
_ => Err(format!("Unexpected operator {:?}", operator)),
}
}
_ => Err(format!("Unexpected token {:?}", token)),
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
#![cfg_attr(
feature = "cargo-clippy",
allow(
clippy::comparison_chain,
clippy::if_same_then_else,
clippy::match_like_matches_macro,
)
feature = "cargo-clippy",
allow(
clippy::comparison_chain,
clippy::if_same_then_else,
clippy::match_like_matches_macro,
)
)]
//! calculation + conversion
//!
@ -63,110 +63,110 @@ pub mod units;
/// };
/// ```
pub struct Number {
/// The number part of a [`Number`] struct
pub value: d128,
/// The unit of a [`Number`] struct. This can be [`NoType`](units::UnitType::NoType)
pub unit: Unit,
/// The number part of a [`Number`] struct
pub value: d128,
/// The unit of a [`Number`] struct. This can be [`NoType`](units::UnitType::NoType)
pub unit: Unit,
}
impl Number {
pub const fn new(value: d128, unit: Unit) -> Number {
Number { value, unit }
}
pub const fn new(value: d128, unit: Unit) -> Number {
Number { value, unit }
}
}
impl Display for Number {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// 0.2/0.01 results in 2E+1, but if we add zero it becomes 20
let fixed_value = self.value + d128!(0);
let output = match self.unit {
Unit::NoUnit => format!("{}", fixed_value),
unit => format!("{} {:?}", fixed_value, unit),
};
write!(f, "{}", output)
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// 0.2/0.01 results in 2E+1, but if we add zero it becomes 20
let fixed_value = self.value + d128!(0);
let output = match self.unit {
Unit::NoUnit => format!("{}", fixed_value),
unit => format!("{} {:?}", fixed_value, unit),
};
write!(f, "{}", output)
}
}
#[derive(Clone, Debug, PartialEq)]
/// Math operators like [`Multiply`](Operator::Multiply), parentheses, etc.
pub enum Operator {
Plus,
Minus,
Multiply,
Divide,
Modulo,
Caret,
LeftParen, // lexer only
RightParen, // lexer only
Plus,
Minus,
Multiply,
Divide,
Modulo,
Caret,
LeftParen, // lexer only
RightParen, // lexer only
}
#[derive(Clone, Debug, PartialEq)]
/// Unary operators like [`Percent`](UnaryOperator::Percent) and [`Factorial`](UnaryOperator::Factorial).
pub enum UnaryOperator {
Percent,
Factorial,
Percent,
Factorial,
}
#[derive(Clone, Debug, PartialEq)]
/// A Text operator like [`To`](TextOperator::To) or [`Of`](TextOperator::Of).
pub enum TextOperator {
To,
Of,
To,
Of,
}
#[derive(Clone, Debug, PartialEq)]
/// A named number like [`Million`](NamedNumber::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,
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, PartialEq)]
/// A constant like [`Pi`](Constant::Pi) or [`E`](Constant::E).
pub enum Constant {
Pi,
E,
Pi,
E,
}
#[derive(Clone, Debug, PartialEq)]
/// Functions identifiers like [`Sqrt`](FunctionIdentifier::Sqrt), [`Sin`](FunctionIdentifier::Sin), [`Round`](FunctionIdentifier::Round), etc.
pub enum FunctionIdentifier {
Sqrt,
Cbrt,
Sqrt,
Cbrt,
Log,
Ln,
Exp,
Log,
Ln,
Exp,
Round,
Ceil,
Floor,
Abs,
Round,
Ceil,
Floor,
Abs,
Sin,
Cos,
Tan,
Sin,
Cos,
Tan,
}
#[derive(Clone, Debug, PartialEq)]
@ -178,15 +178,15 @@ pub enum FunctionIdentifier {
/// dependingon them, turns it into a [`Percent`](UnaryOperator::Percent) or
/// [`Modulo`](Operator::Modulo) [`Token`].
pub enum LexerKeyword {
Per,
PercentChar,
In,
DoubleQuotes,
Mercury,
Hg,
PoundForce,
Force,
Revolution,
Per,
PercentChar,
In,
DoubleQuotes,
Mercury,
Hg,
PoundForce,
Force,
Revolution,
}
#[derive(Clone, Debug, PartialEq)]
@ -194,29 +194,29 @@ pub enum LexerKeyword {
///
/// Strings can be divided up into these tokens by the [`lexer`], and then put into the [`parser`].
pub enum Token {
Operator(Operator),
UnaryOperator(UnaryOperator),
Number(d128),
FunctionIdentifier(FunctionIdentifier),
Constant(Constant),
/// Used by the parser only
Paren,
/// Used by the lexer only
Per,
/// 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),
Operator(Operator),
UnaryOperator(UnaryOperator),
Number(d128),
FunctionIdentifier(FunctionIdentifier),
Constant(Constant),
/// Used by the parser only
Paren,
/// Used by the lexer only
Per,
/// 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),
}
#[macro_export]
macro_rules! numtok {
( $num:literal ) => {
Token::Number(d128!($num))
};
( $num:literal ) => {
Token::Number(d128!($num))
};
}
/// Evaluates a string into a resulting [`Number`].
@ -237,48 +237,52 @@ macro_rules! numtok {
/// }
/// ```
pub fn eval(
input: &str,
allow_trailing_operators: bool,
default_degree: Unit,
verbose: bool,
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) {
Ok(tokens) => {
let lex_time = Instant::now().duration_since(lex_start).as_nanos() as f32;
if verbose {
println!("Lexed TokenVector: {:?}", tokens);
}
match lexer::lex(input, allow_trailing_operators, default_degree) {
Ok(tokens) => {
let lex_time = Instant::now().duration_since(lex_start).as_nanos() as f32;
if verbose {
println!("Lexed TokenVector: {:?}", tokens);
}
let parse_start = Instant::now();
match parser::parse(&tokens) {
Ok(ast) => {
let parse_time = Instant::now().duration_since(parse_start).as_nanos() as f32;
if verbose {
println!("Parsed AstNode: {:#?}", ast);
}
let parse_start = Instant::now();
match parser::parse(&tokens) {
Ok(ast) => {
let parse_time = Instant::now().duration_since(parse_start).as_nanos() as f32;
if verbose {
println!("Parsed AstNode: {:#?}", ast);
}
let eval_start = Instant::now();
match evaluator::evaluate(&ast) {
Ok(answer) => {
let eval_time = Instant::now().duration_since(eval_start).as_nanos() as f32;
let eval_start = Instant::now();
match evaluator::evaluate(&ast) {
Ok(answer) => {
let eval_time =
Instant::now().duration_since(eval_start).as_nanos() as f32;
if verbose {
println!("Evaluated value: {} {:?}", answer.value, answer.unit);
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 evaluation", eval_time / 1000.0 / 1000.0);
}
if verbose {
println!("Evaluated value: {} {:?}", answer.value, answer.unit);
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 evaluation",
eval_time / 1000.0 / 1000.0
);
}
Ok(answer)
}
Err(e) => Err(format!("Eval error: {}", e)),
}
}
Err(e) => Err(format!("Parsing error: {}", e)),
}
}
Err(e) => Err(format!("Lexing error: {}", e)),
}
Ok(answer)
}
Err(e) => Err(format!("Eval error: {}", e)),
}
}
Err(e) => Err(format!("Parsing error: {}", e)),
}
}
Err(e) => Err(format!("Lexing error: {}", e)),
}
}

File diff suppressed because it is too large Load Diff

View File

@ -6,70 +6,70 @@ use std::process::exit;
const VERSION: &str = env!("CARGO_PKG_VERSION");
fn print_help() {
println!(concat!(
"Usage: cpc '<expression>' [options]",
"\n",
"\nOptions:",
"\n --verbose Enable verbose logging",
"\n --version Show cpc version",
"\n --help Show this help page",
));
println!(concat!(
"Usage: cpc '<expression>' [options]",
"\n",
"\nOptions:",
"\n --verbose Enable verbose logging",
"\n --version Show cpc version",
"\n --help Show this help page",
));
}
fn get_args() -> env::Args {
let mut args = env::args();
args.next(); // skip binary name
args
let mut args = env::args();
args.next(); // skip binary name
args
}
/// CLI interface
fn main() {
// parse these first so they work if there are unexpected args
for arg in get_args() {
match arg.as_str() {
"--version" => {
println!("{}", VERSION);
exit(0);
}
"--help" => {
print_help();
exit(0);
}
_ => {}
}
}
let mut verbose = false;
let mut expression_opt = None;
for arg in get_args() {
match arg.as_str() {
"-v" | "--verbose" => verbose = true,
_ => {
if expression_opt.is_none() {
expression_opt = Some(arg);
} else {
eprintln!("Unexpected argument: {}", arg);
exit(1);
}
}
}
}
let expression = match expression_opt {
Some(expression) => expression,
None => {
print_help();
exit(0);
}
};
// parse these first so they work if there are unexpected args
for arg in get_args() {
match arg.as_str() {
"--version" => {
println!("{}", VERSION);
exit(0);
}
"--help" => {
print_help();
exit(0);
}
_ => {}
}
}
let mut verbose = false;
let mut expression_opt = None;
for arg in get_args() {
match arg.as_str() {
"-v" | "--verbose" => verbose = true,
_ => {
if expression_opt.is_none() {
expression_opt = Some(arg);
} else {
eprintln!("Unexpected argument: {}", arg);
exit(1);
}
}
}
}
let expression = match expression_opt {
Some(expression) => expression,
None => {
print_help();
exit(0);
}
};
match eval(&expression, true, Unit::Celsius, verbose) {
Ok(answer) => {
if !verbose {
println!("{}", answer);
}
}
Err(e) => {
eprintln!("{}", e);
exit(1);
}
}
match eval(&expression, true, Unit::Celsius, verbose) {
Ok(answer) => {
if !verbose {
println!("{}", answer);
}
}
Err(e) => {
eprintln!("{}", e);
exit(1);
}
}
}

View File

@ -7,295 +7,295 @@ use crate::UnaryOperator::{Factorial, Percent};
#[derive(Debug)]
/// A struct with a [`Token`](AstNode::token) and [`AstNode`] [`children`](AstNode::children)
pub struct AstNode {
/// The children of the [`AstNode`]
pub children: Vec<AstNode>,
/// The token of the [`AstNode`]
pub token: Token,
/// The children of the [`AstNode`]
pub children: Vec<AstNode>,
/// The token of the [`AstNode`]
pub token: Token,
}
impl AstNode {
pub const fn new(token: Token) -> AstNode {
AstNode {
children: Vec::new(),
token,
}
}
pub const fn new(token: Token) -> AstNode {
AstNode {
children: Vec::new(),
token,
}
}
}
/// Parse [`Token`]s into an Abstract Syntax Tree ([`AstNode`])
pub fn parse(tokens: &[Token]) -> Result<AstNode, String> {
parse_level_1(tokens, 0).and_then(|(ast, next_pos)| {
if next_pos == tokens.len() {
Ok(ast)
} else {
Err(format!(
"Expected end of input, found {:?} at {}",
tokens[next_pos], next_pos
))
}
})
parse_level_1(tokens, 0).and_then(|(ast, next_pos)| {
if next_pos == tokens.len() {
Ok(ast)
} else {
Err(format!(
"Expected end of input, found {:?} at {}",
tokens[next_pos], next_pos
))
}
})
}
// level 1 precedence (lowest): to, of
/// Parse [`To`](crate::TextOperator::To) and [`Of`](crate::TextOperator::Of)
pub fn parse_level_1(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), String> {
// do higher precedences first, then come back down
let (mut node, mut pos) = parse_level_2(tokens, pos)?;
// now we loop through the next tokens
loop {
let token = tokens.get(pos);
match token {
// if there's a match, we once again do higher precedences, then come
// back down again and continue the loop
Some(&Token::TextOperator(To)) | Some(&Token::TextOperator(Of)) => {
let (right_node, next_pos) = parse_level_2(tokens, pos + 1)?;
let mut new_node = AstNode::new(token.unwrap().clone());
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
// if there's no match, we go down to a lower precedence (or, in this
// case, we're done)
_ => {
return Ok((node, pos));
}
}
}
// do higher precedences first, then come back down
let (mut node, mut pos) = parse_level_2(tokens, pos)?;
// now we loop through the next tokens
loop {
let token = tokens.get(pos);
match token {
// if there's a match, we once again do higher precedences, then come
// back down again and continue the loop
Some(&Token::TextOperator(To)) | Some(&Token::TextOperator(Of)) => {
let (right_node, next_pos) = parse_level_2(tokens, pos + 1)?;
let mut new_node = AstNode::new(token.unwrap().clone());
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
// if there's no match, we go down to a lower precedence (or, in this
// case, we're done)
_ => {
return Ok((node, pos));
}
}
}
}
// level 2 precedence: +, -
/// Parse [`Plus`](crate::Operator::Plus) and [`Minus`](crate::Operator::Minus)
pub fn parse_level_2(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), String> {
let (mut node, mut pos) = parse_level_3(tokens, pos)?;
loop {
let token = tokens.get(pos);
match token {
Some(&Token::Operator(Plus)) | Some(&Token::Operator(Minus)) => {
let (right_node, next_pos) = parse_level_3(tokens, pos + 1)?;
let mut new_node = AstNode::new(token.unwrap().clone());
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
_ => {
return Ok((node, pos));
}
}
}
let (mut node, mut pos) = parse_level_3(tokens, pos)?;
loop {
let token = tokens.get(pos);
match token {
Some(&Token::Operator(Plus)) | Some(&Token::Operator(Minus)) => {
let (right_node, next_pos) = parse_level_3(tokens, pos + 1)?;
let mut new_node = AstNode::new(token.unwrap().clone());
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
_ => {
return Ok((node, pos));
}
}
}
}
// level 3 precedence: *, /, modulo, implicative multiplication, foot-inch 6'4"
/// Parse [`Multiply`](crate::Operator::Multiply), [`Divide`](crate::Operator::Divide), [`Modulo`](crate::Operator::Modulo) and implicative multiplication (for example`2pi`)
pub fn parse_level_3(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), String> {
// parse foot-inch syntax 6'4"
let token0 = tokens.get(pos);
if let Some(Token::Number(_number)) = token0 {
let token1 = tokens.get(pos + 1);
if let Some(Token::Unit(Foot)) = token1 {
let token2 = tokens.get(pos + 2);
if let Some(Token::Number(_number)) = token2 {
let token3 = tokens.get(pos + 3);
if let Some(Token::Unit(Inch)) = token3 {
let new_node = AstNode {
children: vec![
AstNode {
children: vec![AstNode::new(token0.unwrap().clone())],
token: Token::Unit(Foot),
},
AstNode {
children: vec![AstNode::new(token2.unwrap().clone())],
token: Token::Unit(Inch),
},
],
token: Token::Operator(Plus),
};
return Ok((new_node, pos + 4));
}
}
}
}
// parse foot-inch syntax 6'4"
let token0 = tokens.get(pos);
if let Some(Token::Number(_number)) = token0 {
let token1 = tokens.get(pos + 1);
if let Some(Token::Unit(Foot)) = token1 {
let token2 = tokens.get(pos + 2);
if let Some(Token::Number(_number)) = token2 {
let token3 = tokens.get(pos + 3);
if let Some(Token::Unit(Inch)) = token3 {
let new_node = AstNode {
children: vec![
AstNode {
children: vec![AstNode::new(token0.unwrap().clone())],
token: Token::Unit(Foot),
},
AstNode {
children: vec![AstNode::new(token2.unwrap().clone())],
token: Token::Unit(Inch),
},
],
token: Token::Operator(Plus),
};
return Ok((new_node, pos + 4));
}
}
}
}
let (mut node, mut pos) = parse_level_4(tokens, pos)?;
let (mut node, mut pos) = parse_level_4(tokens, pos)?;
loop {
let token = tokens.get(pos);
match token {
Some(&Token::Operator(Multiply))
| Some(&Token::Operator(Divide))
| Some(&Token::Operator(Modulo)) => {
let (right_node, next_pos) = parse_level_4(tokens, pos + 1)?;
let mut new_node = AstNode::new(token.unwrap().clone());
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
loop {
let token = tokens.get(pos);
match token {
Some(&Token::Operator(Multiply))
| Some(&Token::Operator(Divide))
| Some(&Token::Operator(Modulo)) => {
let (right_node, next_pos) = parse_level_4(tokens, pos + 1)?;
let mut new_node = AstNode::new(token.unwrap().clone());
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
// 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
// other operators.
// Note that this match statement matches an AstNode token, but the
// matches nested inside check the [`Token`]s. That's why we for example
// match a FunctionIdentifier, and inside that, a RightParen.
// 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
// other operators.
// Note that this match statement matches an AstNode token, but the
// matches nested inside check the [`Token`]s. That's why we for example
// match a FunctionIdentifier, and inside that, a RightParen.
// pi2, )2
Some(&Token::Number(_)) => {
let last_token = tokens.get(pos - 1);
match last_token {
Some(&Token::Constant(_)) | Some(&Token::Operator(RightParen)) => {
let (right_node, next_pos) = parse_level_4(tokens, pos)?;
let mut new_node = AstNode::new(Token::Operator(Multiply));
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
_ => {
return Ok((node, pos));
}
}
}
// 2pi, )pi
Some(&Token::Constant(_)) => {
let last_token = tokens.get(pos - 1);
match last_token {
Some(&Token::Number(_)) | Some(&Token::Operator(RightParen)) => {
let (right_node, next_pos) = parse_level_4(tokens, pos)?;
let mut new_node = AstNode::new(Token::Operator(Multiply));
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
_ => {
return Ok((node, pos));
}
}
}
// 2log(1), )log(1)
Some(&Token::FunctionIdentifier(_)) => {
let last_token = tokens.get(pos - 1);
match last_token {
Some(&Token::Number(_)) | Some(&Token::Operator(RightParen)) => {
let (right_node, next_pos) = parse_level_4(tokens, pos)?;
let mut new_node = AstNode::new(Token::Operator(Multiply));
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
_ => {
return Ok((node, pos));
}
}
}
// 2(3), pi(3), )(3)
Some(&Token::Operator(LeftParen)) => {
let last_token = tokens.get(pos - 1);
match last_token {
Some(&Token::Number(_))
| Some(&Token::Constant(_))
| Some(&Token::Operator(RightParen)) => {
let (right_node, next_pos) = parse_level_4(tokens, pos)?;
let mut new_node = AstNode::new(Token::Operator(Multiply));
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
_ => {
return Ok((node, pos));
}
}
}
_ => {
return Ok((node, pos));
}
}
}
// pi2, )2
Some(&Token::Number(_)) => {
let last_token = tokens.get(pos - 1);
match last_token {
Some(&Token::Constant(_)) | Some(&Token::Operator(RightParen)) => {
let (right_node, next_pos) = parse_level_4(tokens, pos)?;
let mut new_node = AstNode::new(Token::Operator(Multiply));
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
_ => {
return Ok((node, pos));
}
}
}
// 2pi, )pi
Some(&Token::Constant(_)) => {
let last_token = tokens.get(pos - 1);
match last_token {
Some(&Token::Number(_)) | Some(&Token::Operator(RightParen)) => {
let (right_node, next_pos) = parse_level_4(tokens, pos)?;
let mut new_node = AstNode::new(Token::Operator(Multiply));
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
_ => {
return Ok((node, pos));
}
}
}
// 2log(1), )log(1)
Some(&Token::FunctionIdentifier(_)) => {
let last_token = tokens.get(pos - 1);
match last_token {
Some(&Token::Number(_)) | Some(&Token::Operator(RightParen)) => {
let (right_node, next_pos) = parse_level_4(tokens, pos)?;
let mut new_node = AstNode::new(Token::Operator(Multiply));
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
_ => {
return Ok((node, pos));
}
}
}
// 2(3), pi(3), )(3)
Some(&Token::Operator(LeftParen)) => {
let last_token = tokens.get(pos - 1);
match last_token {
Some(&Token::Number(_))
| Some(&Token::Constant(_))
| Some(&Token::Operator(RightParen)) => {
let (right_node, next_pos) = parse_level_4(tokens, pos)?;
let mut new_node = AstNode::new(Token::Operator(Multiply));
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
_ => {
return Ok((node, pos));
}
}
}
_ => {
return Ok((node, pos));
}
}
}
}
// level 4 precedence: ^
/// Parse [`Caret`](crate::Operator::Caret)
pub fn parse_level_4(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), String> {
let (mut node, mut pos) = parse_level_5(tokens, pos)?;
loop {
let token = tokens.get(pos);
match token {
Some(&Token::Operator(Caret)) => {
let (right_node, next_pos) = parse_level_5(tokens, pos + 1)?;
let mut new_node = AstNode::new(token.unwrap().clone());
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
_ => {
return Ok((node, pos));
}
}
}
let (mut node, mut pos) = parse_level_5(tokens, pos)?;
loop {
let token = tokens.get(pos);
match token {
Some(&Token::Operator(Caret)) => {
let (right_node, next_pos) = parse_level_5(tokens, pos + 1)?;
let mut new_node = AstNode::new(token.unwrap().clone());
new_node.children.push(node);
new_node.children.push(right_node);
node = new_node;
pos = next_pos;
}
_ => {
return Ok((node, pos));
}
}
}
}
// level 5 precedence: - (as in -5, but not 4-5)
/// Parse [`Negative`](Token::Negative)
pub fn parse_level_5(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), String> {
// Here we parse the negative unary operator. If the current token
// is a minus, we wrap the right_node inside a Negative AstNode.
//
// Why doesn't this parse 4-5? First, we will first get a 4. In which case,
// we just return the result of parse_level_6(), which will include the pos
// of +. This will then go down to level 2 and be parsed as a normal minus
// operator.
// The difference is that in other levels, we parse higher priorities
// immediately, while in this one we instead check if the current token
// is a minus, and if not, we then return the higher priority as normal.
let token = tokens.get(pos);
match token {
Some(&Token::Operator(Minus)) => {
let (right_node, next_pos) = parse_level_6(tokens, pos + 1)?;
let mut new_node = AstNode::new(Token::Negative);
new_node.children.push(right_node);
Ok((new_node, next_pos))
}
_ => parse_level_6(tokens, pos),
}
// Here we parse the negative unary operator. If the current token
// is a minus, we wrap the right_node inside a Negative AstNode.
//
// Why doesn't this parse 4-5? First, we will first get a 4. In which case,
// we just return the result of parse_level_6(), which will include the pos
// of +. This will then go down to level 2 and be parsed as a normal minus
// operator.
// The difference is that in other levels, we parse higher priorities
// immediately, while in this one we instead check if the current token
// is a minus, and if not, we then return the higher priority as normal.
let token = tokens.get(pos);
match token {
Some(&Token::Operator(Minus)) => {
let (right_node, next_pos) = parse_level_6(tokens, pos + 1)?;
let mut new_node = AstNode::new(Token::Negative);
new_node.children.push(right_node);
Ok((new_node, next_pos))
}
_ => parse_level_6(tokens, pos),
}
}
// level 6 precedence: !, percent, units attached to values
/// Parse [`Factorial`](crate::UnaryOperator::Factorial) and [`Percent`](crate::UnaryOperator::Percent)
pub fn parse_level_6(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), String> {
let (mut node, mut pos) = parse_level_7(tokens, pos)?;
loop {
let token = tokens.get(pos);
match token {
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.
let mut new_node = AstNode::new(token.unwrap().clone());
new_node.children.push(node);
node = new_node;
pos += 1;
}
Some(&Token::Unit(_unit)) => {
// 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());
new_node.children.push(node);
return Ok((new_node, pos + 1));
}
_ => {
// 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
// don't do anything, and pass the number down to a lower precedence.
return Ok((node, pos));
}
}
}
let (mut node, mut pos) = parse_level_7(tokens, pos)?;
loop {
let token = tokens.get(pos);
match token {
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.
let mut new_node = AstNode::new(token.unwrap().clone());
new_node.children.push(node);
node = new_node;
pos += 1;
}
Some(&Token::Unit(_unit)) => {
// 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());
new_node.children.push(node);
return Ok((new_node, pos + 1));
}
_ => {
// 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
// don't do anything, and pass the number down to a lower precedence.
return Ok((node, pos));
}
}
}
}
// level 7 precedence: numbers, standalone units, constants, functions, parens
@ -305,66 +305,68 @@ pub fn parse_level_6(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), S
/// [`FunctionIdentifier`](Token::FunctionIdentifier),
/// [`Paren`](Token::Paren)
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))?;
match token {
&Token::Number(_number) => {
let node = AstNode::new(token.clone());
Ok((node, pos + 1))
}
&Token::Unit(_unit) => {
let node = AstNode::new(token.clone());
Ok((node, pos + 1))
}
Token::Constant(_constant) => {
let node = AstNode::new(token.clone());
Ok((node, pos + 1))
}
Token::FunctionIdentifier(_function_identifier) => {
let left_paren_pos = pos + 1;
let left_paren_token = tokens.get(left_paren_pos);
// check if '(' comes after function identifier, like 'log('
match left_paren_token {
Some(&Token::Operator(LeftParen)) => {
// parse everything inside as you would with normal parentheses,
// then put it inside an ast node.
parse_level_1(tokens, left_paren_pos + 1).and_then(|(node, next_pos)| {
if let Some(&Token::Operator(RightParen)) = tokens.get(next_pos) {
let mut function_node = AstNode::new(token.clone());
function_node.children.push(node);
Ok((function_node, next_pos + 1))
} else {
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
)),
}
}
Token::Operator(LeftParen) => parse_level_1(tokens, pos + 1).and_then(|(node, next_pos)| {
if let Some(&Token::Operator(RightParen)) = tokens.get(next_pos) {
let mut paren_node = AstNode::new(Token::Paren);
paren_node.children.push(node);
Ok((paren_node, next_pos + 1))
} else {
Err(format!(
"Expected closing paren at {} but found {:?}",
next_pos,
tokens.get(next_pos)
))
}
}),
_ => Err(format!(
"Unexpected token {:?}, expected paren or number",
token
)),
}
let token: &Token = tokens
.get(pos)
.ok_or(format!("Unexpected end of input at {}", pos))?;
match token {
&Token::Number(_number) => {
let node = AstNode::new(token.clone());
Ok((node, pos + 1))
}
&Token::Unit(_unit) => {
let node = AstNode::new(token.clone());
Ok((node, pos + 1))
}
Token::Constant(_constant) => {
let node = AstNode::new(token.clone());
Ok((node, pos + 1))
}
Token::FunctionIdentifier(_function_identifier) => {
let left_paren_pos = pos + 1;
let left_paren_token = tokens.get(left_paren_pos);
// check if '(' comes after function identifier, like 'log('
match left_paren_token {
Some(&Token::Operator(LeftParen)) => {
// parse everything inside as you would with normal parentheses,
// then put it inside an ast node.
parse_level_1(tokens, left_paren_pos + 1).and_then(|(node, next_pos)| {
if let Some(&Token::Operator(RightParen)) = tokens.get(next_pos) {
let mut function_node = AstNode::new(token.clone());
function_node.children.push(node);
Ok((function_node, next_pos + 1))
} else {
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
)),
}
}
Token::Operator(LeftParen) => {
parse_level_1(tokens, pos + 1).and_then(|(node, next_pos)| {
if let Some(&Token::Operator(RightParen)) = tokens.get(next_pos) {
let mut paren_node = AstNode::new(Token::Paren);
paren_node.children.push(node);
Ok((paren_node, next_pos + 1))
} else {
Err(format!(
"Expected closing paren at {} but found {:?}",
next_pos,
tokens.get(next_pos)
))
}
})
}
_ => Err(format!(
"Unexpected token {:?}, expected paren or number",
token
)),
}
}

File diff suppressed because it is too large Load Diff