summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhongheng Liu <z.liu@outlook.com.gr>2025-01-23 19:41:14 +0200
committerZhongheng Liu <z.liu@outlook.com.gr>2025-01-23 19:41:14 +0200
commit92617b26a26b3363b38367857a54fa0e4896699f (patch)
treef2283dfde77753ce109bacfc109512885b39e2fd
parent6b08f164481d626c6c9d1b066cd132376b4d627e (diff)
downloadrpn-parse-rs-92617b26a26b3363b38367857a54fa0e4896699f.tar.gz
rpn-parse-rs-92617b26a26b3363b38367857a54fa0e4896699f.tar.bz2
rpn-parse-rs-92617b26a26b3363b38367857a54fa0e4896699f.zip
chore: ready to publish
-rw-r--r--Cargo.lock4
-rw-r--r--Cargo.toml10
-rw-r--r--src/lib.rs37
-rw-r--r--src/main.rs119
-rw-r--r--src/rpn.rs6
-rw-r--r--src/rpntree/types/tree.rs1
6 files changed, 53 insertions, 124 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3980da4..9a056f7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,5 +3,5 @@
version = 3
[[package]]
-name = "rust-test"
-version = "0.1.0"
+name = "rpn"
+version = "0.0.1"
diff --git a/Cargo.toml b/Cargo.toml
index 7c99670..c666f07 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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(())
-}*/
diff --git a/src/rpn.rs b/src/rpn.rs
index 19d62ed..6ac0dec 100644
--- a/src/rpn.rs
+++ b/src/rpn.rs
@@ -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>,
}