From 6cff70f2a313811e3e382473817addac7daabb60 Mon Sep 17 00:00:00 2001 From: russ Date: Tue, 31 Oct 2017 22:02:36 -0700 Subject: [PATCH 1/2] binary, hex, octal literal types --- src/parser.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/tests.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/src/parser.rs b/src/parser.rs index 67096fba..9d8b1161 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -391,6 +391,57 @@ impl<'a> TokenIterator<'a> { } } } + 'x' | 'X' => { + result.push(nxt); + self.char_stream.next(); + while let Some(&nxt_hex) = self.char_stream.peek() { + match nxt_hex { + '0'...'9' | 'a'...'f' | 'A'...'F' => { + result.push(nxt_hex); + self.char_stream.next(); + } + _ => break, + } + } + let out: String = result.iter().cloned().skip(2).collect(); + if let Ok(val) = i64::from_str_radix(&out, 16) { + return Some(Token::IntConst(val)); + } + } + 'o' | 'O' => { + result.push(nxt); + self.char_stream.next(); + while let Some(&nxt_oct) = self.char_stream.peek() { + match nxt_oct { + '0'...'8' => { + result.push(nxt_oct); + self.char_stream.next(); + } + _ => break, + } + } + let out: String = result.iter().cloned().skip(2).collect(); + if let Ok(val) = i64::from_str_radix(&out, 8) { + return Some(Token::IntConst(val)); + } + } + 'b' | 'B' => { + result.push(nxt); + self.char_stream.next(); + while let Some(&nxt_bin) = self.char_stream.peek() { + match nxt_bin { + '0' | '1' | '_' => { + result.push(nxt_bin); + self.char_stream.next(); + } + _ => break, + } + } + let out: String = result.iter().cloned().skip(2).filter(|c| c != &'_').collect(); + if let Ok(val) = i64::from_str_radix(&out, 2) { + return Some(Token::IntConst(val)); + } + } _ => break, } } diff --git a/src/tests.rs b/src/tests.rs index b9dd0711..bc76c046 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -688,4 +688,55 @@ fn test_right_shift_equals() { } else { assert!(false); } +} + +#[test] +fn test_hex_literal() { + let mut engine = Engine::new(); + + if let Ok(result) = engine.eval::("let x = 0xf; x") { + assert_eq!(result, 15); + } else { + assert!(false); + } + + if let Ok(result) = engine.eval::("let x = 0xff; x") { + assert_eq!(result, 255); + } else { + assert!(false); + } +} + +#[test] +fn test_octal_literal() { + let mut engine = Engine::new(); + + if let Ok(result) = engine.eval::("let x = 0o77; x") { + assert_eq!(result, 63); + } else { + assert!(false); + } + + if let Ok(result) = engine.eval::("let x = 0o1234; x") { + assert_eq!(result, 668); + } else { + assert!(false); + } +} + +#[test] +fn test_binary_literal() { + let mut engine = Engine::new(); + + if let Ok(result) = engine.eval::("let x = 0b1111; x") { + assert_eq!(result, 15); + } else { + assert!(false); + } + + if let Ok(result) = engine.eval::("let x = 0b0011_1100_1010_0101; x") { + assert_eq!(result, 15525); + } else { + assert!(false); + } } \ No newline at end of file From 6d151bc2b92663d0a23cba535d59a964826f842a Mon Sep 17 00:00:00 2001 From: russ Date: Tue, 31 Oct 2017 22:10:46 -0700 Subject: [PATCH 2/2] minor refactor for sanity --- src/parser.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 9d8b1161..4276bf37 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -370,6 +370,7 @@ impl<'a> TokenIterator<'a> { match c { '0'...'9' => { let mut result = Vec::new(); + let mut radix_base: Option = None; result.push(c); while let Some(&nxt) = self.char_stream.peek() { @@ -403,10 +404,7 @@ impl<'a> TokenIterator<'a> { _ => break, } } - let out: String = result.iter().cloned().skip(2).collect(); - if let Ok(val) = i64::from_str_radix(&out, 16) { - return Some(Token::IntConst(val)); - } + radix_base = Some(16); } 'o' | 'O' => { result.push(nxt); @@ -420,10 +418,7 @@ impl<'a> TokenIterator<'a> { _ => break, } } - let out: String = result.iter().cloned().skip(2).collect(); - if let Ok(val) = i64::from_str_radix(&out, 8) { - return Some(Token::IntConst(val)); - } + radix_base = Some(8); } 'b' | 'B' => { result.push(nxt); @@ -437,15 +432,19 @@ impl<'a> TokenIterator<'a> { _ => break, } } - let out: String = result.iter().cloned().skip(2).filter(|c| c != &'_').collect(); - if let Ok(val) = i64::from_str_radix(&out, 2) { - return Some(Token::IntConst(val)); - } + radix_base = Some(2); } _ => break, } } + if let Some(radix) = radix_base { + let out: String = result.iter().cloned().skip(2).filter(|c| c != &'_').collect(); + if let Ok(val) = i64::from_str_radix(&out, radix) { + return Some(Token::IntConst(val)); + } + } + let out: String = result.iter().cloned().collect(); if let Ok(val) = out.parse::() {