Skip to content

Instantly share code, notes, and snippets.

@sploiselle
Created December 12, 2019 18:23
Show Gist options
  • Save sploiselle/a11bc1e4cc277e8bcd6e8277b5ab15fb to your computer and use it in GitHub Desktop.
Save sploiselle/a11bc1e4cc277e8bcd6e8277b5ab15fb to your computer and use it in GitHub Desktop.
Parsing a string as a decimal in a single pass with a lot of if statements
for c in s.chars() {
if c == '.' {
if seen_decimal {
bail!("multiple decimal points in numeric literal: {}", s)
}
seen_decimal = true;
continue;
}
if c == '-' {
if seen_e_notation {
if e_negative {
bail!("multiple negative signs in e-notation: {}", s);
}
e_negative = true;
continue;
}
if negative {
bail!("multiple negative signs in numeric literal: {}", s);
}
negative = true;
continue;
}
if c == 'e' || c == 'E' {
if seen_e_notation {
bail!("more than one E for e-notation in numeric literal: {}", s)
}
seen_e_notation = true;
continue;
}
let digit = c
.to_digit(10)
.ok_or_else(|| format_err!("invalid digit in numeric literal: {}", s))?;
if seen_e_notation {
e_exponent = e_exponent
.checked_mul(10)
.ok_or_else(|| format_err!("exponent in e-notation overflows u8: {}", s))?;
e_exponent = e_exponent
.checked_add(digit as u8)
.ok_or_else(|| format_err!("exponent in e-notation overflows u8: {}", s))?;
} else {
precision += 1;
if seen_decimal {
scale += 1;
}
significand = significand
.checked_mul(10)
.ok_or_else(|| format_err!("numeric literal overflows i128: {}", s))?;
significand = significand
.checked_add(i128::from(digit))
.ok_or_else(|| format_err!("numeric literal overflows i128: {}", s))?;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment