Fix number parser grabbing comma

This commit is contained in:
Timothy Warren 2020-02-10 14:10:48 -05:00
parent a480e5a096
commit d87c2cf165
1 changed files with 48 additions and 12 deletions

View File

@ -262,15 +262,31 @@ impl JSON {
n += 1; n += 1;
} else if self.chars[n] >= '1' && self.chars[n] <= '9' && n < max { } else if self.chars[n] >= '1' && self.chars[n] <= '9' && n < max {
n += 1; n += 1;
while self.chars[n].is_ascii_digit() && n < max { loop {
n += 1; if n + 1 > max {
break;
}
if self.chars[n + 1].is_ascii_digit() {
n += 1;
} else {
break;
}
} }
} }
if self.chars[n] == '.' && n < max { if self.chars[n] == '.' && n < max {
n += 1; n += 1;
while self.chars[n].is_ascii_digit() && n < max { loop {
n += 1; if n + 1 > max {
break;
}
if self.chars[n + 1].is_ascii_digit() {
n += 1;
} else {
break;
}
} }
} }
@ -280,25 +296,36 @@ impl JSON {
if self.chars[n] == '-' || self.chars[n] == '+' && n < max { if self.chars[n] == '-' || self.chars[n] == '+' && n < max {
n += 1; n += 1;
} }
// expect digit
loop {
if n + 1 > max {
break;
}
while self.chars[n].is_ascii_digit() && n < max { if self.chars[n + 1].is_ascii_digit() {
n += 1; n += 1;
} else {
break;
}
} }
} }
// If there are numeric digits attempt to parse the digits as a number
if n > start { if n > start {
let end = if n < self.chars.len() { let end = if n < self.chars.len() {
n n
} else { } else {
self.chars.len() max
}; };
let str = String::from_iter(&self.chars[start..=end]); let str = String::from_iter(&self.chars[start..=end]);
self.i += str.len() - 1;
match str.parse::<f64>() { match str.parse::<f64>() {
Ok(n) => Ok(Some(JSONValue::Number(n))), Ok(n) => {
Err(e) => Err(ParseError::ExpectedDigit(format!("{:#?}", (str, e)))), self.increment(str.len() - 1);
return Ok(Some(JSONValue::Number(n)))
},
Err(e) => Err(ParseError::ExpectedDigit(format!("'{}', {:#?}", str, e))),
} }
} else { } else {
Ok(None) Ok(None)
@ -342,7 +369,7 @@ impl JSON {
/// error is returned /// error is returned
fn eat(&mut self, ch: char) -> Result<(), ParseError> { fn eat(&mut self, ch: char) -> Result<(), ParseError> {
if self.chars[self.i] != ch { if self.chars[self.i] != ch {
let msg = format!("Expected '{}'.", ch); let msg = format!("Expected {}.", ch);
return Err(ParseError::ExpectedToken(msg)); return Err(ParseError::ExpectedToken(msg));
} }
@ -408,6 +435,9 @@ mod tests {
#[test] #[test]
fn parse_number() { fn parse_number() {
// This function works like I think, right?
assert_ne!(','.is_ascii_digit(), true);
let mut parser = JSON::new(r#""foo""#); let mut parser = JSON::new(r#""foo""#);
let res = JSON::parse_number(&mut parser); let res = JSON::parse_number(&mut parser);
assert_eq!(res, Ok(None)); assert_eq!(res, Ok(None));
@ -419,6 +449,10 @@ mod tests {
let mut parser = JSON::new("3e4"); let mut parser = JSON::new("3e4");
let res = JSON::parse_number(&mut parser); let res = JSON::parse_number(&mut parser);
assert_eq!(res, Ok(Some(JSONValue::Number(3e4f64)))); assert_eq!(res, Ok(Some(JSONValue::Number(3e4f64))));
let mut parser = JSON::new("1.234,");
let res = JSON::parse_number(&mut parser);
assert_eq!(res, Ok(Some(JSONValue::Number(1.234f64))));
} }
#[test] #[test]
@ -456,6 +490,9 @@ mod tests {
#[test] #[test]
fn can_parse_arbitrary_json() { fn can_parse_arbitrary_json() {
let result = JSON::parse("[{}]");
assert_eq!(result, Ok(JSONValue::Array(vec![JSONValue::Object(HashMap::new())])));
let result = JSON::parse( let result = JSON::parse(
r#"[{ r#"[{
"a": 9.38083151965, "a": 9.38083151965,
@ -472,7 +509,6 @@ mod tests {
"i": ["\"", "\\", "/", "\b", "\f", "\n", "\r", "\t", "\u0001", "\uface"] "i": ["\"", "\\", "/", "\b", "\f", "\n", "\r", "\t", "\u0001", "\uface"]
}]"#, }]"#,
); );
// let msg = format!("{:#?}", result);
assert!(result.is_ok(), format!("{:#?}", result)); assert!(result.is_ok(), format!("{:#?}", result));
} }
} }