class Calculator::Evaluator
Evaluator
parses and evaluates at the same time the stream of tokens
- Author
-
Massimiliano Dal Mas (max.codeware@gmail.com)
- License
-
Distributed under MIT license
Constants
- OPERATORS
Public Instance Methods
current_tk()
click to toggle source
-
returns: token of the current pointer value
# File lib/linmeric/Calculator.rb, line 208 def current_tk return @stream[@i] end
evaluate(stream)
click to toggle source
Evaluates the global expression
-
argument: stream of tokens (Array)
-
returns: result of the operations;
nil
if an error occourred
# File lib/linmeric/Calculator.rb, line 121 def evaluate(stream) @stack = [] @stream = stream @i = 0 @error = false return parse end
make_op()
click to toggle source
Solves the operations saved in @op
# 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)
click to toggle source
It parses the stream of tokens
-
argument: specific end-token (
nil
default) -
returns: result of the operations;
nil
if an error occourred
# 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)
click to toggle source
Returns the operator priority
-
argument: operator (string)
-
returns: priority (fixnum)
# 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)
click to toggle source
State0_1 accepts only numbers or '('
-
argument: specification of which state must be runned (1 default)
-
returns: next state (symbol)
# 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()
click to toggle source
State2 accepts only operators
-
returns: next state (symbol)
# 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