Skip to content

Commit

Permalink
Start infrastructure for parsing numbers in strings #52
Browse files Browse the repository at this point in the history
  • Loading branch information
mverleg committed Jun 17, 2018
1 parent 4346a4f commit 8b4a125
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/mango/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ pub mod encdec;
pub mod errors;

pub mod codeparts;

pub mod parsetxt;
32 changes: 32 additions & 0 deletions src/mango/util/parsetxt/int.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use regex::Regex;

/// This matches integer literals, either just numbers in base 10, or base 2-36 with prefix.
/// The syntax for -37 in base 16 is -16b25 and 2748 is 16bABC.
/// Incorrect values like 4b7 or 0b0 are not handled at the lexing stage.
pub fn int_pattern() -> &'static str {
r"(?:\+|-*)(?:[1-9][0-9]*b(?:_?[0-9a-zA-Z])+|[0-9](?:_?[0-9])*)"
}

/// Convert a String that matches [int_pattern] to an i64 integer. Overflow is possible.
pub fn parse_int<S: Into<String>>(text: S) -> Option<i64> {
let text = text.into();
debug_assert!(
Regex::new(&format!("^{}$", int_pattern()))
.unwrap()
.is_match(&text)
);
Some(0i64)
}

// TODO: possibly add a i32 version?
// TODO: Option<i64> to deal with overflow?

#[cfg(test)]
mod tests {
use super::parse_int;

#[test]
fn test_parse_int() {
assert_eq!(42, parse_int("42").unwrap())
}
}
3 changes: 3 additions & 0 deletions src/mango/util/parsetxt/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod int;

pub mod real;
36 changes: 36 additions & 0 deletions src/mango/util/parsetxt/real.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use regex::Regex;

/// This matches real literals (base 10), which look like this:
/// sign / int1 / period / int2 / e / sign / int
/// Here int is a series of 0-9 digits separated by at most one underscore.
/// Signs are optional, everything from 'e' is optional, and int1 OR int2 is optional.
pub fn real_pattern() -> &'static str {
// TODO: do I want to allow numbers to start with a period?
// TODO: for now, only base10 for reals (would 8b11e2 be 9*8^2 or 9*10^2?)
// TODO: does not deal with NaN of infinity
r"(?:\+|-*)(?:\d(?:_?\d)*\.\d(?:_?\d)*|\d(?:_?\d)*\.|\.\d(?:_?\d)*)(?:e(?:\+|-|)\d(?:_?\d)*)?"
}

/// Convert a String that matches [real_pattern] to an f64 real. Overflow and loss of precision is possible.
pub fn parse_real<S: Into<String>>(text: S) -> Option<f64> {
let text = text.into();
debug_assert!(
Regex::new(&format!("^{}$", real_pattern()))
.unwrap()
.is_match(&text)
);
Some(0.0f64)
}

// TODO: possibly add a i32 version?
// TODO: Option<i64> to deal with overflow?

#[cfg(test)]
mod tests {
use super::parse_real;

#[test]
fn test_parse_int() {
assert_eq!(42., parse_real("42.").unwrap())
}
}

0 comments on commit 8b4a125

Please sign in to comment.