class Extract::MathCalc

Public Class Methods

method_missing(sym,*args,&b) click to toggle source
# File lib/extract/math_calc.rb, line 106
def method_missing(sym,*args,&b)
  new.send(sym,*args,&b)
end

Public Instance Methods

parse_eval(input) click to toggle source
# File lib/extract/math_calc.rb, line 89
def parse_eval(input)
  raw_input = input
  #raise input.map { |x| x.text_value }.inspect
  input = input.map { |x| MathWrapper.new(:str => (x.respond_to?(:excel_value) ? x.excel_value : x.text_value)) }
  #input = input.split(" ") if input.kind_of?(String)
  res = shunting_yard(input)
  #puts "before rpn #{res.inspect}"
  begin
    res = rpn(res)
  rescue => exp
    puts raw_input.map { |x| x.text_value }.inspect
    puts res.inspect
    raise exp
  end
end
rpn(input) click to toggle source
# File lib/extract/math_calc.rb, line 76
def rpn(input)
  results = []
  input.each do |object|
    if object.operator?
      r, l = results.pop, results.pop
      results << object.apply(l, r)
    else
      results << object
    end
  end
  results.first
end
shunting_yard(input) click to toggle source
# File lib/extract/math_calc.rb, line 45
def shunting_yard(input)
  [].tap do |rpn|

    # where I store operators before putting them onto final rpn list
    operator_stack = []

    input.each do |object|

      if object.operator?
        op1 = object

        # while we have an operator on the temp stack
        # and that op on the temp stack has a higher precedence than the current op
        while (op2 = operator_stack.last) && (op1.left_associative? ? op1.precedence <= op2.precedence : op1.precedence < op2.precedence)
          rpn << operator_stack.pop 
        end
        operator_stack << op1
      else
        rpn << object
      end
    end
    rpn << operator_stack.pop until operator_stack.empty?
  end
end
shunting_yard_old(input) click to toggle source
# File lib/extract/math_calc.rb, line 70
def shunting_yard_old(input)
  input = input.map { |x| MathWrapper.new(:str => x) }
  res = shunting_yard_inner(input)
  res.map { |x| x.str }
end