diff options
author | Zhongheng Liu <z.liu@outlook.com.gr> | 2025-01-23 19:41:14 +0200 |
---|---|---|
committer | Zhongheng Liu <z.liu@outlook.com.gr> | 2025-01-23 19:41:14 +0200 |
commit | 92617b26a26b3363b38367857a54fa0e4896699f (patch) | |
tree | f2283dfde77753ce109bacfc109512885b39e2fd | |
parent | 6b08f164481d626c6c9d1b066cd132376b4d627e (diff) | |
download | rpn-parse-rs-92617b26a26b3363b38367857a54fa0e4896699f.tar.gz rpn-parse-rs-92617b26a26b3363b38367857a54fa0e4896699f.tar.bz2 rpn-parse-rs-92617b26a26b3363b38367857a54fa0e4896699f.zip |
chore: ready to publish
-rw-r--r-- | Cargo.lock | 4 | ||||
-rw-r--r-- | Cargo.toml | 10 | ||||
-rw-r--r-- | src/lib.rs | 37 | ||||
-rw-r--r-- | src/main.rs | 119 | ||||
-rw-r--r-- | src/rpn.rs | 6 | ||||
-rw-r--r-- | src/rpntree/types/tree.rs | 1 |
6 files changed, 53 insertions, 124 deletions
@@ -3,5 +3,5 @@ version = 3 [[package]] -name = "rust-test" -version = "0.1.0" +name = "rpn" +version = "0.0.1" @@ -1,6 +1,10 @@ [package] -name = "rust-test" -version = "0.1.0" +name = "rpn" +version = "0.0.1" edition = "2021" - +author = ["Zhongheng Liu <z.liu@outlook.com.gr>"] +description = "Reverse Polish Notation parsing support" +[lib] +name = "rpn" +path = "src/lib.rs" [dependencies] diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..8e36c01 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,37 @@ +//! Reverse Polish Notation parsing library +//! +//! Example code: +//! ``` +//! use rpn::eval; +//! use std::collections::HashMap; +//! let mut m: HashMap<char, f32> = HashMap::new(); +//! m.insert('a', 1.0); +//! m.insert('b', 2.0); +//! m.insert('c', 3.0); +//! println!("{}", match eval("ab-c+c*".to_string(), m) { +//! Ok(n) => n.to_string(), +//! Err(s) => s, +//! }) +//! ``` +//! +//! TODOs +//! - Binary tree converting from infix to postfix operation + +mod rpn; +mod rpntree; + +use std::collections::HashMap; + +pub use rpn::{eval, RpnOperation}; +pub use rpntree::eval_rpn; + +pub fn test() { + let mut m: HashMap<char, f32> = HashMap::new(); + m.insert('a', 1.0); + m.insert('b', 2.0); + m.insert('c', 3.0); + println!("{}", match eval("ab-c+c*".to_string(), m) { + Ok(n) => n.to_string(), + Err(s) => s, + }) +} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 4578e30..0000000 --- a/src/main.rs +++ /dev/null @@ -1,119 +0,0 @@ -mod rpn; -mod rpntree; -use std::{collections::HashMap, io::stdin}; -/*struct TextSettings {} -struct Component { - text: String, - setting: TextSettings, -} -struct Article { - title: String, - components: Vec<Component>, -} -impl Display for Component { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.text) - } -} -impl Component { - fn new(text: String, setting: Option<TextSettings>) -> Component { - match setting { - Some(s) => { - return Component { - text, - setting: s, - } - }, - None => { - return Component { - text, - setting: TextSettings {} - } - } - } - } -} -impl Article { - fn new(lines: Vec<String>) -> Article { - let mut components = vec![]; - for (i, l) in lines.iter().enumerate() { - components.insert(i, Component::new(l.to_string(), None)); - } - Article { - title: "article title".to_string(), - components, - } - } -} -impl Display for Article { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut builder = String::from(""); - for c in &self.components { - builder += &format!("{}\n", c); - } - write!(f, "{}", builder) - } -}*/ -fn main() -> Result<(), String> { - rpntree::test(); - static RETURN_CHAR: &str = "*"; - let mut vars: HashMap<char, f32> = HashMap::new(); - println!("Input your variable mappings below, in K:char,V:f32 format, * to break;"); - let term = stdin(); - loop { - let mut s = String::new(); - let _ = term.read_line(&mut s); - if s.trim() == RETURN_CHAR { - break; - } - let vals = s.trim().split_once(','); - if vals.is_none() { - println!("Format invalid!"); - return Err("Format invalid".to_string()); - } - let (k_s, v_s) = vals.unwrap(); - println!("Stored: '{}': '{}'", k_s, v_s); - if k_s.chars().count() != 1 { - println!("Identifier must only be one character!"); - return Err("Identified length exceeded".to_string()); - } - let k = k_s.chars().next(); - if k.is_none() { - return Err("No identifier name found.".to_string()); - } - let v = v_s.parse::<f32>(); - match v { - Ok(val) => vars.insert(k.unwrap(), val), - Err(e) => return Err(e.to_string()), - }; - } - println!("Great! Now put your RPN expression below: "); - let mut rpn_str = String::new(); - let _ = term.read_line(&mut rpn_str); - let result = rpn::eval(rpn_str.trim().to_string(), vars); - match result { - Ok(number) => { - println!("Result: {}", number); - return Ok(()); - } - Err(reason) => { - return Err(format!("In RPN evaluation: {}", reason)); - } - } -} -/*fn _main() -> Result<(), Box<dyn Error>> { - println!("running main function"); - let mut cont = true; - let mut lines: Vec<String> = vec![]; - while true { - let mut s = String::new(); - let input = stdin(); - let _size = input.read_line(&mut s); - println!("{}", s); - if s.eq("stop") { break; } - lines.push(s); - } - let a = Article::new(lines); - println!("{}", a); - Ok(()) -}*/ @@ -1,5 +1,6 @@ use std::collections::HashMap; +/// Available RPN operations pub enum RpnOperation { Add, Subtract, @@ -23,6 +24,11 @@ fn rpn_match_op(c: char) -> Option<RpnOperation> { _ => None, } } + +/// Evaluates an expression in Reverse Polish Notation +/// +/// Returns `f32` arithmetic result if the expression can be parsed +/// Returns `Err` with a message if the RPN expression is malformed pub fn eval(rpn_str: String, var_map: HashMap<char, f32>) -> Result<f32, String> { let mut stack: Vec<f32> = vec![]; for (_i, ch) in rpn_str.chars().enumerate() { diff --git a/src/rpntree/types/tree.rs b/src/rpntree/types/tree.rs index 1ea7016..0181389 100644 --- a/src/rpntree/types/tree.rs +++ b/src/rpntree/types/tree.rs @@ -1,4 +1,5 @@ use std::fmt::Display; +/// A binary tree structure used to parse and evaluate an expression into RPN. pub struct Tree<T: Copy> { pub root_node: TreeNode<T>, } |