Add hexadecimal numerics
This commit is contained in:
		
							parent
							
								
									a3d923da12
								
							
						
					
					
						commit
						a09bccb255
					
				| @ -1,6 +1,6 @@ | |||||||
| // Main | // Main | ||||||
| fn main() -> bool { | fn main() -> bool { | ||||||
|     return 5 == fibonacci(5); |     return 144 == fibonacci(0xc); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Fibonacci | // Fibonacci | ||||||
|  | |||||||
| @ -153,6 +153,16 @@ impl Parse for PrimaryExpression { | |||||||
|                         Expression(Kind::VariableName(v.clone()), stream.get_range().unwrap()) |                         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) => { |                 Token::DecimalValue(v) => { | ||||||
|                     stream.next(); // Consume decimal
 |                     stream.next(); // Consume decimal
 | ||||||
|                     if let (Some(Token::Dot), Some(Token::DecimalValue(fractional))) = |                     if let (Some(Token::Dot), Some(Token::DecimalValue(fractional))) = | ||||||
| @ -172,7 +182,8 @@ impl Parse for PrimaryExpression { | |||||||
|                     } else { |                     } else { | ||||||
|                         Expression( |                         Expression( | ||||||
|                             Kind::Literal(Literal::Integer( |                             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(), |                             stream.get_range().unwrap(), | ||||||
|                         ) |                         ) | ||||||
|  | |||||||
| @ -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 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)] | #[derive(Eq, PartialEq, Clone, PartialOrd, Ord)] | ||||||
| pub enum Token { | pub enum Token { | ||||||
|     /// Values
 |     /// Values
 | ||||||
|     Identifier(String), |     Identifier(String), | ||||||
|     /// Number with at most one decimal point
 |     /// Number in the decimal base
 | ||||||
|     DecimalValue(String), |     DecimalValue(String), | ||||||
|  |     /// Integer number in the hexadecimal base
 | ||||||
|  |     HexadecimalValue(String), | ||||||
|     /// Some character literal that was surrounded by 'single-quotes'.
 |     /// Some character literal that was surrounded by 'single-quotes'.
 | ||||||
|     CharLit(String), |     CharLit(String), | ||||||
|     /// Some string literal that was surrounded by "double-quotes".
 |     /// Some string literal that was surrounded by "double-quotes".
 | ||||||
| @ -130,6 +141,7 @@ impl ToString for Token { | |||||||
|         match &self { |         match &self { | ||||||
|             Token::Identifier(ident) => ident.clone(), |             Token::Identifier(ident) => ident.clone(), | ||||||
|             Token::DecimalValue(val) => val.to_string(), |             Token::DecimalValue(val) => val.to_string(), | ||||||
|  |             Token::HexadecimalValue(val) => val.to_string(), | ||||||
|             Token::CharLit(lit) => format!("\'{}\'", lit), |             Token::CharLit(lit) => format!("\'{}\'", lit), | ||||||
|             Token::StringLit(lit) => format!("\"{}\"", lit), |             Token::StringLit(lit) => format!("\"{}\"", lit), | ||||||
|             Token::LetKeyword => String::from("let"), |             Token::LetKeyword => String::from("let"), | ||||||
| @ -348,15 +360,26 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error | |||||||
|             } |             } | ||||||
|             // Decimals
 |             // Decimals
 | ||||||
|             c if DECIMAL_NUMERICS.contains(c) => { |             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() { |                 while let Some(c) = cursor.first() { | ||||||
|                     if !DECIMAL_NUMERICS.contains(&c) { |                     if !numerics.contains(&c) { | ||||||
|                         break; |                         break; | ||||||
|                     } |                     } | ||||||
|                     value += &c.to_string(); |                     value += c; | ||||||
|                     cursor.next(); |                     cursor.next(); | ||||||
|                 } |                 } | ||||||
|                 Token::DecimalValue(value) |                 match value { | ||||||
|  |                     NumberType::Decimal(value) => Token::DecimalValue(value), | ||||||
|  |                     NumberType::Hexadecimal(hex) => Token::HexadecimalValue(hex), | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             '-' if cursor.first() == Some('>') => { |             '-' if cursor.first() == Some('>') => { | ||||||
|                 cursor.next(); // Eat `>`
 |                 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)] | #[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] | ||||||
| pub enum Error { | pub enum Error { | ||||||
|     #[error("Invalid token '{}' ", .0)] |     #[error("Invalid token '{}' ", .0)] | ||||||
|  | |||||||
| @ -78,7 +78,7 @@ pub fn parse_module<'map, T: Into<String>>( | |||||||
|     map.set_tokens(id, tokens.clone()); |     map.set_tokens(id, tokens.clone()); | ||||||
| 
 | 
 | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|     dbg!(&tokens); |     println!("{:#?}", &tokens); | ||||||
| 
 | 
 | ||||||
|     Ok((id, tokens)) |     Ok((id, tokens)) | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user