diff --git a/kalk/src/parser.rs b/kalk/src/parser.rs index 98fd1e6..3572568 100644 --- a/kalk/src/parser.rs +++ b/kalk/src/parser.rs @@ -569,30 +569,51 @@ fn parse_identifier(context: &mut Context) -> Result { // Reverse the identifier and take two. This gets the last two characters (in reversed order). // Now reverse this to finally get the last two characters in correct order. // It's a bit weird, but it should work for more than ASCII. - let last_two_chars_rev: String = identifier.full_name.chars().rev().take(2).collect(); - let last_two_chars: String = last_two_chars_rev.chars().rev().collect(); - let mut dx = None; + let mut identifier_without_dx: Vec = identifier.full_name.chars().collect(); + let mut last_two_chars = String::new(); + let last_char = identifier_without_dx.pop().unwrap_or_default(); + let first_char = identifier_without_dx.pop().unwrap_or_default(); + last_two_chars.push(first_char); + last_two_chars.push(last_char); + if context.is_in_integral && last_two_chars.starts_with("d") { // If the token contains more than just "dx", // save the dx/dy/du/etc. in a variable, that can be // used further down when splitting the identifier into multiple variables. if identifier.full_name.len() > 2 { // This variable will be used further down in order to separate dx from the rest. - dx = Some(last_two_chars); + let pos = context.pos - 1; + context.pos = pos; + context.tokens[pos] = Token { + kind: TokenKind::Identifier, + value: identifier_without_dx.iter().collect(), + span: (0, 0), + }; + + let left_expr = parse_exponent(context)?; + + // Revert back to how it was before. + context.tokens[pos] = Token { + kind: TokenKind::Identifier, + value: identifier.full_name.to_string(), + span: (0, 0), + }; + + return Ok(Expr::Binary( + Box::new(left_expr), + TokenKind::Star, + Box::new(Expr::Var(Identifier::from_full_name(&last_two_chars))), + )); } else { return Ok(Expr::Var(Identifier::from_full_name(&last_two_chars))); } } - split_into_variables(context, &identifier, dx) + split_into_variables(context, &identifier) } } -fn split_into_variables( - context: &mut Context, - identifier: &Identifier, - dx: Option, -) -> Result { +fn split_into_variables(context: &mut Context, identifier: &Identifier) -> Result { let mut chars: Vec = identifier.pure_name.chars().collect(); let mut left = Expr::Var(Identifier::from_full_name(&chars[0].to_string())); @@ -614,13 +635,6 @@ fn split_into_variables( chars.push(last_char); } - // If there is a an infinitesimal at the end, - // remove it from 'chars', since it should be separate. - if let Some(_) = dx { - chars.pop(); - chars.pop(); - } - // Turn each individual character into its own variable reference. // This parses eg `xy` as `x*y` instead of *one* variable. let mut right_chars = chars.iter().skip(1).peekable(); @@ -657,14 +671,6 @@ fn split_into_variables( left = Expr::Binary(Box::new(left), TokenKind::Star, Box::new(right)); } - if let Some(dx) = dx { - left = Expr::Binary( - Box::new(left), - TokenKind::Star, - Box::new(Expr::Var(Identifier::from_full_name(&dx))), - ); - } - Ok(left) }