mirror of
https://github.com/PaddiM8/kalker.git
synced 2025-06-25 20:21:44 +02:00
Fixed 'dx' parsing in integrals
This commit is contained in:
parent
841317b09b
commit
7ea88895ff
@ -180,15 +180,19 @@ fn build_fn_decl(
|
|||||||
|
|
||||||
fn_decl
|
fn_decl
|
||||||
}
|
}
|
||||||
_ => Stmt::Expr(Box::new(Expr::Binary(
|
_ => {
|
||||||
Box::new(Expr::Binary(
|
let new_binary = Expr::Binary(
|
||||||
Box::new(identifier_expr),
|
Box::new(Expr::Binary(
|
||||||
TokenKind::Star,
|
Box::new(identifier_expr),
|
||||||
Box::new(parameter_expr),
|
TokenKind::Star,
|
||||||
)),
|
Box::new(parameter_expr),
|
||||||
TokenKind::Equals,
|
)),
|
||||||
Box::new(right),
|
TokenKind::Equals,
|
||||||
))),
|
Box::new(right),
|
||||||
|
);
|
||||||
|
|
||||||
|
Stmt::Expr(Box::new(analyse_expr(context, new_binary)?))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,12 +270,12 @@ fn analyse_binary<'a>(
|
|||||||
context.in_conditional = true;
|
context.in_conditional = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let right = analyse_expr(context, right)?;
|
|
||||||
let result = match (&left, &op) {
|
let result = match (&left, &op) {
|
||||||
(_, TokenKind::Equals) if !context.in_conditional => {
|
(_, TokenKind::Equals) if !context.in_conditional => {
|
||||||
// Equation
|
// Equation
|
||||||
context.in_equation = true;
|
context.in_equation = true;
|
||||||
let left = analyse_expr(context, left)?;
|
let left = analyse_expr(context, left)?;
|
||||||
|
let right = analyse_expr(context, right)?;
|
||||||
|
|
||||||
// If it has already been set to false manually somewhere else,
|
// If it has already been set to false manually somewhere else,
|
||||||
// abort and analyse as a comparison instead.
|
// abort and analyse as a comparison instead.
|
||||||
@ -332,7 +336,7 @@ fn analyse_binary<'a>(
|
|||||||
_ => Ok(Expr::Binary(
|
_ => Ok(Expr::Binary(
|
||||||
Box::new(analyse_expr(context, left)?),
|
Box::new(analyse_expr(context, left)?),
|
||||||
op,
|
op,
|
||||||
Box::new(right),
|
Box::new(analyse_expr(context, right)?),
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -370,6 +374,12 @@ fn analyse_var(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let adjacent_factor = if let Some(adjacent_factor) = adjacent_factor {
|
||||||
|
Some(analyse_expr(context, adjacent_factor)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
if context.symbol_table.contains_var(&identifier.pure_name)
|
if context.symbol_table.contains_var(&identifier.pure_name)
|
||||||
|| (identifier.pure_name.len() == 1 && !context.in_equation)
|
|| (identifier.pure_name.len() == 1 && !context.in_equation)
|
||||||
{
|
{
|
||||||
@ -417,7 +427,7 @@ fn analyse_var(
|
|||||||
let last_char = identifier_without_dx.pop().unwrap_or_default();
|
let last_char = identifier_without_dx.pop().unwrap_or_default();
|
||||||
let second_last_char = identifier_without_dx.pop().unwrap_or_default();
|
let second_last_char = identifier_without_dx.pop().unwrap_or_default();
|
||||||
|
|
||||||
if context.in_integral && second_last_char == 'd' && identifier.pure_name.len() > 2 {
|
if context.in_integral && second_last_char == 'd' && identifier.pure_name.len() >= 2 {
|
||||||
let new_identifier: String = identifier_without_dx.iter().collect();
|
let new_identifier: String = identifier_without_dx.iter().collect();
|
||||||
with_adjacent(
|
with_adjacent(
|
||||||
build_dx(context, &new_identifier, last_char)?,
|
build_dx(context, &new_identifier, last_char)?,
|
||||||
@ -425,7 +435,7 @@ fn analyse_var(
|
|||||||
adjacent_exponent,
|
adjacent_exponent,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
build_split_up_vars(context, identifier, adjacent_exponent)
|
build_split_up_vars(context, identifier, adjacent_factor, adjacent_exponent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -458,13 +468,13 @@ fn build_fn_call(
|
|||||||
adjacent_expr: Expr,
|
adjacent_expr: Expr,
|
||||||
log_base: Option<Expr>,
|
log_base: Option<Expr>,
|
||||||
) -> Result<Expr, CalcError> {
|
) -> Result<Expr, CalcError> {
|
||||||
let is_integral = identifier.full_name == "integrate";
|
let is_integral = identifier.pure_name == "integrate";
|
||||||
if is_integral {
|
if is_integral {
|
||||||
context.in_integral = true;
|
context.in_integral = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't perform equation solving on special functions
|
// Don't perform equation solving on special functions
|
||||||
if is_integral || identifier.full_name == "sum" || identifier.full_name == "prod" {
|
if is_integral || identifier.pure_name == "sum" || identifier.pure_name == "prod" {
|
||||||
context.in_equation = false;
|
context.in_equation = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,16 +532,32 @@ fn build_dx(
|
|||||||
name_without_dx: &str,
|
name_without_dx: &str,
|
||||||
char_after_d: char,
|
char_after_d: char,
|
||||||
) -> Result<Expr, CalcError> {
|
) -> Result<Expr, CalcError> {
|
||||||
Ok(Expr::Binary(
|
if name_without_dx.len() == 0 {
|
||||||
Box::new(build_var(context, name_without_dx)),
|
Ok(Expr::Var(Identifier::from_full_name(&format!(
|
||||||
TokenKind::Star,
|
"d{}",
|
||||||
Box::new(build_var(context, &char_after_d.to_string())),
|
char_after_d.to_string()
|
||||||
))
|
))))
|
||||||
|
} else {
|
||||||
|
Ok(Expr::Binary(
|
||||||
|
Box::new(analyse_var(
|
||||||
|
context,
|
||||||
|
Identifier::from_full_name(name_without_dx),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)?),
|
||||||
|
TokenKind::Star,
|
||||||
|
Box::new(Expr::Var(Identifier::from_full_name(&format!(
|
||||||
|
"d{}",
|
||||||
|
char_after_d.to_string()
|
||||||
|
)))),
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_split_up_vars(
|
fn build_split_up_vars(
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
identifier: Identifier,
|
identifier: Identifier,
|
||||||
|
adjacent_factor: Option<Expr>,
|
||||||
adjacent_exponent: Option<Expr>,
|
adjacent_exponent: Option<Expr>,
|
||||||
) -> Result<Expr, CalcError> {
|
) -> Result<Expr, CalcError> {
|
||||||
let mut chars: Vec<char> = identifier.pure_name.chars().collect();
|
let mut chars: Vec<char> = identifier.pure_name.chars().collect();
|
||||||
@ -543,10 +569,14 @@ fn build_split_up_vars(
|
|||||||
// create a function call expression, where that last character
|
// create a function call expression, where that last character
|
||||||
// is the argument.
|
// is the argument.
|
||||||
if context.symbol_table.contains_fn(&identifier_without_last) {
|
if context.symbol_table.contains_fn(&identifier_without_last) {
|
||||||
return Ok(Expr::FnCall(
|
return with_adjacent(
|
||||||
Identifier::from_full_name(&identifier_without_last),
|
Expr::FnCall(
|
||||||
vec![build_var(context, &last_char.to_string())],
|
Identifier::from_full_name(&identifier_without_last),
|
||||||
));
|
vec![build_var(context, &last_char.to_string())],
|
||||||
|
),
|
||||||
|
adjacent_factor,
|
||||||
|
adjacent_exponent,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, re-add the character.
|
// Otherwise, re-add the character.
|
||||||
chars.push(last_char);
|
chars.push(last_char);
|
||||||
|
@ -54,4 +54,19 @@ mod tests {
|
|||||||
fn test_variables() {
|
fn test_variables() {
|
||||||
assert!(is_true(eval_file("variables")));
|
assert!(is_true(eval_file("variables")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_functions() {
|
||||||
|
assert!(is_true(eval_file("functions")));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_derivation() {
|
||||||
|
assert!(is_true(eval_file("derivation")));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_integration() {
|
||||||
|
assert!(is_true(eval_file("integration")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user