implement a custom shunting yard algorithm for bit manipulation only

This commit is contained in:
rhpidfyre 2025-04-12 19:11:23 -04:00
parent 90b2087c82
commit 43457aae9f
3 changed files with 61 additions and 9 deletions

View File

@ -1,5 +1,4 @@
use std::io; use std::io;
use libbitfyre::base;
use crate::{diff::{self, Compare}, eval::{eval, EvalError, EvalResult}, map::{input_error, MapDisplay}}; use crate::{diff::{self, Compare}, eval::{eval, EvalError, EvalResult}, map::{input_error, MapDisplay}};
@ -25,12 +24,16 @@ fn init_message() {
pub struct Out; pub struct Out;
impl Out { impl Out {
fn binary(&self, val: i64) -> String {
format!("{:b}", val)
}
fn error(&self, eval_error: EvalError) { fn error(&self, eval_error: EvalError) {
match eval_error { match eval_error {
EvalError::I64Conversion(parse_int_error) => println!("{parse_int_error}"), EvalError::I64Conversion(parse_int_error) => println!("{parse_int_error}"),
EvalError::InvalidOperator(invalid_op) => println!("The operator {:?} is invalid.", invalid_op), EvalError::InvalidOperator(invalid_op) => println!("The operator {:?} is invalid.", invalid_op),
EvalError::LeftMissing => println!("Left side expression missing."),
EvalError::RightMissing => println!("Right side expression missing."), EvalError::RightMissing => println!("Right side expression missing."),
EvalError::LeftMissing => println!("Left side expression missing."),
} }
} }
@ -38,9 +41,7 @@ impl Out {
let diffed_eval_chars = diffed_eval.chars().count(); let diffed_eval_chars = diffed_eval.chars().count();
let mut char_counts = [diffed_left.chars().count(), diffed_right.chars().count(), diffed_eval_chars]; let mut char_counts = [diffed_left.chars().count(), diffed_right.chars().count(), diffed_eval_chars];
char_counts.sort(); char_counts.sort();
let subtracted_count = char_counts.last().map_or(0, |biggest_len| { let subtracted_count = char_counts.last().map_or(0, |biggest_len| *biggest_len-diffed_eval_chars);
*biggest_len-diffed_eval_chars
});
format!("{}{diffed_eval}", "0".repeat(subtracted_count)) format!("{}{diffed_eval}", "0".repeat(subtracted_count))
} }
@ -48,11 +49,11 @@ impl Out {
eval_out.map_or_else(|e| self.error(e), |result| { eval_out.map_or_else(|e| self.error(e), |result| {
let mut differ = diff::Comparer::new(); let mut differ = diff::Comparer::new();
let diffed = differ.compare(Compare { let diffed = differ.compare(Compare {
right: base::binary(result.input.right), right: self.binary(result.input.right),
left: base::binary(result.input.left), left: self.binary(result.input.left),
}); });
let padded_eval = self.padded(&diffed.left, &diffed.right, base::binary(result.eval)); let padded_eval = self.padded(&diffed.left, &diffed.right, self.binary(result.eval));
println!("{}", diffed.left); println!("{}", diffed.left);
println!("{}", diffed.right); println!("{}", diffed.right);
println!("{}", "-".repeat(padded_eval.chars().count())); println!("{}", "-".repeat(padded_eval.chars().count()));
@ -79,7 +80,9 @@ impl Bitfyre {
io::stdin().read_line(&mut input).map_or_display(|_size| match input.trim() { io::stdin().read_line(&mut input).map_or_display(|_size| match input.trim() {
"exit" => self.terminate(None), "exit" => self.terminate(None),
"help" => help_docs(), "help" => help_docs(),
trim => Out.evaled(eval(trim.split_whitespace().collect())) trim => {
}
}) })
}) })
} }

View File

@ -1,6 +1,7 @@
use input::Bitfyre; use input::Bitfyre;
use cli::parser; use cli::parser;
mod shunting_yard;
mod input; mod input;
mod eval; mod eval;
mod diff; mod diff;

48
src/shunting_yard.rs Normal file
View File

@ -0,0 +1,48 @@
pub type Precision = i64;
struct ShuntingYard {
input: String,
output: Vec<String>,
stack: Vec<String>,
}
impl ShuntingYard {
pub const fn new(input: String) -> Self {
Self {
input,
output: Vec::new(),
stack: Vec::new()
}
}
fn is_operator(&mut self, value: char) -> bool {
match value {
'&' | '^' | '|' => {
self.stack.push(value.to_string());
true
},
'>' | '<' => {
if let Some(last) = self.stack.last_mut() {
match last.as_str() {
">" => *last = ">>".to_owned(),
"<" => *last = "<<".to_owned(),
_ => self.stack.push(value.to_string())
}
} else {
self.stack.push(value.to_string())
};
true
}
_ => false
}
}
pub fn eval(&mut self) {
self.output = self.input.chars()
.collect::<Vec<char>>()
.into_iter()
.filter(|char| self.is_operator(*char))
.map(|char_num| char_num.to_string())
.collect::<Vec<String>>();
}
}