Add basic tokenization

This commit is contained in:
Erin Nova 2021-09-29 15:13:51 -04:00
commit ac30bfdfa5
Signed by: erin
GPG key ID: DA70E064A8C70F44
4 changed files with 121 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

7
Cargo.lock generated Normal file
View file

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "calc"
version = "0.1.0"

9
Cargo.toml Normal file
View file

@ -0,0 +1,9 @@
[package]
name = "calc"
description = "A simple terminal calculator"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

104
src/main.rs Normal file
View file

@ -0,0 +1,104 @@
use::std::io;
// Enum of different mathematical operations
#[derive(Debug)]
enum Operators {
Add,
Subtract,
Multiply,
Divide,
Power,
}
// Enum of different separators
#[derive(Debug)]
enum Separators {
Open,
Close,
Decimal,
}
// Enum for types of one 'block" in an eqation
#[derive(Debug)]
enum Blocks {
Operator(Operators), // A mathematical operator
Separator(Separators), // A separator, eg. '(', ')'
Integer(i32), // An integer
Float(f64), // A float
Error,
}
// Determine what type a 'block' is
fn determine_type(block: &str) -> Blocks {
let block_type = match block {
// Check if it's an operator
"+" => Blocks::Operator(Operators::Add),
"-" => Blocks::Operator(Operators::Subtract),
"*" => Blocks::Operator(Operators::Multiply),
"/" => Blocks::Operator(Operators::Divide),
"^" => Blocks::Operator(Operators::Power),
// Check if it's a separator
"(" => Blocks::Separator(Separators::Open),
")" => Blocks::Separator(Separators::Close),
"." => Blocks::Separator(Separators::Decimal),
_ => {
match block.parse::<i32>() {
Ok(integer) => Blocks::Integer(integer),
Err(_e) => {
match block.parse::<f64>() {
Ok(float) => Blocks::Float(float),
Err(_e) => Blocks::Error,
}
}
}
}
};
return block_type;
}
// cut the input string into different pieces
fn separate(input: String) {
// Vector for the whole equation
let mut equation: Vec<Blocks> = Vec::new();
// Vector for collecting a single number
let mut number: Vec<char> = Vec::new();
// Loop through each character in the equation
for i in input.chars() {
match i.to_digit(10) {
Some(..) => {
number.push(i);
},
None => {
if i == '.' {
number.push(i);
} else {
let full_number: String = number.iter().collect::<String>();
println!("Full number found: {}", full_number);
number = Vec::new(); // Any found number has finished, so clear the vector
equation.push(determine_type(&full_number));
}
equation.push(determine_type(&i.to_string())); // Determine the type and append it to the equation vector
}
}
println!("{}", i);
}
let full_number: String = number.iter().collect::<String>();
equation.push(determine_type(&full_number));
println!("{:?}", equation);
// 5+6-2/45*(6-2)^5
}
fn main() {
println!("RUNK (Rust Universal Number Calculator)");
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("Failed to read input");
input = input.split_whitespace().collect();
println!("Your input was {}", input);
separate(input);
}