mirror of
https://github.com/PaddiM8/kalker.git
synced 2024-12-14 02:20:57 +01:00
Renamed CalcError to KalkError
This commit is contained in:
parent
1630a8282e
commit
136036f3f0
@ -3,11 +3,10 @@ Overview of features
|
|||||||
Groups: (), ⌈⌉, ⌊⌋, []
|
Groups: (), ⌈⌉, ⌊⌋, []
|
||||||
Pre-defined functions and constants
|
Pre-defined functions and constants
|
||||||
User-defined functions and variables
|
User-defined functions and variables
|
||||||
User-defined units (experimental and limited)
|
|
||||||
Understands fairly ambiguous syntax. Eg. 2sinx + 2xy
|
Understands fairly ambiguous syntax. Eg. 2sinx + 2xy
|
||||||
Syntax highlighting
|
Syntax highlighting
|
||||||
Completion for special symbols on tab
|
Completion for special symbols on tab
|
||||||
Sum functions
|
Sum/prod functions
|
||||||
|
|
||||||
Operators
|
Operators
|
||||||
+, -, *, /
|
+, -, *, /
|
||||||
|
@ -2,7 +2,7 @@ use crate::{
|
|||||||
ast::{ConditionalPiece, Expr, Identifier, RangedVar, Stmt},
|
ast::{ConditionalPiece, Expr, Identifier, RangedVar, Stmt},
|
||||||
inverter,
|
inverter,
|
||||||
lexer::TokenKind,
|
lexer::TokenKind,
|
||||||
parser::{self, CalcError},
|
parser::{self, KalkError},
|
||||||
prelude,
|
prelude,
|
||||||
symbol_table::SymbolTable,
|
symbol_table::SymbolTable,
|
||||||
};
|
};
|
||||||
@ -25,7 +25,7 @@ pub(crate) struct Context<'a> {
|
|||||||
pub(crate) fn analyse_stmt(
|
pub(crate) fn analyse_stmt(
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
statement: Stmt,
|
statement: Stmt,
|
||||||
) -> Result<Stmt, CalcError> {
|
) -> Result<Stmt, KalkError> {
|
||||||
let mut context = Context {
|
let mut context = Context {
|
||||||
symbol_table,
|
symbol_table,
|
||||||
current_function_name: None,
|
current_function_name: None,
|
||||||
@ -77,7 +77,7 @@ pub(crate) fn analyse_stmt(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn analyse_stmt_expr(context: &mut Context, value: Expr) -> Result<Stmt, CalcError> {
|
fn analyse_stmt_expr(context: &mut Context, value: Expr) -> Result<Stmt, KalkError> {
|
||||||
Ok(
|
Ok(
|
||||||
if let Expr::Binary(left, TokenKind::Equals, right) = value {
|
if let Expr::Binary(left, TokenKind::Equals, right) = value {
|
||||||
match *left {
|
match *left {
|
||||||
@ -125,11 +125,11 @@ fn analyse_stmt_expr(context: &mut Context, value: Expr) -> Result<Stmt, CalcErr
|
|||||||
}
|
}
|
||||||
Expr::Var(identifier) if !context.in_conditional => {
|
Expr::Var(identifier) if !context.in_conditional => {
|
||||||
if inverter::contains_var(context.symbol_table, &right, &identifier.full_name) {
|
if inverter::contains_var(context.symbol_table, &right, &identifier.full_name) {
|
||||||
return Err(CalcError::VariableReferencesItself);
|
return Err(KalkError::VariableReferencesItself);
|
||||||
}
|
}
|
||||||
|
|
||||||
if prelude::is_constant(&identifier.full_name) {
|
if prelude::is_constant(&identifier.full_name) {
|
||||||
return Err(CalcError::UnableToOverrideConstant(identifier.pure_name));
|
return Err(KalkError::UnableToOverrideConstant(identifier.pure_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@ -155,7 +155,7 @@ fn build_fn_decl_from_scratch(
|
|||||||
identifier_expr: Expr,
|
identifier_expr: Expr,
|
||||||
parameter_expr: Expr,
|
parameter_expr: Expr,
|
||||||
right: Expr,
|
right: Expr,
|
||||||
) -> Result<Stmt, CalcError> {
|
) -> Result<Stmt, KalkError> {
|
||||||
Ok(match identifier_expr {
|
Ok(match identifier_expr {
|
||||||
Expr::Var(identifier) if !prelude::is_prelude_func(&identifier.full_name) => {
|
Expr::Var(identifier) if !prelude::is_prelude_func(&identifier.full_name) => {
|
||||||
// Check if all the expressions in the parameter_expr are
|
// Check if all the expressions in the parameter_expr are
|
||||||
@ -229,7 +229,7 @@ fn build_fn_decl_from_scratch(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn analyse_expr(context: &mut Context, expr: Expr) -> Result<Expr, CalcError> {
|
fn analyse_expr(context: &mut Context, expr: Expr) -> Result<Expr, KalkError> {
|
||||||
Ok(match expr {
|
Ok(match expr {
|
||||||
Expr::Binary(left, op, right) => analyse_binary(context, *left, op, *right)?,
|
Expr::Binary(left, op, right) => analyse_binary(context, *left, op, *right)?,
|
||||||
Expr::Unary(op, value) => Expr::Unary(op, Box::new(analyse_expr(context, *value)?)),
|
Expr::Unary(op, value) => Expr::Unary(op, Box::new(analyse_expr(context, *value)?)),
|
||||||
@ -291,7 +291,7 @@ fn analyse_binary(
|
|||||||
left: Expr,
|
left: Expr,
|
||||||
op: TokenKind,
|
op: TokenKind,
|
||||||
right: Expr,
|
right: Expr,
|
||||||
) -> Result<Expr, CalcError> {
|
) -> Result<Expr, KalkError> {
|
||||||
let previous_in_conditional = context.in_conditional;
|
let previous_in_conditional = context.in_conditional;
|
||||||
if op == TokenKind::And || op == TokenKind::Or {
|
if op == TokenKind::And || op == TokenKind::Or {
|
||||||
context.in_conditional = true;
|
context.in_conditional = true;
|
||||||
@ -335,7 +335,7 @@ fn analyse_binary(
|
|||||||
// If the inverted expression still contains the variable,
|
// If the inverted expression still contains the variable,
|
||||||
// the equation solving failed.
|
// the equation solving failed.
|
||||||
if inverter::contains_var(context.symbol_table, &inverted, var_name) {
|
if inverter::contains_var(context.symbol_table, &inverted, var_name) {
|
||||||
return Err(CalcError::UnableToSolveEquation);
|
return Err(KalkError::UnableToSolveEquation);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.symbol_table.insert(Stmt::VarDecl(
|
context.symbol_table.insert(Stmt::VarDecl(
|
||||||
@ -440,7 +440,7 @@ fn analyse_comparison_with_var(
|
|||||||
var: Expr,
|
var: Expr,
|
||||||
op: TokenKind,
|
op: TokenKind,
|
||||||
right: Expr,
|
right: Expr,
|
||||||
) -> Result<Expr, CalcError> {
|
) -> Result<Expr, KalkError> {
|
||||||
let right = analyse_expr(context, right)?;
|
let right = analyse_expr(context, right)?;
|
||||||
|
|
||||||
if context.comprehension_vars.is_none() {
|
if context.comprehension_vars.is_none() {
|
||||||
@ -503,7 +503,7 @@ fn analyse_var(
|
|||||||
identifier: Identifier,
|
identifier: Identifier,
|
||||||
adjacent_factor: Option<Expr>,
|
adjacent_factor: Option<Expr>,
|
||||||
adjacent_exponent: Option<Expr>,
|
adjacent_exponent: Option<Expr>,
|
||||||
) -> Result<Expr, CalcError> {
|
) -> Result<Expr, KalkError> {
|
||||||
let adjacent_factor = if let Some(adjacent_factor) = adjacent_factor {
|
let adjacent_factor = if let Some(adjacent_factor) = adjacent_factor {
|
||||||
Some(analyse_expr(context, adjacent_factor)?)
|
Some(analyse_expr(context, adjacent_factor)?)
|
||||||
} else {
|
} else {
|
||||||
@ -582,7 +582,7 @@ fn with_adjacent(
|
|||||||
expr: Expr,
|
expr: Expr,
|
||||||
factor: Option<Expr>,
|
factor: Option<Expr>,
|
||||||
exponent: Option<Expr>,
|
exponent: Option<Expr>,
|
||||||
) -> Result<Expr, CalcError> {
|
) -> Result<Expr, KalkError> {
|
||||||
if let Some(factor) = factor {
|
if let Some(factor) = factor {
|
||||||
Ok(Expr::Binary(
|
Ok(Expr::Binary(
|
||||||
Box::new(expr),
|
Box::new(expr),
|
||||||
@ -600,7 +600,7 @@ fn with_adjacent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_indexed_var(context: &mut Context, identifier: Identifier) -> Result<Expr, CalcError> {
|
fn build_indexed_var(context: &mut Context, identifier: Identifier) -> Result<Expr, KalkError> {
|
||||||
let underscore_pos = identifier.pure_name.find('_').unwrap();
|
let underscore_pos = identifier.pure_name.find('_').unwrap();
|
||||||
let var_name = &identifier.pure_name[0..underscore_pos];
|
let var_name = &identifier.pure_name[0..underscore_pos];
|
||||||
let lowered = &identifier.pure_name[underscore_pos + 1..];
|
let lowered = &identifier.pure_name[underscore_pos + 1..];
|
||||||
@ -621,7 +621,7 @@ fn build_dx(
|
|||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
name_without_dx: &str,
|
name_without_dx: &str,
|
||||||
char_after_d: char,
|
char_after_d: char,
|
||||||
) -> Result<Expr, CalcError> {
|
) -> Result<Expr, KalkError> {
|
||||||
if name_without_dx.is_empty() {
|
if name_without_dx.is_empty() {
|
||||||
Ok(Expr::Var(Identifier::from_full_name(&format!(
|
Ok(Expr::Var(Identifier::from_full_name(&format!(
|
||||||
"d{}",
|
"d{}",
|
||||||
@ -649,7 +649,7 @@ fn build_split_up_vars(
|
|||||||
identifier: Identifier,
|
identifier: Identifier,
|
||||||
adjacent_factor: Option<Expr>,
|
adjacent_factor: Option<Expr>,
|
||||||
adjacent_exponent: Option<Expr>,
|
adjacent_exponent: Option<Expr>,
|
||||||
) -> Result<Expr, CalcError> {
|
) -> Result<Expr, KalkError> {
|
||||||
let mut chars: Vec<char> = identifier.pure_name.chars().collect();
|
let mut chars: Vec<char> = identifier.pure_name.chars().collect();
|
||||||
let last_char = chars.pop().unwrap_or_default();
|
let last_char = chars.pop().unwrap_or_default();
|
||||||
let identifier_without_last: String = chars.iter().collect();
|
let identifier_without_last: String = chars.iter().collect();
|
||||||
@ -737,7 +737,7 @@ fn analyse_fn(
|
|||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
identifier: Identifier,
|
identifier: Identifier,
|
||||||
arguments: Vec<Expr>,
|
arguments: Vec<Expr>,
|
||||||
) -> Result<Expr, CalcError> {
|
) -> Result<Expr, KalkError> {
|
||||||
let is_integral = identifier.pure_name == "integrate";
|
let is_integral = identifier.pure_name == "integrate";
|
||||||
let prev_in_integral = context.in_integral;
|
let prev_in_integral = context.in_integral;
|
||||||
if is_integral {
|
if is_integral {
|
||||||
|
@ -7,13 +7,13 @@ use crate::float;
|
|||||||
use crate::interpreter;
|
use crate::interpreter;
|
||||||
use crate::kalk_value::KalkValue;
|
use crate::kalk_value::KalkValue;
|
||||||
use crate::lexer::TokenKind;
|
use crate::lexer::TokenKind;
|
||||||
use crate::parser::CalcError;
|
use crate::parser::KalkError;
|
||||||
|
|
||||||
pub fn derive_func(
|
pub fn derive_func(
|
||||||
context: &mut interpreter::Context,
|
context: &mut interpreter::Context,
|
||||||
name: &Identifier,
|
name: &Identifier,
|
||||||
argument: KalkValue,
|
argument: KalkValue,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
const H: f64 = 0.000001;
|
const H: f64 = 0.000001;
|
||||||
|
|
||||||
let unit = argument.get_unit().cloned();
|
let unit = argument.get_unit().cloned();
|
||||||
@ -45,7 +45,7 @@ pub fn integrate_with_unknown_variable(
|
|||||||
a: &Expr,
|
a: &Expr,
|
||||||
b: &Expr,
|
b: &Expr,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
let mut integration_variable: Option<&str> = None;
|
let mut integration_variable: Option<&str> = None;
|
||||||
|
|
||||||
// integral(a, b, expr dx)
|
// integral(a, b, expr dx)
|
||||||
@ -59,7 +59,7 @@ pub fn integrate_with_unknown_variable(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if integration_variable.is_none() {
|
if integration_variable.is_none() {
|
||||||
return Err(CalcError::ExpectedDx);
|
return Err(KalkError::ExpectedDx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// "dx" is still in the expression. Set dx = 1, so that it doesn't affect the expression value.
|
// "dx" is still in the expression. Set dx = 1, so that it doesn't affect the expression value.
|
||||||
@ -77,7 +77,7 @@ pub fn integrate(
|
|||||||
b: &Expr,
|
b: &Expr,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
integration_variable: &str,
|
integration_variable: &str,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
Ok(simpsons_rule(context, a, b, expr, integration_variable)?.round_if_needed())
|
Ok(simpsons_rule(context, a, b, expr, integration_variable)?.round_if_needed())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ fn simpsons_rule(
|
|||||||
b_expr: &Expr,
|
b_expr: &Expr,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
integration_variable: &str,
|
integration_variable: &str,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
let mut result_real = float!(0);
|
let mut result_real = float!(0);
|
||||||
let mut result_imaginary = float!(0);
|
let mut result_imaginary = float!(0);
|
||||||
let original_variable_value = context
|
let original_variable_value = context
|
||||||
|
@ -3,7 +3,7 @@ use crate::ast::{Identifier, RangedVar};
|
|||||||
use crate::calculation_result::CalculationResult;
|
use crate::calculation_result::CalculationResult;
|
||||||
use crate::kalk_value::KalkValue;
|
use crate::kalk_value::KalkValue;
|
||||||
use crate::lexer::TokenKind;
|
use crate::lexer::TokenKind;
|
||||||
use crate::parser::CalcError;
|
use crate::parser::KalkError;
|
||||||
use crate::parser::DECL_UNIT;
|
use crate::parser::DECL_UNIT;
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
use crate::{as_number_or_zero, calculus};
|
use crate::{as_number_or_zero, calculus};
|
||||||
@ -44,7 +44,7 @@ impl<'a> Context<'a> {
|
|||||||
pub fn interpret(
|
pub fn interpret(
|
||||||
&mut self,
|
&mut self,
|
||||||
statements: Vec<Stmt>,
|
statements: Vec<Stmt>,
|
||||||
) -> Result<Option<CalculationResult>, CalcError> {
|
) -> Result<Option<CalculationResult>, KalkError> {
|
||||||
for (i, stmt) in statements.iter().enumerate() {
|
for (i, stmt) in statements.iter().enumerate() {
|
||||||
let num = eval_stmt(self, stmt)?;
|
let num = eval_stmt(self, stmt)?;
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ struct SumVar {
|
|||||||
value: i128,
|
value: i128,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_stmt(context: &mut Context, stmt: &Stmt) -> Result<KalkValue, CalcError> {
|
fn eval_stmt(context: &mut Context, stmt: &Stmt) -> Result<KalkValue, KalkError> {
|
||||||
match stmt {
|
match stmt {
|
||||||
Stmt::VarDecl(_, _) => eval_var_decl_stmt(context, stmt),
|
Stmt::VarDecl(_, _) => eval_var_decl_stmt(context, stmt),
|
||||||
Stmt::FnDecl(_, _, _) => eval_fn_decl_stmt(),
|
Stmt::FnDecl(_, _, _) => eval_fn_decl_stmt(),
|
||||||
@ -89,20 +89,20 @@ fn eval_stmt(context: &mut Context, stmt: &Stmt) -> Result<KalkValue, CalcError>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_var_decl_stmt(context: &mut Context, stmt: &Stmt) -> Result<KalkValue, CalcError> {
|
fn eval_var_decl_stmt(context: &mut Context, stmt: &Stmt) -> Result<KalkValue, KalkError> {
|
||||||
context.symbol_table.insert(stmt.clone());
|
context.symbol_table.insert(stmt.clone());
|
||||||
Ok(KalkValue::from(1))
|
Ok(KalkValue::from(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_fn_decl_stmt() -> Result<KalkValue, CalcError> {
|
fn eval_fn_decl_stmt() -> Result<KalkValue, KalkError> {
|
||||||
Ok(KalkValue::from(1)) // Nothing needs to happen here, since the parser will already have added the FnDecl's to the symbol table.
|
Ok(KalkValue::from(1)) // Nothing needs to happen here, since the parser will already have added the FnDecl's to the symbol table.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_unit_decl_stmt() -> Result<KalkValue, CalcError> {
|
fn eval_unit_decl_stmt() -> Result<KalkValue, KalkError> {
|
||||||
Ok(KalkValue::from(1))
|
Ok(KalkValue::from(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_expr_stmt(context: &mut Context, expr: &Expr) -> Result<KalkValue, CalcError> {
|
fn eval_expr_stmt(context: &mut Context, expr: &Expr) -> Result<KalkValue, KalkError> {
|
||||||
eval_expr(context, expr, None)
|
eval_expr(context, expr, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,11 +110,11 @@ pub(crate) fn eval_expr(
|
|||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
unit: Option<&String>,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
if let (Ok(elapsed), Some(timeout)) = (context.start_time.elapsed(), context.timeout) {
|
if let (Ok(elapsed), Some(timeout)) = (context.start_time.elapsed(), context.timeout) {
|
||||||
if elapsed.as_millis() >= timeout {
|
if elapsed.as_millis() >= timeout {
|
||||||
return Err(CalcError::TimedOut);
|
return Err(KalkError::TimedOut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ fn eval_binary_expr(
|
|||||||
op: &TokenKind,
|
op: &TokenKind,
|
||||||
right_expr: &Expr,
|
right_expr: &Expr,
|
||||||
unit: Option<&String>,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
if let TokenKind::ToKeyword = op {
|
if let TokenKind::ToKeyword = op {
|
||||||
// TODO: When the unit conversion function takes a Float instead of Expr,
|
// TODO: When the unit conversion function takes a Float instead of Expr,
|
||||||
// move this to the match statement further down.
|
// move this to the match statement further down.
|
||||||
@ -201,14 +201,14 @@ fn eval_unary_expr(
|
|||||||
op: &TokenKind,
|
op: &TokenKind,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
unit: Option<&String>,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
let num = eval_expr(context, expr, unit)?;
|
let num = eval_expr(context, expr, unit)?;
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
TokenKind::Minus => Ok(num.mul(context, KalkValue::from(-1f64))),
|
TokenKind::Minus => Ok(num.mul(context, KalkValue::from(-1f64))),
|
||||||
TokenKind::Percent => Ok(num.mul(context, KalkValue::from(0.01f64))),
|
TokenKind::Percent => Ok(num.mul(context, KalkValue::from(0.01f64))),
|
||||||
TokenKind::Exclamation => Ok(prelude::special_funcs::factorial(num)),
|
TokenKind::Exclamation => Ok(prelude::special_funcs::factorial(num)),
|
||||||
_ => Err(CalcError::InvalidOperator),
|
_ => Err(KalkError::InvalidOperator),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,7 +216,7 @@ fn eval_unit_expr(
|
|||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
identifier: &str,
|
identifier: &str,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
let angle_unit = &context.angle_unit.clone();
|
let angle_unit = &context.angle_unit.clone();
|
||||||
if (identifier == "rad" || identifier == "deg") && angle_unit != identifier {
|
if (identifier == "rad" || identifier == "deg") && angle_unit != identifier {
|
||||||
return convert_unit(
|
return convert_unit(
|
||||||
@ -235,11 +235,11 @@ pub fn convert_unit(
|
|||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
from_unit: Option<&String>,
|
from_unit: Option<&String>,
|
||||||
to_unit: Option<&String>,
|
to_unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
let (from_unit, to_unit) = if let (Some(from_unit), Some(to_unit)) = (from_unit, to_unit) {
|
let (from_unit, to_unit) = if let (Some(from_unit), Some(to_unit)) = (from_unit, to_unit) {
|
||||||
(from_unit, to_unit)
|
(from_unit, to_unit)
|
||||||
} else {
|
} else {
|
||||||
return Err(CalcError::InvalidUnit);
|
return Err(KalkError::InvalidUnit);
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(Stmt::UnitDecl(_, _, unit_def)) =
|
if let Some(Stmt::UnitDecl(_, _, unit_def)) =
|
||||||
@ -253,7 +253,7 @@ pub fn convert_unit(
|
|||||||
let (real, imaginary, _) = as_number_or_zero!(eval_expr(context, &unit_def, None)?);
|
let (real, imaginary, _) = as_number_or_zero!(eval_expr(context, &unit_def, None)?);
|
||||||
Ok(KalkValue::Number(real, imaginary, Some(to_unit.clone())))
|
Ok(KalkValue::Number(real, imaginary, Some(to_unit.clone())))
|
||||||
} else {
|
} else {
|
||||||
Err(CalcError::InvalidUnit)
|
Err(KalkError::InvalidUnit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,7 +261,7 @@ fn eval_var_expr(
|
|||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
identifier: &Identifier,
|
identifier: &Identifier,
|
||||||
unit: Option<&String>,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
// If there is a constant with this name, return a literal expression with its value
|
// If there is a constant with this name, return a literal expression with its value
|
||||||
if let Some(value) = prelude::CONSTANTS.get(identifier.full_name.as_ref() as &str) {
|
if let Some(value) = prelude::CONSTANTS.get(identifier.full_name.as_ref() as &str) {
|
||||||
return eval_expr(context, &Expr::Literal(*value), unit);
|
return eval_expr(context, &Expr::Literal(*value), unit);
|
||||||
@ -284,7 +284,7 @@ fn eval_var_expr(
|
|||||||
if let Some(Stmt::VarDecl(_, expr)) = var_decl {
|
if let Some(Stmt::VarDecl(_, expr)) = var_decl {
|
||||||
eval_expr(context, &expr, unit)
|
eval_expr(context, &expr, unit)
|
||||||
} else {
|
} else {
|
||||||
Err(CalcError::UndefinedVar(identifier.full_name.clone()))
|
Err(KalkError::UndefinedVar(identifier.full_name.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +294,7 @@ fn eval_literal_expr(
|
|||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
value: f64,
|
value: f64,
|
||||||
unit: Option<&String>,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
let mut float = float!(value);
|
let mut float = float!(value);
|
||||||
float.set_prec(context.precision);
|
float.set_prec(context.precision);
|
||||||
|
|
||||||
@ -307,7 +307,7 @@ fn eval_literal_expr(
|
|||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
value: f64,
|
value: f64,
|
||||||
unit: Option<&String>,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
Ok(KalkValue::Number(float!(value), float!(0), unit.cloned()))
|
Ok(KalkValue::Number(float!(value), float!(0), unit.cloned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +315,7 @@ fn eval_group_expr(
|
|||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
unit: Option<&String>,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
eval_expr(context, expr, unit)
|
eval_expr(context, expr, unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,7 +324,7 @@ pub(crate) fn eval_fn_call_expr(
|
|||||||
identifier: &Identifier,
|
identifier: &Identifier,
|
||||||
expressions: &[Expr],
|
expressions: &[Expr],
|
||||||
unit: Option<&String>,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
// Special functions
|
// Special functions
|
||||||
match identifier.full_name.as_ref() {
|
match identifier.full_name.as_ref() {
|
||||||
"sum" | "prod" => {
|
"sum" | "prod" => {
|
||||||
@ -333,7 +333,7 @@ pub(crate) fn eval_fn_call_expr(
|
|||||||
if let Expr::Var(var_identifier) = &**left {
|
if let Expr::Var(var_identifier) = &**left {
|
||||||
// Make sure exactly 3 arguments were supplied.
|
// Make sure exactly 3 arguments were supplied.
|
||||||
if expressions.len() != 3 {
|
if expressions.len() != 3 {
|
||||||
return Err(CalcError::IncorrectAmountOfArguments(
|
return Err(KalkError::IncorrectAmountOfArguments(
|
||||||
3,
|
3,
|
||||||
"sum/prod".into(),
|
"sum/prod".into(),
|
||||||
expressions.len(),
|
expressions.len(),
|
||||||
@ -369,10 +369,10 @@ pub(crate) fn eval_fn_call_expr(
|
|||||||
if let Expr::Var(integration_variable) = &expressions[3] {
|
if let Expr::Var(integration_variable) = &expressions[3] {
|
||||||
&integration_variable.full_name[1..]
|
&integration_variable.full_name[1..]
|
||||||
} else {
|
} else {
|
||||||
return Err(CalcError::ExpectedDx);
|
return Err(KalkError::ExpectedDx);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
_ => Err(CalcError::IncorrectAmountOfArguments(
|
_ => Err(KalkError::IncorrectAmountOfArguments(
|
||||||
3,
|
3,
|
||||||
"integrate".into(),
|
"integrate".into(),
|
||||||
expressions.len(),
|
expressions.len(),
|
||||||
@ -496,7 +496,7 @@ pub(crate) fn eval_fn_call_expr(
|
|||||||
match stmt_definition {
|
match stmt_definition {
|
||||||
Some(Stmt::FnDecl(_, arguments, fn_body)) => {
|
Some(Stmt::FnDecl(_, arguments, fn_body)) => {
|
||||||
if arguments.len() != expressions.len() {
|
if arguments.len() != expressions.len() {
|
||||||
return Err(CalcError::IncorrectAmountOfArguments(
|
return Err(KalkError::IncorrectAmountOfArguments(
|
||||||
arguments.len(),
|
arguments.len(),
|
||||||
identifier.full_name.clone(),
|
identifier.full_name.clone(),
|
||||||
expressions.len(),
|
expressions.len(),
|
||||||
@ -549,7 +549,7 @@ pub(crate) fn eval_fn_call_expr(
|
|||||||
|
|
||||||
fn_value
|
fn_value
|
||||||
}
|
}
|
||||||
_ => Err(CalcError::UndefinedFn(identifier.full_name.clone())),
|
_ => Err(KalkError::UndefinedFn(identifier.full_name.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -561,7 +561,7 @@ fn eval_loop(
|
|||||||
end_expr: &Expr,
|
end_expr: &Expr,
|
||||||
expression: &Expr,
|
expression: &Expr,
|
||||||
unit: Option<String>,
|
unit: Option<String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
if context.sum_variables.is_none() {
|
if context.sum_variables.is_none() {
|
||||||
context.sum_variables = Some(Vec::new());
|
context.sum_variables = Some(Vec::new());
|
||||||
}
|
}
|
||||||
@ -611,7 +611,7 @@ fn eval_piecewise(
|
|||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
pieces: &[crate::ast::ConditionalPiece],
|
pieces: &[crate::ast::ConditionalPiece],
|
||||||
unit: Option<&String>,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
for piece in pieces {
|
for piece in pieces {
|
||||||
if let KalkValue::Boolean(condition_is_true) = eval_expr(context, &piece.condition, unit)? {
|
if let KalkValue::Boolean(condition_is_true) = eval_expr(context, &piece.condition, unit)? {
|
||||||
if condition_is_true {
|
if condition_is_true {
|
||||||
@ -620,10 +620,10 @@ fn eval_piecewise(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(CalcError::PiecewiseConditionsAreFalse)
|
Err(KalkError::PiecewiseConditionsAreFalse)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_vector(context: &mut Context, values: &[Expr]) -> Result<KalkValue, CalcError> {
|
fn eval_vector(context: &mut Context, values: &[Expr]) -> Result<KalkValue, KalkError> {
|
||||||
let mut eval_values = Vec::new();
|
let mut eval_values = Vec::new();
|
||||||
for value in values {
|
for value in values {
|
||||||
eval_values.push(eval_expr(context, value, None)?);
|
eval_values.push(eval_expr(context, value, None)?);
|
||||||
@ -632,7 +632,7 @@ fn eval_vector(context: &mut Context, values: &[Expr]) -> Result<KalkValue, Calc
|
|||||||
Ok(KalkValue::Vector(eval_values))
|
Ok(KalkValue::Vector(eval_values))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_matrix(context: &mut Context, rows: &[Vec<Expr>]) -> Result<KalkValue, CalcError> {
|
fn eval_matrix(context: &mut Context, rows: &[Vec<Expr>]) -> Result<KalkValue, KalkError> {
|
||||||
let mut eval_rows = Vec::new();
|
let mut eval_rows = Vec::new();
|
||||||
for row in rows {
|
for row in rows {
|
||||||
let mut eval_row = Vec::new();
|
let mut eval_row = Vec::new();
|
||||||
@ -651,12 +651,12 @@ fn eval_indexer(
|
|||||||
var: &Expr,
|
var: &Expr,
|
||||||
index_expressions: &[Expr],
|
index_expressions: &[Expr],
|
||||||
unit: Option<&String>,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
let var_value = eval_expr(context, var, unit)?;
|
let var_value = eval_expr(context, var, unit)?;
|
||||||
match var_value {
|
match var_value {
|
||||||
KalkValue::Vector(values) => {
|
KalkValue::Vector(values) => {
|
||||||
if index_expressions.len() != 1 {
|
if index_expressions.len() != 1 {
|
||||||
return Err(CalcError::IncorrectAmountOfIndexes(
|
return Err(KalkError::IncorrectAmountOfIndexes(
|
||||||
index_expressions.len(),
|
index_expressions.len(),
|
||||||
1,
|
1,
|
||||||
));
|
));
|
||||||
@ -666,7 +666,7 @@ fn eval_indexer(
|
|||||||
if let Some(value) = values.get(index - 1) {
|
if let Some(value) = values.get(index - 1) {
|
||||||
Ok(value.clone())
|
Ok(value.clone())
|
||||||
} else {
|
} else {
|
||||||
Err(CalcError::ItemOfIndexDoesNotExist(vec![index]))
|
Err(KalkError::ItemOfIndexDoesNotExist(vec![index]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KalkValue::Matrix(rows) => {
|
KalkValue::Matrix(rows) => {
|
||||||
@ -676,18 +676,18 @@ fn eval_indexer(
|
|||||||
return if let Some(row) = rows.get(row_index - 1) {
|
return if let Some(row) = rows.get(row_index - 1) {
|
||||||
Ok(KalkValue::Vector(row.clone()))
|
Ok(KalkValue::Vector(row.clone()))
|
||||||
} else {
|
} else {
|
||||||
Err(CalcError::ItemOfIndexDoesNotExist(vec![row_index]))
|
Err(KalkError::ItemOfIndexDoesNotExist(vec![row_index]))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if indices.len() != 2 {
|
if indices.len() != 2 {
|
||||||
return Err(CalcError::IncorrectAmountOfIndexes(indices.len(), 2));
|
return Err(KalkError::IncorrectAmountOfIndexes(indices.len(), 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
let row_index = indices[0];
|
let row_index = indices[0];
|
||||||
let column_index = indices[1];
|
let column_index = indices[1];
|
||||||
if row_index == 0 || column_index == 0 {
|
if row_index == 0 || column_index == 0 {
|
||||||
return Err(CalcError::ItemOfIndexDoesNotExist(vec![
|
return Err(KalkError::ItemOfIndexDoesNotExist(vec![
|
||||||
row_index,
|
row_index,
|
||||||
column_index,
|
column_index,
|
||||||
]));
|
]));
|
||||||
@ -699,26 +699,26 @@ fn eval_indexer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(CalcError::ItemOfIndexDoesNotExist(vec![
|
Err(KalkError::ItemOfIndexDoesNotExist(vec![
|
||||||
row_index,
|
row_index,
|
||||||
column_index,
|
column_index,
|
||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
_ => Err(CalcError::CanOnlyIndexX),
|
_ => Err(KalkError::CanOnlyIndexX),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_indices(context: &mut Context, expressions: &[Expr]) -> Result<Vec<usize>, CalcError> {
|
fn as_indices(context: &mut Context, expressions: &[Expr]) -> Result<Vec<usize>, KalkError> {
|
||||||
let mut indices = Vec::new();
|
let mut indices = Vec::new();
|
||||||
for expr in expressions {
|
for expr in expressions {
|
||||||
let value = eval_expr(context, expr, None)?;
|
let value = eval_expr(context, expr, None)?;
|
||||||
if value.has_imaginary() {
|
if value.has_imaginary() {
|
||||||
return Err(CalcError::CannotIndexByImaginary);
|
return Err(KalkError::CannotIndexByImaginary);
|
||||||
}
|
}
|
||||||
|
|
||||||
let index = value.to_f64() as usize;
|
let index = value.to_f64() as usize;
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
return Err(CalcError::ItemOfIndexDoesNotExist(vec![index]));
|
return Err(KalkError::ItemOfIndexDoesNotExist(vec![index]));
|
||||||
}
|
}
|
||||||
|
|
||||||
indices.push(index);
|
indices.push(index);
|
||||||
@ -732,9 +732,9 @@ fn eval_comprehension(
|
|||||||
left: &Expr,
|
left: &Expr,
|
||||||
conditions: &[Expr],
|
conditions: &[Expr],
|
||||||
vars: &[RangedVar],
|
vars: &[RangedVar],
|
||||||
) -> Result<Vec<KalkValue>, CalcError> {
|
) -> Result<Vec<KalkValue>, KalkError> {
|
||||||
if vars.len() != conditions.len() {
|
if vars.len() != conditions.len() {
|
||||||
return Err(CalcError::InvalidComprehension(String::from("Expected a new variable to be introduced for every condition (conditions are comma separated).")));
|
return Err(KalkError::InvalidComprehension(String::from("Expected a new variable to be introduced for every condition (conditions are comma separated).")));
|
||||||
}
|
}
|
||||||
|
|
||||||
let condition = conditions.first().unwrap();
|
let condition = conditions.first().unwrap();
|
||||||
@ -806,7 +806,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interpret_with_unit(stmt: Stmt) -> Result<Option<CalculationResult>, CalcError> {
|
fn interpret_with_unit(stmt: Stmt) -> Result<Option<CalculationResult>, KalkError> {
|
||||||
let mut symbol_table = SymbolTable::new();
|
let mut symbol_table = SymbolTable::new();
|
||||||
symbol_table
|
symbol_table
|
||||||
.insert(DEG_RAD_UNIT.clone())
|
.insert(DEG_RAD_UNIT.clone())
|
||||||
@ -815,7 +815,7 @@ mod tests {
|
|||||||
context(&mut symbol_table, "rad").interpret(vec![stmt])
|
context(&mut symbol_table, "rad").interpret(vec![stmt])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interpret(stmt: Stmt) -> Result<Option<KalkValue>, CalcError> {
|
fn interpret(stmt: Stmt) -> Result<Option<KalkValue>, KalkError> {
|
||||||
if let Some(result) = interpret_with_unit(stmt)? {
|
if let Some(result) = interpret_with_unit(stmt)? {
|
||||||
Ok(Some(result.get_value()))
|
Ok(Some(result.get_value()))
|
||||||
} else {
|
} else {
|
||||||
@ -976,7 +976,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
interpret(stmt),
|
interpret(stmt),
|
||||||
Err(CalcError::UndefinedVar(String::from("x")))
|
Err(KalkError::UndefinedVar(String::from("x")))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1016,7 +1016,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
interpret(stmt),
|
interpret(stmt),
|
||||||
Err(CalcError::UndefinedFn(String::from("f")))
|
Err(KalkError::UndefinedFn(String::from("f")))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::ast::Identifier;
|
use crate::ast::Identifier;
|
||||||
use crate::ast::{Expr, Stmt};
|
use crate::ast::{Expr, Stmt};
|
||||||
use crate::lexer::TokenKind;
|
use crate::lexer::TokenKind;
|
||||||
use crate::parser::CalcError;
|
use crate::parser::KalkError;
|
||||||
use crate::prelude;
|
use crate::prelude;
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
@ -44,7 +44,7 @@ impl Expr {
|
|||||||
&self,
|
&self,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
unknown_var: &str,
|
unknown_var: &str,
|
||||||
) -> Result<Self, CalcError> {
|
) -> Result<Self, KalkError> {
|
||||||
let target_expr = Expr::Var(Identifier::from_full_name(unknown_var));
|
let target_expr = Expr::Var(Identifier::from_full_name(unknown_var));
|
||||||
let result = invert(target_expr, symbol_table, self, unknown_var);
|
let result = invert(target_expr, symbol_table, self, unknown_var);
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ impl Expr {
|
|||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
target_expr: Expr,
|
target_expr: Expr,
|
||||||
unknown_var: &str,
|
unknown_var: &str,
|
||||||
) -> Result<Self, CalcError> {
|
) -> Result<Self, KalkError> {
|
||||||
let x = invert(target_expr, symbol_table, self, unknown_var)?;
|
let x = invert(target_expr, symbol_table, self, unknown_var)?;
|
||||||
Ok(x.0)
|
Ok(x.0)
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ fn invert(
|
|||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
unknown_var: &str,
|
unknown_var: &str,
|
||||||
) -> Result<(Expr, Expr), CalcError> {
|
) -> Result<(Expr, Expr), KalkError> {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Binary(left, op, right) => {
|
Expr::Binary(left, op, right) => {
|
||||||
invert_binary(target_expr, symbol_table, left, op, right, unknown_var)
|
invert_binary(target_expr, symbol_table, left, op, right, unknown_var)
|
||||||
@ -86,12 +86,12 @@ fn invert(
|
|||||||
unknown_var,
|
unknown_var,
|
||||||
),
|
),
|
||||||
Expr::Literal(_) => Ok((target_expr, expr.clone())),
|
Expr::Literal(_) => Ok((target_expr, expr.clone())),
|
||||||
Expr::Piecewise(_) => Err(CalcError::UnableToInvert(String::from("Piecewise"))),
|
Expr::Piecewise(_) => Err(KalkError::UnableToInvert(String::from("Piecewise"))),
|
||||||
Expr::Vector(_) => Err(CalcError::UnableToInvert(String::from("Vector"))),
|
Expr::Vector(_) => Err(KalkError::UnableToInvert(String::from("Vector"))),
|
||||||
Expr::Matrix(_) => Err(CalcError::UnableToInvert(String::from("Matrix"))),
|
Expr::Matrix(_) => Err(KalkError::UnableToInvert(String::from("Matrix"))),
|
||||||
Expr::Indexer(_, _) => Err(CalcError::UnableToInvert(String::from("Inverter"))),
|
Expr::Indexer(_, _) => Err(KalkError::UnableToInvert(String::from("Inverter"))),
|
||||||
Expr::Comprehension(_, _, _) => {
|
Expr::Comprehension(_, _, _) => {
|
||||||
Err(CalcError::UnableToInvert(String::from("Comprehension")))
|
Err(KalkError::UnableToInvert(String::from("Comprehension")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ fn invert_binary(
|
|||||||
op: &TokenKind,
|
op: &TokenKind,
|
||||||
right: &Expr,
|
right: &Expr,
|
||||||
unknown_var: &str,
|
unknown_var: &str,
|
||||||
) -> Result<(Expr, Expr), CalcError> {
|
) -> Result<(Expr, Expr), KalkError> {
|
||||||
let op_inv = match op {
|
let op_inv = match op {
|
||||||
TokenKind::Plus => TokenKind::Minus,
|
TokenKind::Plus => TokenKind::Minus,
|
||||||
TokenKind::Minus => {
|
TokenKind::Minus => {
|
||||||
@ -194,7 +194,7 @@ fn invert_binary(
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
_ => return Err(CalcError::UnableToInvert(String::new())),
|
_ => return Err(KalkError::UnableToInvert(String::new())),
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the left expression contains the unit, invert the right one instead,
|
// If the left expression contains the unit, invert the right one instead,
|
||||||
@ -203,7 +203,7 @@ fn invert_binary(
|
|||||||
// But if the right expression *also* contains the unit,
|
// But if the right expression *also* contains the unit,
|
||||||
// throw an error, since it can't handle this yet.
|
// throw an error, since it can't handle this yet.
|
||||||
if contains_var(symbol_table, right, unknown_var) {
|
if contains_var(symbol_table, right, unknown_var) {
|
||||||
return Err(CalcError::UnableToInvert(String::from(
|
return Err(KalkError::UnableToInvert(String::from(
|
||||||
"Expressions with several instances of an unknown variable (this might be supported in the future). Try simplifying the expression.",
|
"Expressions with several instances of an unknown variable (this might be supported in the future). Try simplifying the expression.",
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -233,14 +233,14 @@ fn invert_binary(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invert_unary(target_expr: Expr, op: &TokenKind, expr: &Expr) -> Result<(Expr, Expr), CalcError> {
|
fn invert_unary(target_expr: Expr, op: &TokenKind, expr: &Expr) -> Result<(Expr, Expr), KalkError> {
|
||||||
match op {
|
match op {
|
||||||
TokenKind::Minus => Ok((
|
TokenKind::Minus => Ok((
|
||||||
// Make the target expression negative
|
// Make the target expression negative
|
||||||
Expr::Unary(TokenKind::Minus, Box::new(target_expr)),
|
Expr::Unary(TokenKind::Minus, Box::new(target_expr)),
|
||||||
expr.clone(), // And then continue inverting the inner-expression.
|
expr.clone(), // And then continue inverting the inner-expression.
|
||||||
)),
|
)),
|
||||||
_ => Err(CalcError::UnableToInvert(String::new())),
|
_ => Err(KalkError::UnableToInvert(String::new())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +250,7 @@ fn invert_unit(
|
|||||||
identifier: &str,
|
identifier: &str,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
unknown_var: &str,
|
unknown_var: &str,
|
||||||
) -> Result<(Expr, Expr), CalcError> {
|
) -> Result<(Expr, Expr), KalkError> {
|
||||||
let x = Expr::Binary(
|
let x = Expr::Binary(
|
||||||
Box::new(target_expr),
|
Box::new(target_expr),
|
||||||
TokenKind::ToKeyword,
|
TokenKind::ToKeyword,
|
||||||
@ -264,7 +264,7 @@ fn invert_var(
|
|||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
identifier: &Identifier,
|
identifier: &Identifier,
|
||||||
unknown_var: &str,
|
unknown_var: &str,
|
||||||
) -> Result<(Expr, Expr), CalcError> {
|
) -> Result<(Expr, Expr), KalkError> {
|
||||||
if identifier.full_name == unknown_var {
|
if identifier.full_name == unknown_var {
|
||||||
Ok((target_expr, Expr::Var(identifier.clone())))
|
Ok((target_expr, Expr::Var(identifier.clone())))
|
||||||
} else if let Some(Stmt::VarDecl(_, var_expr)) =
|
} else if let Some(Stmt::VarDecl(_, var_expr)) =
|
||||||
@ -282,7 +282,7 @@ fn invert_fn_call(
|
|||||||
identifier: &Identifier,
|
identifier: &Identifier,
|
||||||
arguments: &[Expr],
|
arguments: &[Expr],
|
||||||
unknown_var: &str,
|
unknown_var: &str,
|
||||||
) -> Result<(Expr, Expr), CalcError> {
|
) -> Result<(Expr, Expr), KalkError> {
|
||||||
// If prelude function
|
// If prelude function
|
||||||
match arguments.len() {
|
match arguments.len() {
|
||||||
1 => {
|
1 => {
|
||||||
@ -310,7 +310,7 @@ fn invert_fn_call(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(CalcError::UnableToInvert(format!(
|
return Err(KalkError::UnableToInvert(format!(
|
||||||
"Function '{}'",
|
"Function '{}'",
|
||||||
identifier.full_name
|
identifier.full_name
|
||||||
)));
|
)));
|
||||||
@ -321,7 +321,7 @@ fn invert_fn_call(
|
|||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
if prelude::BINARY_FUNCS.contains_key(identifier.full_name.as_ref() as &str) {
|
if prelude::BINARY_FUNCS.contains_key(identifier.full_name.as_ref() as &str) {
|
||||||
return Err(CalcError::UnableToInvert(format!(
|
return Err(KalkError::UnableToInvert(format!(
|
||||||
"Function '{}'",
|
"Function '{}'",
|
||||||
identifier.full_name
|
identifier.full_name
|
||||||
)));
|
)));
|
||||||
@ -336,12 +336,12 @@ fn invert_fn_call(
|
|||||||
{
|
{
|
||||||
(parameters, body)
|
(parameters, body)
|
||||||
} else {
|
} else {
|
||||||
return Err(CalcError::UndefinedFn(identifier.full_name.clone()));
|
return Err(KalkError::UndefinedFn(identifier.full_name.clone()));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make sure the input is valid.
|
// Make sure the input is valid.
|
||||||
if parameters.len() != arguments.len() {
|
if parameters.len() != arguments.len() {
|
||||||
return Err(CalcError::IncorrectAmountOfArguments(
|
return Err(KalkError::IncorrectAmountOfArguments(
|
||||||
parameters.len(),
|
parameters.len(),
|
||||||
identifier.full_name.clone(),
|
identifier.full_name.clone(),
|
||||||
arguments.len(),
|
arguments.len(),
|
||||||
@ -404,7 +404,7 @@ pub fn contains_var(symbol_table: &SymbolTable, expr: &Expr, var_name: &str) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Multiply an expression into a group.
|
/// Multiply an expression into a group.
|
||||||
fn multiply_into(expr: &Expr, base_expr: &Expr) -> Result<Expr, CalcError> {
|
fn multiply_into(expr: &Expr, base_expr: &Expr) -> Result<Expr, KalkError> {
|
||||||
match base_expr {
|
match base_expr {
|
||||||
Expr::Binary(left, op, right) => match op {
|
Expr::Binary(left, op, right) => match op {
|
||||||
// If + or -, multiply the expression with each term.
|
// If + or -, multiply the expression with each term.
|
||||||
@ -419,7 +419,7 @@ fn multiply_into(expr: &Expr, base_expr: &Expr) -> Result<Expr, CalcError> {
|
|||||||
*op,
|
*op,
|
||||||
right.clone(),
|
right.clone(),
|
||||||
)),
|
)),
|
||||||
_ => Err(CalcError::UnableToInvert(String::new())),
|
_ => Err(KalkError::UnableToInvert(String::new())),
|
||||||
},
|
},
|
||||||
// If it's a literal, just multiply them together.
|
// If it's a literal, just multiply them together.
|
||||||
Expr::Literal(_) | Expr::Var(_) => Ok(Expr::Binary(
|
Expr::Literal(_) | Expr::Var(_) => Ok(Expr::Binary(
|
||||||
@ -427,10 +427,10 @@ fn multiply_into(expr: &Expr, base_expr: &Expr) -> Result<Expr, CalcError> {
|
|||||||
TokenKind::Star,
|
TokenKind::Star,
|
||||||
Box::new(base_expr.clone()),
|
Box::new(base_expr.clone()),
|
||||||
)),
|
)),
|
||||||
Expr::Group(_) => Err(CalcError::UnableToInvert(String::from(
|
Expr::Group(_) => Err(KalkError::UnableToInvert(String::from(
|
||||||
"Parenthesis multiplied with parenthesis (this should be possible in the future).",
|
"Parenthesis multiplied with parenthesis (this should be possible in the future).",
|
||||||
))),
|
))),
|
||||||
_ => Err(CalcError::UnableToInvert(String::new())),
|
_ => Err(KalkError::UnableToInvert(String::new())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ impl Default for Context {
|
|||||||
|
|
||||||
/// Error that occured during parsing or evaluation.
|
/// Error that occured during parsing or evaluation.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum CalcError {
|
pub enum KalkError {
|
||||||
CannotIndexByImaginary,
|
CannotIndexByImaginary,
|
||||||
CanOnlyIndexX,
|
CanOnlyIndexX,
|
||||||
Expected(String),
|
Expected(String),
|
||||||
@ -116,42 +116,42 @@ pub enum CalcError {
|
|||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for CalcError {
|
impl ToString for KalkError {
|
||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
CalcError::CannotIndexByImaginary => String::from("Cannot index by imaginary numbers."),
|
KalkError::CannotIndexByImaginary => String::from("Cannot index by imaginary numbers."),
|
||||||
CalcError::CanOnlyIndexX => String::from("Indexing (getting an item with a specific index) is only possible on vectors and matrices."),
|
KalkError::CanOnlyIndexX => String::from("Indexing (getting an item with a specific index) is only possible on vectors and matrices."),
|
||||||
CalcError::Expected(description) => format!("Expected: {}", description),
|
KalkError::Expected(description) => format!("Expected: {}", description),
|
||||||
CalcError::ExpectedDx => String::from("Expected eg. dx, to specify for which variable the operation is being done to. Example with integration: ∫(0, 1, x dx) or ∫(0, 1, x, dx). You may need to put parenthesis around the expression before dx/dy/du/etc."),
|
KalkError::ExpectedDx => String::from("Expected eg. dx, to specify for which variable the operation is being done to. Example with integration: ∫(0, 1, x dx) or ∫(0, 1, x, dx). You may need to put parenthesis around the expression before dx/dy/du/etc."),
|
||||||
CalcError::ExpectedIf => String::from("Expected 'if', with a condition after it."),
|
KalkError::ExpectedIf => String::from("Expected 'if', with a condition after it."),
|
||||||
CalcError::IncorrectAmountOfArguments(expected, func, got) => format!(
|
KalkError::IncorrectAmountOfArguments(expected, func, got) => format!(
|
||||||
"Expected {} arguments for function {}, but got {}.",
|
"Expected {} arguments for function {}, but got {}.",
|
||||||
expected, func, got
|
expected, func, got
|
||||||
),
|
),
|
||||||
CalcError::IncorrectAmountOfIndexes(expected, got) => format!(
|
KalkError::IncorrectAmountOfIndexes(expected, got) => format!(
|
||||||
"Expected {} indexes but got {}.",
|
"Expected {} indexes but got {}.",
|
||||||
expected, got
|
expected, got
|
||||||
),
|
),
|
||||||
CalcError::ItemOfIndexDoesNotExist(indexes) => format!("Item of index ⟦{}⟧ does not exist.", indexes.iter().map(|x| x.to_string()).collect::<Vec<String>>().join(", ")),
|
KalkError::ItemOfIndexDoesNotExist(indexes) => format!("Item of index ⟦{}⟧ does not exist.", indexes.iter().map(|x| x.to_string()).collect::<Vec<String>>().join(", ")),
|
||||||
CalcError::InconsistentColumnWidths => String::from("Inconsistent column widths. Matrix columns must be the same size."),
|
KalkError::InconsistentColumnWidths => String::from("Inconsistent column widths. Matrix columns must be the same size."),
|
||||||
CalcError::InvalidComprehension(x) => format!("Invalid comprehension: {}", x),
|
KalkError::InvalidComprehension(x) => format!("Invalid comprehension: {}", x),
|
||||||
CalcError::InvalidNumberLiteral(x) => format!("Invalid number literal: '{}'.", x),
|
KalkError::InvalidNumberLiteral(x) => format!("Invalid number literal: '{}'.", x),
|
||||||
CalcError::InvalidOperator => String::from("Invalid operator."),
|
KalkError::InvalidOperator => String::from("Invalid operator."),
|
||||||
CalcError::InvalidUnit => String::from("Invalid unit."),
|
KalkError::InvalidUnit => String::from("Invalid unit."),
|
||||||
CalcError::TimedOut => String::from("Operation took too long."),
|
KalkError::TimedOut => String::from("Operation took too long."),
|
||||||
CalcError::VariableReferencesItself => String::from("Variable references itself."),
|
KalkError::VariableReferencesItself => String::from("Variable references itself."),
|
||||||
CalcError::PiecewiseConditionsAreFalse => String::from("All the conditions in the piecewise are false."),
|
KalkError::PiecewiseConditionsAreFalse => String::from("All the conditions in the piecewise are false."),
|
||||||
CalcError::UnexpectedToken(got, expected) => {
|
KalkError::UnexpectedToken(got, expected) => {
|
||||||
format!("Unexpected token: '{:?}', expected '{:?}'.", got, expected)
|
format!("Unexpected token: '{:?}', expected '{:?}'.", got, expected)
|
||||||
}
|
}
|
||||||
CalcError::UnableToInvert(msg) => format!("Unable to invert: {}", msg),
|
KalkError::UnableToInvert(msg) => format!("Unable to invert: {}", msg),
|
||||||
CalcError::UndefinedFn(name) => format!("Undefined function: '{}'.", name),
|
KalkError::UndefinedFn(name) => format!("Undefined function: '{}'.", name),
|
||||||
CalcError::UndefinedVar(name) => format!("Undefined variable: '{}'.", name),
|
KalkError::UndefinedVar(name) => format!("Undefined variable: '{}'.", name),
|
||||||
CalcError::UnableToParseExpression => String::from("Unable to parse expression."),
|
KalkError::UnableToParseExpression => String::from("Unable to parse expression."),
|
||||||
CalcError::UnableToSolveEquation => String::from("Unable to solve equation."),
|
KalkError::UnableToSolveEquation => String::from("Unable to solve equation."),
|
||||||
CalcError::UnableToOverrideConstant(name) => format!("Unable to override constant: '{}'.", name),
|
KalkError::UnableToOverrideConstant(name) => format!("Unable to override constant: '{}'.", name),
|
||||||
CalcError::UnrecognizedBase => String::from("Unrecognized base."),
|
KalkError::UnrecognizedBase => String::from("Unrecognized base."),
|
||||||
CalcError::Unknown => String::from("Unknown error."),
|
KalkError::Unknown => String::from("Unknown error."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,7 +163,7 @@ pub fn eval(
|
|||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
input: &str,
|
input: &str,
|
||||||
#[cfg(feature = "rug")] precision: u32,
|
#[cfg(feature = "rug")] precision: u32,
|
||||||
) -> Result<Option<CalculationResult>, CalcError> {
|
) -> Result<Option<CalculationResult>, KalkError> {
|
||||||
let statements = parse(context, input)?;
|
let statements = parse(context, input)?;
|
||||||
|
|
||||||
let symbol_table = context.symbol_table.get_mut();
|
let symbol_table = context.symbol_table.get_mut();
|
||||||
@ -186,7 +186,7 @@ pub fn eval(
|
|||||||
/// Parse expressions/declarations and return a syntax tree.
|
/// Parse expressions/declarations and return a syntax tree.
|
||||||
///
|
///
|
||||||
/// `None` will be returned if the last statement is a declaration.
|
/// `None` will be returned if the last statement is a declaration.
|
||||||
pub fn parse(context: &mut Context, input: &str) -> Result<Vec<Stmt>, CalcError> {
|
pub fn parse(context: &mut Context, input: &str) -> Result<Vec<Stmt>, KalkError> {
|
||||||
let mut lexer = Lexer::new(input);
|
let mut lexer = Lexer::new(input);
|
||||||
context.tokens = lexer.lex();
|
context.tokens = lexer.lex();
|
||||||
context.pos = 0;
|
context.pos = 0;
|
||||||
@ -211,7 +211,7 @@ pub fn parse(context: &mut Context, input: &str) -> Result<Vec<Stmt>, CalcError>
|
|||||||
Ok(statements)
|
Ok(statements)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
|
fn parse_stmt(context: &mut Context) -> Result<Stmt, KalkError> {
|
||||||
if match_token(context, TokenKind::UnitKeyword) {
|
if match_token(context, TokenKind::UnitKeyword) {
|
||||||
parse_unit_decl_stmt(context)
|
parse_unit_decl_stmt(context)
|
||||||
} else {
|
} else {
|
||||||
@ -219,7 +219,7 @@ fn parse_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_piecewise(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_piecewise(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
advance(context);
|
advance(context);
|
||||||
skip_newlines(context);
|
skip_newlines(context);
|
||||||
|
|
||||||
@ -250,7 +250,7 @@ fn parse_piecewise(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
|
|
||||||
reached_otherwise = true;
|
reached_otherwise = true;
|
||||||
} else {
|
} else {
|
||||||
return Err(CalcError::ExpectedIf);
|
return Err(KalkError::ExpectedIf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if match_token(context, TokenKind::Semicolon) {
|
if match_token(context, TokenKind::Semicolon) {
|
||||||
@ -269,7 +269,7 @@ fn parse_piecewise(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
Ok(Expr::Piecewise(pieces))
|
Ok(Expr::Piecewise(pieces))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_unit_decl_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
|
fn parse_unit_decl_stmt(context: &mut Context) -> Result<Stmt, KalkError> {
|
||||||
advance(context); // Unit keyword
|
advance(context); // Unit keyword
|
||||||
let identifier = advance(context).clone();
|
let identifier = advance(context).clone();
|
||||||
consume(context, TokenKind::Equals)?;
|
consume(context, TokenKind::Equals)?;
|
||||||
@ -283,7 +283,7 @@ fn parse_unit_decl_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
|
|||||||
let base_unit = if let Some(base_unit) = &context.unit_decl_base_unit {
|
let base_unit = if let Some(base_unit) = &context.unit_decl_base_unit {
|
||||||
base_unit.clone()
|
base_unit.clone()
|
||||||
} else {
|
} else {
|
||||||
return Err(CalcError::InvalidUnit);
|
return Err(KalkError::InvalidUnit);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Automatically create a second unit decl with the expression inverted.
|
// Automatically create a second unit decl with the expression inverted.
|
||||||
@ -302,11 +302,11 @@ fn parse_unit_decl_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
|
|||||||
Ok(stmt)
|
Ok(stmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_expr(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_expr(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
parse_or(context)
|
parse_or(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_comprehension(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_comprehension(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let left = parse_or(context)?;
|
let left = parse_or(context)?;
|
||||||
|
|
||||||
if match_token(context, TokenKind::Colon) {
|
if match_token(context, TokenKind::Colon) {
|
||||||
@ -319,7 +319,7 @@ fn parse_comprehension(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_comprehension_comma(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_comprehension_comma(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let left = parse_or(context)?;
|
let left = parse_or(context)?;
|
||||||
|
|
||||||
if match_token(context, TokenKind::Comma) {
|
if match_token(context, TokenKind::Comma) {
|
||||||
@ -332,7 +332,7 @@ fn parse_comprehension_comma(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_or(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_or(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let left = parse_and(context)?;
|
let left = parse_and(context)?;
|
||||||
|
|
||||||
if match_token(context, TokenKind::Or) {
|
if match_token(context, TokenKind::Or) {
|
||||||
@ -345,7 +345,7 @@ fn parse_or(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_and(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_and(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let left = parse_comparison(context)?;
|
let left = parse_comparison(context)?;
|
||||||
|
|
||||||
if match_token(context, TokenKind::And) {
|
if match_token(context, TokenKind::And) {
|
||||||
@ -358,7 +358,7 @@ fn parse_and(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_comparison(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_comparison(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let mut left = parse_to(context)?;
|
let mut left = parse_to(context)?;
|
||||||
|
|
||||||
// Equality check
|
// Equality check
|
||||||
@ -460,7 +460,7 @@ fn parse_comparison(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_to(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_to(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let left = parse_term(context)?;
|
let left = parse_term(context)?;
|
||||||
|
|
||||||
if match_token(context, TokenKind::ToKeyword) {
|
if match_token(context, TokenKind::ToKeyword) {
|
||||||
@ -477,7 +477,7 @@ fn parse_to(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_term(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_term(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let mut left = parse_factor(context)?;
|
let mut left = parse_factor(context)?;
|
||||||
|
|
||||||
while match_token(context, TokenKind::Plus) || match_token(context, TokenKind::Minus) {
|
while match_token(context, TokenKind::Plus) || match_token(context, TokenKind::Minus) {
|
||||||
@ -491,7 +491,7 @@ fn parse_term(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_factor(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_factor(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let mut left = parse_unit(context)?;
|
let mut left = parse_unit(context)?;
|
||||||
|
|
||||||
if let Expr::Unary(TokenKind::Percent, percent_left) = left.clone() {
|
if let Expr::Unary(TokenKind::Percent, percent_left) = left.clone() {
|
||||||
@ -531,7 +531,7 @@ fn parse_factor(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_unit(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_unit(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let expr = parse_exponent(context)?;
|
let expr = parse_exponent(context)?;
|
||||||
|
|
||||||
if match_token(context, TokenKind::Identifier) {
|
if match_token(context, TokenKind::Identifier) {
|
||||||
@ -547,7 +547,7 @@ fn parse_unit(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
Ok(expr)
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_exponent(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_exponent(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let left = parse_unary(context)?;
|
let left = parse_unary(context)?;
|
||||||
|
|
||||||
if match_token(context, TokenKind::Power) {
|
if match_token(context, TokenKind::Power) {
|
||||||
@ -559,7 +559,7 @@ fn parse_exponent(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_unary(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_unary(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
if match_token(context, TokenKind::Minus) {
|
if match_token(context, TokenKind::Minus) {
|
||||||
let op = advance(context).kind;
|
let op = advance(context).kind;
|
||||||
let expr = Box::new(parse_unary(context)?);
|
let expr = Box::new(parse_unary(context)?);
|
||||||
@ -574,7 +574,7 @@ fn parse_unary(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_indexer(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_indexer(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let left = parse_factorial(context)?;
|
let left = parse_factorial(context)?;
|
||||||
|
|
||||||
if match_token(context, TokenKind::OpenDoubleBracket) {
|
if match_token(context, TokenKind::OpenDoubleBracket) {
|
||||||
@ -593,7 +593,7 @@ fn parse_indexer(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_factorial(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_factorial(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let expr = parse_primary(context)?;
|
let expr = parse_primary(context)?;
|
||||||
|
|
||||||
Ok(if match_token(context, TokenKind::Exclamation) {
|
Ok(if match_token(context, TokenKind::Exclamation) {
|
||||||
@ -604,19 +604,19 @@ fn parse_factorial(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_primary(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_primary(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let expr = match peek(context).kind {
|
let expr = match peek(context).kind {
|
||||||
TokenKind::OpenParenthesis | TokenKind::OpenBracket => parse_vector(context)?,
|
TokenKind::OpenParenthesis | TokenKind::OpenBracket => parse_vector(context)?,
|
||||||
TokenKind::Pipe | TokenKind::OpenCeil | TokenKind::OpenFloor => parse_group_fn(context)?,
|
TokenKind::Pipe | TokenKind::OpenCeil | TokenKind::OpenFloor => parse_group_fn(context)?,
|
||||||
TokenKind::Identifier => parse_identifier(context)?,
|
TokenKind::Identifier => parse_identifier(context)?,
|
||||||
TokenKind::Literal => Expr::Literal(string_to_num(&advance(context).value)?),
|
TokenKind::Literal => Expr::Literal(string_to_num(&advance(context).value)?),
|
||||||
_ => return Err(CalcError::UnableToParseExpression),
|
_ => return Err(KalkError::UnableToParseExpression),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(expr)
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_group_fn(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_group_fn(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let name = match &peek(context).kind {
|
let name = match &peek(context).kind {
|
||||||
TokenKind::Pipe => "abs",
|
TokenKind::Pipe => "abs",
|
||||||
TokenKind::OpenCeil => "ceil",
|
TokenKind::OpenCeil => "ceil",
|
||||||
@ -634,7 +634,7 @@ fn parse_group_fn(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_vector(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_vector(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let kind = advance(context).kind;
|
let kind = advance(context).kind;
|
||||||
|
|
||||||
if kind == TokenKind::OpenBracket {
|
if kind == TokenKind::OpenBracket {
|
||||||
@ -660,7 +660,7 @@ fn parse_vector(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
{
|
{
|
||||||
if let Some(columns) = column_count {
|
if let Some(columns) = column_count {
|
||||||
if columns != items_in_row {
|
if columns != items_in_row {
|
||||||
return Err(CalcError::InconsistentColumnWidths);
|
return Err(KalkError::InconsistentColumnWidths);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
column_count = Some(items_in_row);
|
column_count = Some(items_in_row);
|
||||||
@ -676,7 +676,7 @@ fn parse_vector(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if peek(context).kind == TokenKind::Eof {
|
if peek(context).kind == TokenKind::Eof {
|
||||||
return Err(CalcError::Expected(String::from(
|
return Err(KalkError::Expected(String::from(
|
||||||
"Closing group symbol, eg. )",
|
"Closing group symbol, eg. )",
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -699,7 +699,7 @@ fn parse_vector(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_identifier(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_identifier(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
let identifier = Identifier::from_full_name(&advance(context).value);
|
let identifier = Identifier::from_full_name(&advance(context).value);
|
||||||
|
|
||||||
let mut log_base = None;
|
let mut log_base = None;
|
||||||
@ -775,12 +775,12 @@ fn advance(context: &mut Context) -> &Token {
|
|||||||
previous(context)
|
previous(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consume(context: &mut Context, kind: TokenKind) -> Result<&Token, CalcError> {
|
fn consume(context: &mut Context, kind: TokenKind) -> Result<&Token, KalkError> {
|
||||||
if match_token(context, kind) {
|
if match_token(context, kind) {
|
||||||
return Ok(advance(context));
|
return Ok(advance(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(CalcError::UnexpectedToken(peek(context).kind, kind))
|
Err(KalkError::UnexpectedToken(peek(context).kind, kind))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_at_end(context: &Context) -> bool {
|
fn is_at_end(context: &Context) -> bool {
|
||||||
@ -793,16 +793,16 @@ fn skip_newlines(context: &mut Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_to_num(value: &str) -> Result<f64, CalcError> {
|
fn string_to_num(value: &str) -> Result<f64, KalkError> {
|
||||||
let base = get_base(value)?;
|
let base = get_base(value)?;
|
||||||
if let Some(result) = crate::radix::parse_float_radix(&value.replace(" ", ""), base) {
|
if let Some(result) = crate::radix::parse_float_radix(&value.replace(" ", ""), base) {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
} else {
|
} else {
|
||||||
Err(CalcError::InvalidNumberLiteral(value.into()))
|
Err(KalkError::InvalidNumberLiteral(value.into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_base(value: &str) -> Result<u8, CalcError> {
|
fn get_base(value: &str) -> Result<u8, KalkError> {
|
||||||
let underscore_pos = if let Some(i) = value.find('_') {
|
let underscore_pos = if let Some(i) = value.find('_') {
|
||||||
i
|
i
|
||||||
} else {
|
} else {
|
||||||
@ -813,7 +813,7 @@ fn get_base(value: &str) -> Result<u8, CalcError> {
|
|||||||
if let Some(base) = crate::text_utils::parse_subscript(subscript) {
|
if let Some(base) = crate::text_utils::parse_subscript(subscript) {
|
||||||
Ok(base)
|
Ok(base)
|
||||||
} else {
|
} else {
|
||||||
Err(CalcError::UnrecognizedBase)
|
Err(KalkError::UnrecognizedBase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -825,7 +825,7 @@ mod tests {
|
|||||||
use crate::test_helpers::*;
|
use crate::test_helpers::*;
|
||||||
use wasm_bindgen_test::*;
|
use wasm_bindgen_test::*;
|
||||||
|
|
||||||
fn parse_with_context(context: &mut Context, tokens: Vec<Token>) -> Result<Stmt, CalcError> {
|
fn parse_with_context(context: &mut Context, tokens: Vec<Token>) -> Result<Stmt, KalkError> {
|
||||||
context.tokens = tokens;
|
context.tokens = tokens;
|
||||||
context.pos = 0;
|
context.pos = 0;
|
||||||
|
|
||||||
@ -834,7 +834,7 @@ mod tests {
|
|||||||
analysis::analyse_stmt(symbol_table, parsed)
|
analysis::analyse_stmt(symbol_table, parsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(tokens: Vec<Token>) -> Result<Stmt, CalcError> {
|
fn parse(tokens: Vec<Token>) -> Result<Stmt, KalkError> {
|
||||||
let mut context = Context::new();
|
let mut context = Context::new();
|
||||||
context.tokens = tokens;
|
context.tokens = tokens;
|
||||||
context.pos = 0;
|
context.pos = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user