Skip to content

Commit

Permalink
Support parsing floats in scientific notation
Browse files Browse the repository at this point in the history
  • Loading branch information
benruijl committed Jun 7, 2024
1 parent 271f855 commit de52f18
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/coefficient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1353,7 +1353,7 @@ mod test {
);
assert_eq!(
r,
"1.5707963267948966192313216916397514420985846996875529104874722*x+21.472450319416851"
"1.5707963267948966192313216916397514420985846996875529104874722*x+21.472450421034925"
);
}

Expand Down
74 changes: 67 additions & 7 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ impl Token {

let ops = ['\0', '^', '+', '*', '-', '(', ')', '/', ',', '[', ']'];
let whitespace = [' ', '\t', '\n', '\r', '\\'];
let forbidden = [';', ':', '&', '!', '%'];
let forbidden = [';', ':', '&', '!', '%', '.'];

let mut char_iter = input.chars();
let mut c = char_iter.next().unwrap_or('\0'); // add EOF as a token
Expand Down Expand Up @@ -680,12 +680,55 @@ impl Token {
}
}
ParseState::Number => {
if c != '_' && c != ' ' && c != '.' && !c.is_ascii_digit() {
let mut last_digit_is_exp = false;
loop {
if c.is_ascii_digit() {
id_buffer.push(c);
c = char_iter.next().unwrap_or('\0');
last_digit_is_exp = false;
continue;
}

if last_digit_is_exp && c != '-' && c != '+' {
// input cannot be a floating point number
// add a multiplication operator, e.g 2.2ex => 2.2*ex

let e = id_buffer.pop().unwrap();
state = ParseState::Any;
stack.push(Token::Number(id_buffer.as_str().into()));
id_buffer.clear();

extra_ops.push(e);
extra_ops.push(c);
c = '*';

break;
}

if c == '\0' {
last_digit_is_exp = false;
break;
}

let digit_is_exp = c == 'e' || c == 'E';

if c != '_' && c != ' ' {
if !digit_is_exp && !last_digit_is_exp && c != '.' {
break;
}

id_buffer.push(c);
}

last_digit_is_exp = digit_is_exp;

c = char_iter.next().unwrap_or('\0');
}

if !last_digit_is_exp {
state = ParseState::Any;
stack.push(Token::Number(id_buffer.as_str().into()));
id_buffer.clear();
} else if c != '_' && c != ' ' {
id_buffer.push(c);
}
}
ParseState::RationalPolynomial => {
Expand Down Expand Up @@ -1247,7 +1290,13 @@ impl Token {
mod test {
use std::sync::Arc;

use crate::{atom::Atom, domains::integer::Z, parser::Token, state::State};
use crate::{
atom::Atom,
domains::integer::Z,
parser::Token,
printer::{AtomPrinter, PrintOptions},
state::State,
};

#[test]
fn pow() {
Expand All @@ -1271,13 +1320,24 @@ mod test {
fn liberal() {
let input = Atom::parse(
"89233_21837281 x
^2 / y + 5",
^2 / y + 5 + 5x",
)
.unwrap();
let res = Atom::parse("8923321837281*x^2*y^-1+5").unwrap();
let res = Atom::parse("8923321837281*x^2*y^-1+5+5x").unwrap();
assert_eq!(input, res);
}

#[test]
fn float() {
let input = Atom::parse("1.2x+1e-5+1e+5 1.1234e23 +2exp(5)").unwrap();

let r = format!(
"{}",
AtomPrinter::new_with_options(input.as_view(), PrintOptions::file())
);
assert_eq!(r, "1.2000000000000000*x+2*exp(5)+1.1234000000000000e28");
}

#[test]
fn square_bracket_function() {
let input = Atom::parse("v1 [v1, v2]+5 + v1[]").unwrap();
Expand Down

0 comments on commit de52f18

Please sign in to comment.