use crate::parser::{
ast::metadata::AstNodeMeta,
error::{ParserError, ParserErrorVariant},
lexer::{
tokens::{Token, TokenTy},
IndexedToken,
},
state::ParserState,
util::NodeParserResult,
};
use num::{BigUint, Num};
use std::cmp;
#[derive(Debug)]
pub struct IntegerLiteral<'src> {
pub meta: AstNodeMeta<'src>,
pub value: BigUint,
}
impl<'src> IntegerLiteral<'src> {
pub fn parse(parser_state: &mut ParserState<'src>) -> NodeParserResult<Self> {
let IndexedToken {
index,
token: Token { length, .. },
} = parser_state
.next_token_if_ty_eq(TokenTy::IntegerLit)
.ok_or_else(|| ParserError {
byte_range: parser_state.peek_byte_range(),
ty: ParserErrorVariant::Expected("integer literal"),
})?;
let matching_source = &parser_state.source[index..index + length];
let prefix = &matching_source[..cmp::max(2, matching_source.len())];
let radix = match prefix {
"0x" | "0X" => 16,
"0b" | "0B" => 2,
"0o" => 8,
_ => 10,
};
let body = if radix != 10 {
&matching_source[2..]
} else {
matching_source
};
let value = BigUint::from_str_radix(body, radix)
.expect("lexer checks integer literal format");
Ok(IntegerLiteral {
meta: parser_state.make_ast_node_meta(index, length),
value,
})
}
}