@@ -21,211 +21,161 @@ impl Error {
21
21
}
22
22
}
23
23
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 ( ) ;
56
37
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) ;
98
54
}
55
+ continue ;
99
56
}
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
- }
129
57
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 ) ;
134
62
}
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) ;
146
80
}
147
81
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 ( ) ) ;
151
83
}
152
84
}
85
+ continue ;
153
86
}
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) ;
172
92
}
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 ( ) ;
189
110
}
190
111
}
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
+ }
197
130
}
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 ( ) ;
212
146
}
213
147
}
214
148
}
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
+ }
219
168
}
220
-
221
- //for debugging\
222
- //println!("{:?}", symbol_stack);
223
- //println!("{:?}", output);
224
- //println!("{:?}", self.infix);
225
-
226
- self . reverse_pn = output;
227
-
228
- Ok ( ( ) )
229
169
}
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
+ )
230
179
}
231
180
181
+
0 commit comments