Skip to content

Commit d6e8b04

Browse files
committed
total refactoring to simplify and increase speed
1 parent b2b8bcf commit d6e8b04

File tree

2 files changed

+138
-188
lines changed

2 files changed

+138
-188
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ edition = "2018"
1111

1212

1313
[dependencies]
14-
rust_prefix_to_postfix = {path = "rust_prefix_to_postfix"}
14+
rust_prefix_to_postfix = {path = "https://github.com/EmberCraze/rust_prefix_to_postfix.git"}
1515
```
1616
2. Use call the trait in the library and add a new infix operation
1717
```Rust

src/lib.rs

+137-187
Original file line numberDiff line numberDiff line change
@@ -21,211 +21,161 @@ impl Error {
2121
}
2222
}
2323

24-
//add interfacing through trait
25-
pub trait Operation {
26-
fn new(infix_input: &String) -> Result<Self> where Self: Sized;//Self needs to have size to be known at compile time
27-
fn reverse_polish_parsing(&mut self) -> Result<()>;
28-
}
29-
30-
31-
//this should contain infix notation(3+4) and reverse polish notation(34+)
32-
pub struct OperationInfo {
33-
pub infix: Vec<char>,
34-
pub reverse_pn: Vec<String>,
35-
}
36-
37-
impl Operation for OperationInfo {
38-
//initializes the structure and fills out the parameters
39-
fn new(infix_input: &String) -> Result<Self>{
40-
41-
let mut infix_vector: Vec<char> = vec![];
42-
43-
for chr in infix_input.chars(){
44-
infix_vector.push(chr);
45-
}
46-
47-
let op_info = OperationInfo {
48-
infix: infix_vector,
49-
reverse_pn: vec![],
50-
};
51-
52-
Ok(
53-
op_info
54-
)
55-
}
24+
///A function that uses the shunting yard algorithm to convert infix notation to reverse polish notation
25+
pub fn reverse_polish_parsing(infix_input: &String)->Result<Vec<String>>{
26+
//This is using the shunting yard algorithm
27+
let math_ops_prio_1: Vec<char> = vec!['+', '-'];
28+
let math_ops_prio_2: Vec<char> = vec!['*', '/', '%'];
29+
let math_ops_prio_3: Vec<char> = vec!['^'];
30+
31+
let functions: Vec<String> = vec!["sqrt".to_string(), "max".to_string(), "min".to_string()];
32+
33+
let mut symbol_stack: Vec<&char> = vec![];
34+
let mut output: Vec<String> = vec![];
35+
let mut next_output_value_num = "".to_string();
36+
let mut next_output_value_alpha = "".to_string();
5637

57-
fn reverse_polish_parsing(&mut self)->Result<()>{
58-
//This is using the shunting yard algorithm
59-
let math_ops_prio_1: Vec<char> = vec!['+', '-'];
60-
let math_ops_prio_2: Vec<char> = vec!['*', '/', '%'];
61-
let math_ops_prio_3: Vec<char> = vec!['^'];
62-
//this may require word recognition
63-
let functions: Vec<String> = vec!["sqrt".to_string(), "max".to_string(), "min".to_string()];
64-
65-
let mut symbol_stack: Vec<&char> = vec![];
66-
let mut output: Vec<String> = vec![];
67-
let mut next_output_value_num = "".to_string();
68-
let mut next_output_value_alpha = "".to_string();
69-
70-
71-
//TODO this algorithm needs revision to optimize
72-
for (index, chr) in self.infix.iter().enumerate() {
73-
if chr.is_digit(10) {
74-
//i must be a digit
75-
//println!("{} is a digit", chr);
76-
//looking at the previous and next index we can determine if there were
77-
//numbers before this and if this is the last number of the element
78-
79-
//if the previous element was a number, then we are on a continuos number
80-
81-
if index > 0 && self.infix[index - 1].is_digit(10){
82-
next_output_value_num = next_output_value_num + &chr.to_string();
83-
}
84-
else {
85-
next_output_value_num = chr.to_string();
86-
}
87-
//if the next value is not a digit, then we are on the last digit of the whole number
88-
if index < self.infix.len() - 1 {
89-
if !self.infix[index + 1].is_digit(10){
90-
output.push(next_output_value_num.to_string());
91-
}
92-
continue;
93-
}
94-
95-
//checking if the last character in the vector is equal to the current
96-
if index == self.infix.len() - 1 {//self.infix.chars().last().unwrap(){
97-
output.push(next_output_value_num.to_string());
38+
let infix_as_chars: Vec<char> = infix_input.chars().collect();
39+
40+
for (index, chr) in infix_as_chars.iter().enumerate() {
41+
if chr.is_digit(10) {
42+
//it must be a digit
43+
//looking at the previous and next index we can determine if there were
44+
//numbers before this and if this is the last number of the element
45+
46+
//if the previous element was a number, then we are on a continuos number
47+
48+
next_output_value_num.push(*chr);
49+
//if the next value is not a digit, then we are on the last digit of the whole number
50+
if index < infix_as_chars.len() - 1 {
51+
if !infix_as_chars[index + 1].is_digit(10){
52+
let moved_value = std::mem::take(&mut next_output_value_num);
53+
output.push(moved_value);
9854
}
55+
continue;
9956
}
100-
else if chr.is_alphabetic() {
101-
//i must be a digit
102-
//println!("{} is a digit", chr);
103-
//looking at the previous and next index we can determine if there were
104-
//numbers before this and if this is the last number of the element
105-
106-
//if the previous element was a number, then we are on a continuos number
107-
108-
if index > 0 && self.infix[index - 1].is_alphabetic(){
109-
next_output_value_alpha = next_output_value_alpha + &chr.to_string();
110-
}
111-
else {
112-
next_output_value_alpha = chr.to_string();
113-
}
114-
115-
116-
//if the next value is not a digit, then we are on the last digit of the whole number
117-
if index < self.infix.len() - 1 {
118-
//println!("{:?}", self.infix[index + 1]);
119-
if !self.infix[index + 1].is_alphabetic() {
120-
if functions.contains(&next_output_value_alpha){
121-
output.push(next_output_value_alpha.to_string());
122-
}
123-
else{
124-
return Err(Error::could_not_parse_function());
125-
}
126-
}
127-
continue;
128-
}
12957

130-
//checking if the last character in the vector is equal to the current
131-
if index == self.infix.len() - 1 {//self.infix.chars().last().unwrap(){
132-
output.push(next_output_value_alpha.to_string());
133-
}
58+
//checking if the last character in the vector is equal to the current
59+
if index == infix_as_chars.len() - 1 {
60+
let moved_value = std::mem::take(&mut next_output_value_num);
61+
output.push(moved_value);
13462
}
135-
else if math_ops_prio_3.contains(&chr){
136-
//i must be an operator of prio 3
137-
//println!("{} is a prio 3 operator", chr);
138-
loop{
139-
//if the last value in the stack is of lower prio or if the stack i empty
140-
//push the value to the stack
141-
//if the last value is not prio 3 and is not an end parenthesis add the prio 3 operand
142-
if !math_ops_prio_3.contains(&symbol_stack[symbol_stack.len()-1])
143-
&& symbol_stack[symbol_stack.len()-1] != &')'{
144-
symbol_stack.push(chr);
145-
break;
63+
}
64+
else if chr.is_alphabetic() {
65+
//it must be an alphabetical character
66+
//looking at the previous and next index we can determine if there were
67+
//characters before this and if this is the last character of the element
68+
69+
//if the previous element was a character, then we are on a continuos character
70+
71+
next_output_value_alpha.push(*chr);
72+
73+
74+
//if the next value is not a character, then we are on the last character of the whole string
75+
if index < infix_as_chars.len() - 1 {
76+
if !infix_as_chars[index + 1].is_alphabetic() {
77+
if functions.contains(&next_output_value_alpha){
78+
let moved_value = std::mem::take(&mut next_output_value_alpha);
79+
output.push(moved_value);
14680
}
14781
else{
148-
//pop the last symbol and add it to the output
149-
output.push(symbol_stack[symbol_stack.len()-1].to_string());
150-
symbol_stack.pop();
82+
return Err(Error::could_not_parse_function());
15183
}
15284
}
85+
continue;
15386
}
154-
else if math_ops_prio_2.contains(&chr){
155-
//i must be an operator of prio 2
156-
//println!("{} is a prio 2 operator", chr);
157-
loop{
158-
//if the last value in the stack is of lower prio or if the stack i empty
159-
//push the value to the stack
160-
//if the last value is not prio 2 and is not an end parenthesis add the prio 2 operand
161-
if ![&math_ops_prio_2[..],&math_ops_prio_3[..]].concat().contains(&symbol_stack[symbol_stack.len()-1])
162-
&& symbol_stack[symbol_stack.len()-1] != &')'{
163-
symbol_stack.push(chr);
164-
break;
165-
}
166-
else{
167-
//pop the last symbol and add it to the output
168-
output.push(symbol_stack[symbol_stack.len()-1].to_string());
169-
symbol_stack.pop();
170-
}
171-
}
87+
88+
//checking if the last character in the vector is equal to the current
89+
if index == infix_as_chars.len() - 1 {
90+
let moved_value = std::mem::take(&mut next_output_value_alpha);
91+
output.push(moved_value);
17292
}
173-
else if math_ops_prio_1.contains(&chr){
174-
//i must be and operator of prio 1
175-
//println!("{} is a prio 1 operator", chr);
176-
177-
loop{
178-
//if the last value in the stack is a start parenthesis or
179-
//if the stack is empty push the prio 1 operator to the stack
180-
//else pop all symbols that are higher priority to the output
181-
if symbol_stack.len() == 0 || symbol_stack[symbol_stack.len()-1] == &'(' {
182-
symbol_stack.push(chr);
183-
break;
184-
}
185-
else{
186-
output.push(symbol_stack[symbol_stack.len()-1].to_string());
187-
symbol_stack.pop();
188-
}
93+
}
94+
else if math_ops_prio_3.contains(&chr){
95+
//it must be an operator of prio 3
96+
97+
loop{
98+
//if the last value in the stack is of lower prio or if the stack i empty
99+
//push the value to the stack
100+
//if the last value is not prio 3 and is not an end parenthesis add the prio 3 operand
101+
if !math_ops_prio_3.contains(&symbol_stack[symbol_stack.len()-1])
102+
&& symbol_stack[symbol_stack.len()-1] != &')'{
103+
symbol_stack.push(chr);
104+
break;
105+
}
106+
else{
107+
//pop the last symbol and add it to the output
108+
output.push(symbol_stack[symbol_stack.len()-1].to_string());
109+
symbol_stack.pop();
189110
}
190111
}
191-
else if chr == &'('{
192-
//i is a start parenthesis
193-
//println!("{} is a start parenthesis", chr);
194-
195-
//we always place it on the stack
196-
symbol_stack.push(chr);
112+
}
113+
else if math_ops_prio_2.contains(&chr){
114+
//it must be an operator of prio 2
115+
116+
loop{
117+
//if the last value in the stack is of lower prio or if the stack i empty
118+
//push the value to the stack
119+
//if the last value is not prio 2 and is not an end parenthesis add the prio 2 operand
120+
if ![&math_ops_prio_2[..],&math_ops_prio_3[..]].concat().contains(&symbol_stack[symbol_stack.len()-1])
121+
&& symbol_stack[symbol_stack.len()-1] != &')'{
122+
symbol_stack.push(chr);
123+
break;
124+
}
125+
else{
126+
//pop the last symbol and add it to the output
127+
output.push(symbol_stack[symbol_stack.len()-1].to_string());
128+
symbol_stack.pop();
129+
}
197130
}
198-
else if chr == &')'{
199-
//i is a end parenthesis
200-
//println!("{} is an end parenthesis", chr);
201-
202-
loop{
203-
//pop symbols to the output until it reaches an start parenthesis
204-
if symbol_stack[symbol_stack.len()-1] != &'(' {
205-
output.push(symbol_stack[symbol_stack.len()-1].to_string());
206-
symbol_stack.pop();
207-
}
208-
else{
209-
symbol_stack.pop();
210-
break;
211-
}
131+
}
132+
else if math_ops_prio_1.contains(&chr){
133+
//it must be and operator of prio 1
134+
135+
loop{
136+
//if the last value in the stack is a start parenthesis or
137+
//if the stack is empty push the prio 1 operator to the stack
138+
//else pop all symbols that are higher priority to the output
139+
if symbol_stack.len() == 0 || symbol_stack[symbol_stack.len()-1] == &'(' {
140+
symbol_stack.push(chr);
141+
break;
142+
}
143+
else{
144+
output.push(symbol_stack[symbol_stack.len()-1].to_string());
145+
symbol_stack.pop();
212146
}
213147
}
214148
}
215-
//emptying the stack
216-
for _ in 0..symbol_stack.len(){
217-
output.push(symbol_stack[symbol_stack.len()-1].to_string());
218-
symbol_stack.pop();
149+
else if chr == &'('{
150+
//it is a start parenthesis
151+
//we always place it on the stack
152+
symbol_stack.push(chr);
153+
}
154+
else if chr == &')'{
155+
//it is a end parenthesis
156+
157+
loop{
158+
//pop symbols to the output until it reaches an start parenthesis
159+
if symbol_stack[symbol_stack.len()-1] != &'(' {
160+
output.push(symbol_stack[symbol_stack.len()-1].to_string());
161+
symbol_stack.pop();
162+
}
163+
else{
164+
symbol_stack.pop();
165+
break;
166+
}
167+
}
219168
}
220-
221-
//for debugging\
222-
//println!("{:?}", symbol_stack);
223-
//println!("{:?}", output);
224-
//println!("{:?}", self.infix);
225-
226-
self.reverse_pn = output;
227-
228-
Ok(())
229169
}
170+
//emptying the stack
171+
for _ in 0..symbol_stack.len(){
172+
output.push(symbol_stack[symbol_stack.len()-1].to_string());
173+
symbol_stack.pop();
174+
}
175+
176+
Ok(
177+
output
178+
)
230179
}
231180

181+

0 commit comments

Comments
 (0)