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