use crate::parser::{code, prelude::*, Input, ParseError, ParseResult};
use super::{LiteralError, Radix};
pub fn recognize_integer(
radix: Radix,
signed: bool,
) -> impl for<'a> Fn(Input<'a>) -> ParseResult<'a, &str> {
move |input| {
match signed {
true => recognize(tuple((opt(any((char('+'), char('-')))), radix.digit1())))(input),
false => recognize(radix.digit1())(input),
}
.map_err(|mut err| {
err.push(input, code::ERR_INTEGER_FORMAT, LiteralError::IntegerFormat);
err
})
}
}
pub fn integer(radix: Radix, signed: bool) -> impl for<'a> Fn(Input<'a>) -> ParseResult<'a, i64> {
move |input| {
let (output, input) = recognize_integer(radix, signed)(input)?;
let value = i64::from_str_radix(output, radix.base()).map_err(|_| {
ParseError::new(input, code::ERR_INTEGER, LiteralError::Integer).and_semantic()
})?;
Ok((value, input))
}
}
#[cfg(test)]
mod tests {
use super::*;
const INTEGERS: [(&str, Radix); 42] = [
("0", Radix::Binary),
("0", Radix::Octal),
("0", Radix::Decimal),
("0", Radix::Hexadecimal),
("1", Radix::Binary),
("1", Radix::Octal),
("1", Radix::Decimal),
("1", Radix::Hexadecimal),
("0101010", Radix::Binary),
("01234567", Radix::Octal),
("0123456789", Radix::Decimal),
("0123456789", Radix::Hexadecimal),
("abcdef", Radix::Hexadecimal),
("ABCDEF", Radix::Hexadecimal),
("+0", Radix::Binary),
("+0", Radix::Octal),
("+0", Radix::Decimal),
("+0", Radix::Hexadecimal),
("+1", Radix::Binary),
("+1", Radix::Octal),
("+1", Radix::Decimal),
("+1", Radix::Hexadecimal),
("+0101010", Radix::Binary),
("+01234567", Radix::Octal),
("+0123456789", Radix::Decimal),
("+0123456789", Radix::Hexadecimal),
("+abcdef", Radix::Hexadecimal),
("+ABCDEF", Radix::Hexadecimal),
("-0", Radix::Binary),
("-0", Radix::Octal),
("-0", Radix::Decimal),
("-0", Radix::Hexadecimal),
("-1", Radix::Binary),
("-1", Radix::Octal),
("-1", Radix::Decimal),
("-1", Radix::Hexadecimal),
("-0101010", Radix::Binary),
("-01234567", Radix::Octal),
("-0123456789", Radix::Decimal),
("-0123456789", Radix::Hexadecimal),
("-abcdef", Radix::Hexadecimal),
("-ABCDEF", Radix::Hexadecimal),
];
#[test]
fn recognize_integer_success() {
for (value, radix) in INTEGERS.iter() {
let input = Input::new(value);
let result = recognize_integer(*radix, true)(input);
assert_eq!(result, Ok((*value, Input::new(""))));
}
}
#[test]
fn integer_success() {
for (value, radix) in INTEGERS.iter() {
let input = Input::new(value);
let result = integer(*radix, true)(input);
assert_eq!(
result,
Ok((
i64::from_str_radix(value, radix.base()).unwrap(),
Input::new("")
))
);
}
}
}