From 0f496a8e5d2678ce3d81e402ab612534af787917 Mon Sep 17 00:00:00 2001 From: visil Date: Mon, 20 Nov 2023 00:37:09 +0300 Subject: =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B8=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + Cargo.toml | 8 ++++++ src/main.rs | 35 +++++++++++++++++++++++ src/parser.rs | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/main.rs create mode 100644 src/parser.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9d07f78 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "progcalc" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..d4e9cac --- /dev/null +++ b/src/main.rs @@ -0,0 +1,35 @@ + + +#[derive(Debug)] +enum BaseNumber { + Decimal(i64), + Octal(i64), + Binary(i64), + Hexadecimal(i64), + Nan, +} + +impl BaseNumber { + fn format(&self) -> Result { + match self { + Self::Binary(value) => Ok(format!("{:b}", value)), + Self::Octal(value) => Ok(format!("{:o}", value)), + Self::Decimal(value) => Ok(format!("{}", value)), + Self::Hexadecimal(value) => Ok(format!("{:x}", value)), + Nan => Err("Not a number!".to_string()), + } + } +} + +#[derive(Debug)] +enum Operator { + Add, + Sub, + Mul, + Div, +} + +fn main() { + println!("Hello, world!"); + println!("{}", numformat(15, 16).unwrap()); +} diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..fe414b0 --- /dev/null +++ b/src/parser.rs @@ -0,0 +1,91 @@ +extern crate core; +use core::str::Chars; + +#[derive(Debug, PartialEq)] +pub enum Token { + Number(i32), + Plus, + Minus, + Multiply, + Divide, +} + +pub struct Lexer<'a> { + chars: Chars<'a>, +} + +impl<'a> Lexer<'a> { + // Constructor + pub fn new(input: &'a str) -> Self { + Lexer { chars: input.chars() } +} + + fn next_token(&mut self) -> Option { + let next_char = self.chars.next()?; + + match next_char { + '+' => Some(Token::Plus), + '-' => Some(Token::Minus), + '*' => Some(Token::Multiply), + '/' => Some(Token::Divide), + '1'..='9' => { + let mut number = next_char.to_digit(10)? as i32; + while let Some(next_char) = self.chars.clone().next() { + if let Some(digit) = next_char.to_digit(10) { + number = number * 10 + digit as i32; + self.chars.next(); + } else { + break; + } + } + Some(Token::Number(number)) + } + '0' => { + let base = match self.chars.next().unwrap() { + 'b' => Some(2), + 'o' => Some(8), + 'x' => Some(16), + _ => None, + }; + if base.is_none() { + return None; + } + + let mut number = next_char.to_digit(base.clone().unwrap())?; + while let Some(next_char) = self.chars.clone().next() { + if let Some(digit) = next_char.to_digit(base.clone().unwrap()) { + number = number * base.clone().unwrap() + digit; + self.chars.next(); + } else { + break; + } + } + Some(Token::Number(number as i32)) + } + _ => None, + } + } + + pub fn tokenize(&mut self) -> Vec { + let mut tokens = Vec::new(); + while let Some(token) = self.next_token() { + tokens.push(token); + } + tokens + } +} + +fn main() { + let mut lexer = Lexer::new("0x6A+0b001101*0o13"); + let tokens = lexer.tokenize(); + assert_eq!( + tokens, + vec![ + Token::Number(106), + Token::Plus, + Token::Number(13), + Token::Multiply, + Token::Number(11), + ] + ); +} \ No newline at end of file -- cgit v1.2.3