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
-
*returns*: token of the current pointer value
# File lib/linmeric/Calculator.rb, line 208 def current_tk return @stream[@i] end
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
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
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
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 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 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