Change parse_number and fix float interpretation

This commit is contained in:
imaqtkatt 2024-08-02 17:39:52 -03:00
parent c426087d09
commit dcc3642ab1
5 changed files with 92 additions and 38 deletions

View File

@ -1518,80 +1518,85 @@ pub trait ParserCommons<'a>: Parser<'a> {
let radix = match self.peek_many(2) {
Some("0x") => {
self.advance_many(2);
16
Radix::Hex
}
Some("0b") => {
self.advance_many(2);
2
Radix::Bin
}
_ => 10,
_ => Radix::Dec,
};
let num_str = self.take_while(move |c| c.is_digit(radix) || c == '_');
let num_str = self.take_while(move |c| c.is_digit(radix as u32) || c == '_');
let num_str = num_str.chars().filter(|c| *c != '_').collect::<String>();
let next_is_hex = self.peek_one().map_or(false, |c| "0123456789abcdefABCDEF".contains(c));
if next_is_hex || num_str.is_empty() {
let base = match radix {
16 => "hexadecimal",
10 => "decimal",
2 => "binary",
_ => unreachable!(),
};
self.expected(format!("valid {base} digit").as_str())
self.expected(format!("valid {} digit", radix.to_string()).as_str())
} else {
u32::from_str_radix(&num_str, radix).map_err(|e| e.to_string())
u32::from_str_radix(&num_str, radix as u32).map_err(|e| e.to_string())
}
}
fn u32_with_radix(&mut self, radix: Radix) -> ParseResult<u32> {
let num_str = self.take_while(move |c| c.is_digit(radix as u32) || c == '_');
let num_str = num_str.chars().filter(|c| *c != '_').collect::<String>();
let next_is_hex = self.peek_one().map_or(false, |c| "0123456789abcdefABCDEF".contains(c));
if next_is_hex || num_str.is_empty() {
self.expected(format!("valid {} digit", radix.to_string()).as_str())
} else {
u32::from_str_radix(&num_str, radix as u32).map_err(|e| e.to_string())
}
}
fn parse_number(&mut self) -> ParseResult<Num> {
let ini_idx = *self.index();
// Parses sign
let sgn = if self.try_consume_exactly("+") {
let sign = if self.try_consume_exactly("+") {
Some(1)
} else if self.try_consume_exactly("-") {
Some(-1)
} else {
None
};
// Parses main value
let num = self.parse_u32()?;
// Parses frac value (Float type)
// TODO: Will lead to some rounding errors
// TODO: Doesn't cover very large/small numbers
let fra = if let Some('.') = self.peek_one() {
let radix = match self.peek_many(2) {
Some("0x") => {
self.advance_many(2);
Radix::Hex
}
Some("0b") => {
self.advance_many(2);
Radix::Bin
}
_ => Radix::Dec,
};
let num = self.u32_with_radix(radix)?;
let frac = if let Some('.') = self.peek_one() {
self.advance_one();
let ini_idx = *self.index();
let fra = self.parse_u32()? as f32;
let fra = self.u32_with_radix(radix)?;
let end_idx = *self.index();
let fra = fra / 10f32.powi((end_idx - ini_idx) as i32);
let fra = fra as f32 / (radix.to_f32()).powi((end_idx - ini_idx) as i32);
Some(fra)
} else {
None
};
// F24
if let Some(fra) = fra {
let sgn = sgn.unwrap_or(1);
return Ok(Num::F24(sgn as f32 * (num as f32 + fra)));
if let Some(frac) = frac {
let sign = sign.unwrap_or(1);
return Ok(Num::F24(sign as f32 * (num as f32 + frac)));
}
// I24
if let Some(sgn) = sgn {
let num = sgn * num as i32;
if let Some(sign) = sign {
let num = sign as i32 * num as i32;
if !(-0x00800000..=0x007fffff).contains(&num) {
return self.num_range_err(ini_idx, "I24");
}
return Ok(Num::I24(num));
} else {
if num >= 1 << 24 {
return self.num_range_err(ini_idx, "U24");
}
Ok(Num::U24(num))
}
// U24
if num >= 1 << 24 {
return self.num_range_err(ini_idx, "U24");
}
Ok(Num::U24(num))
}
fn num_range_err<T>(&mut self, ini_idx: usize, typ: &str) -> ParseResult<T> {
@ -1659,3 +1664,30 @@ pub trait ParserCommons<'a>: Parser<'a> {
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Radix {
Bin = 2,
Dec = 10,
Hex = 16,
}
impl Radix {
fn to_f32(&self) -> f32 {
match self {
Radix::Bin => 2.,
Radix::Dec => 10.,
Radix::Hex => 16.,
}
}
}
impl ToString for Radix {
fn to_string(&self) -> String {
match self {
Radix::Bin => "binary".to_string(),
Radix::Dec => "decimal".to_string(),
Radix::Hex => "hexadecimal".to_string(),
}
}
}

View File

@ -0,0 +1,2 @@
def main:
return 0xA.0xA

View File

@ -0,0 +1,2 @@
def main:
return [0x12.129, 0x0.2, 0b101.101, 0xAAAAAAAA.AAAAAAAA]

View File

@ -0,0 +1,9 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/parse_file/bad_floating.bend
---
Errors:
In tests/golden_tests/parse_file/bad_floating.bend :
- expected: newline
- detected:
 2 | return 0xA.0xA

View File

@ -0,0 +1,9 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/run_file/floating_numbers.bend
---
NumScott:
[18.072, 0.125, 5.625, 2863333376.000]
Scott:
[18.072, 0.125, 5.625, 2863333376.000]