Add hexadecimal numerics

This commit is contained in:
Sofia 2025-07-24 21:24:17 +03:00
parent a3d923da12
commit a09bccb255
4 changed files with 59 additions and 9 deletions

View File

@ -1,6 +1,6 @@
// Main
fn main() -> bool {
return 5 == fibonacci(5);
return 144 == fibonacci(0xc);
}
// Fibonacci

View File

@ -153,6 +153,16 @@ impl Parse for PrimaryExpression {
Expression(Kind::VariableName(v.clone()), stream.get_range().unwrap())
}
}
Token::HexadecimalValue(v) => {
stream.next(); // Consume hexadecimal
Expression(
Kind::Literal(Literal::Integer(
u128::from_str_radix(&v, 16)
.expect("Hexadecimal is not parseable as u128!"),
)),
stream.get_range().unwrap(),
)
}
Token::DecimalValue(v) => {
stream.next(); // Consume decimal
if let (Some(Token::Dot), Some(Token::DecimalValue(fractional))) =
@ -172,7 +182,8 @@ impl Parse for PrimaryExpression {
} else {
Expression(
Kind::Literal(Literal::Integer(
v.parse().expect("Integer is not parseable as u128!"),
u128::from_str_radix(&v, 10)
.expect("Integer is not parseable as u128!"),
)),
stream.get_range().unwrap(),
)

View File

@ -1,13 +1,24 @@
use std::{fmt::Debug, str::Chars};
use std::{
fmt::Debug,
ops::{Add, AddAssign},
str::Chars,
};
static BINARY_NUMERICS: &[char] = &['0', '1'];
static OCTAL_NUMERICS: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7'];
static DECIMAL_NUMERICS: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
static HEXADECIMAL_NUMERICS: &[char] = &[
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
];
#[derive(Eq, PartialEq, Clone, PartialOrd, Ord)]
pub enum Token {
/// Values
Identifier(String),
/// Number with at most one decimal point
/// Number in the decimal base
DecimalValue(String),
/// Integer number in the hexadecimal base
HexadecimalValue(String),
/// Some character literal that was surrounded by 'single-quotes'.
CharLit(String),
/// Some string literal that was surrounded by "double-quotes".
@ -130,6 +141,7 @@ impl ToString for Token {
match &self {
Token::Identifier(ident) => ident.clone(),
Token::DecimalValue(val) => val.to_string(),
Token::HexadecimalValue(val) => val.to_string(),
Token::CharLit(lit) => format!("\'{}\'", lit),
Token::StringLit(lit) => format!("\"{}\"", lit),
Token::LetKeyword => String::from("let"),
@ -348,15 +360,26 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error
}
// Decimals
c if DECIMAL_NUMERICS.contains(c) => {
let mut value = character.to_string();
let mut value = NumberType::Decimal(character.to_string());
let mut numerics = DECIMAL_NUMERICS;
if let Some(second) = cursor.second() {
if cursor.first() == Some('x') && HEXADECIMAL_NUMERICS.contains(&second) {
cursor.next();
value = NumberType::Hexadecimal(String::new());
numerics = HEXADECIMAL_NUMERICS;
}
}
while let Some(c) = cursor.first() {
if !DECIMAL_NUMERICS.contains(&c) {
if !numerics.contains(&c) {
break;
}
value += &c.to_string();
value += c;
cursor.next();
}
Token::DecimalValue(value)
match value {
NumberType::Decimal(value) => Token::DecimalValue(value),
NumberType::Hexadecimal(hex) => Token::HexadecimalValue(hex),
}
}
'-' if cursor.first() == Some('>') => {
cursor.next(); // Eat `>`
@ -411,6 +434,22 @@ fn escape_char(c: &char) -> char {
}
}
enum NumberType {
Decimal(String),
Hexadecimal(String),
}
impl AddAssign<char> for NumberType {
fn add_assign(&mut self, rhs: char) {
*self = match self {
NumberType::Decimal(val) => NumberType::Decimal(val.to_owned() + &rhs.to_string()),
NumberType::Hexadecimal(val) => {
NumberType::Hexadecimal(val.to_owned() + &rhs.to_string())
}
};
}
}
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Error {
#[error("Invalid token '{}' ", .0)]

View File

@ -78,7 +78,7 @@ pub fn parse_module<'map, T: Into<String>>(
map.set_tokens(id, tokens.clone());
#[cfg(debug_assertions)]
dbg!(&tokens);
println!("{:#?}", &tokens);
Ok((id, tokens))
}