Class: Calculator::Evaluator
- Inherits:
-
Object
- Object
- Calculator::Evaluator
- Defined in:
- lib/linmeric/Calculator.rb
Overview
Evaluator parses and evaluates at the same time the stream of tokens
- Author
-
Massimiliano Dal Mas ([email protected])
- License
-
Distributed under MIT license
Constant Summary collapse
- OPERATORS =
{ "+" => lambda do |a,b| return (a || 0) + (b || 0) end, "-" => lambda do |a,b| return (a || 0) - (b || 0) end, "*" => lambda do |a,b| return a * b end, "/" => lambda do |a,b| unless b != 0 @error = true return nil end return a / b.to_f end, "^" => lambda do |a,b| unless a != 0 and b != 0 @error = true return nil end return a ** b end }
Instance Method Summary collapse
-
#current_tk ⇒ Object
-
returns: token of the current pointer value.
-
-
#evaluate(stream) ⇒ Object
Evaluates the global expression.
-
#make_op ⇒ Object
Solves the operations saved in @op.
-
#parse(m_end = nil) ⇒ Object
It parses the stream of tokens.
-
#priority(op) ⇒ Object
Returns the operator priority.
-
#state0_1(state = 1) ⇒ Object
State0_1 accepts only numbers or ‘(’.
-
#state2 ⇒ Object
State2 accepts only operators.
Instance Method Details
#current_tk ⇒ Object
-
returns: token of the current pointer value
208 209 210 |
# File 'lib/linmeric/Calculator.rb', line 208 def current_tk return @stream[@i] end |
#evaluate(stream) ⇒ Object
Evaluates the global expression
-
argument: stream of tokens (Array)
-
returns: result of the operations;
nilif an error occourred
121 122 123 124 125 126 127 |
# File 'lib/linmeric/Calculator.rb', line 121 def evaluate(stream) @stack = [] @stream = stream @i = 0 @error = false return parse end |
#make_op ⇒ Object
Solves the operations saved in @op
198 199 200 201 202 203 204 205 |
# File 'lib/linmeric/Calculator.rb', line 198 def make_op while @op.size > 0 and !@error do b = @num.pop a = @num.pop op = @op.pop @num.push OPERATORS[op][a,b] end end |
#parse(m_end = nil) ⇒ Object
It parses the stream of tokens
-
argument: specific end-token (
nildefault) -
returns: result of the operations;
nilif an error occourred
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/linmeric/Calculator.rb', line 133 def parse(m_end = nil) @num = [] @op = [] st = state0_1(0) return nil if @error @i += 1 while @i < @stream.size and current_tk.value != m_end do st = self.send(st) return nil if @error @i += 1 end return nil if st == :state_0_1 make_op return @num.pop end |
#priority(op) ⇒ Object
Returns the operator priority
-
argument: operator (string)
-
returns: priority (fixnum)
216 217 218 219 220 221 222 223 224 225 |
# File 'lib/linmeric/Calculator.rb', line 216 def priority(op) case op when "+","-" return 1 when "*","/" return 2 when /\^/ return 3 end end |
#state0_1(state = 1) ⇒ Object
State0_1 accepts only numbers or ‘(’
-
argument: specification of which state must be runned (1 default)
-
returns: next state (symbol)
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/linmeric/Calculator.rb', line 153 def state0_1(state = 1) case current_tk.tag when :NUMBER @num.push current_tk.value when :L_PAR @i += 1 @stack.push @op @stack.push @num res = parse(")") @num = @stack.pop @num << res @op = @stack.pop when :OPERATOR if (["+","-"].include? current_tk.value) and (state)== 0 then @op.push current_tk.value return :state0_1 else @error = true end else @error = true end return :state2 end |
#state2 ⇒ Object
State2 accepts only operators
-
returns: next state (symbol)
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/linmeric/Calculator.rb', line 181 def state2 if current_tk.tag == :OPERATOR then if @op.size == 0 then @op.push current_tk.value elsif priority(current_tk.value) >= priority(@op.last) @op.push current_tk.value elsif priority(current_tk.value) < priority(@op.last) make_op @op.push current_tk.value end else @error = true end return :state0_1 end |