use crate::parser::error::{ParserError, ParserErrorKind};
use crate::parser::Parser;
use crate::{ast::literal::IntegerLiteral, lexer::token::TokenTy};
use num::{BigUint, Num};
impl IntegerLiteral {
pub fn parse(parser: &mut Parser) -> Result<Self, ParserError> {
let int_lit_token = parser.next_if_is(TokenTy::IntegerLiteral).ok_or_else(|| {
ParserErrorKind::ExpectedIntegerLiteral.at(parser.peek_fragment_or_rest_cloned())
})?;
let mut parse_str: &str = int_lit_token.fragment.as_str();
let mut chars = parse_str.chars();
let prefix: [char; 2] = [chars.next().unwrap(), chars.next().unwrap_or('\0')];
let radix: u32 = match prefix {
['0', 'x' | 'X'] => {
parse_str = &parse_str[2..];
16
}
['0', 'b' | 'B'] => {
parse_str = &parse_str[2..];
2
}
['0', 'o'] => {
parse_str = &parse_str[2..];
8
}
_ => 10,
};
let value = BigUint::from_str_radix(parse_str, radix)
.expect("num should successfully parse");
Ok(IntegerLiteral {
fragment: int_lit_token.fragment,
value,
})
}
}
#[cfg(test)]
mod tests {
use num::BigUint;
use crate::{ast::literal::IntegerLiteral, lexer::Lexer, parser::Parser};
#[test]
fn normal() {
let mut parser = Parser::new(Lexer::new_test("1000"));
let int_lit = IntegerLiteral::parse(&mut parser).unwrap();
assert_eq!(int_lit.value, BigUint::new(vec![1000]));
assert_eq!(parser.lexer.remaining.as_str(), "");
assert_eq!(int_lit.fragment.as_str(), "1000");
}
}