Class: Extract::MathCalc

Inherits:
Object show all
Defined in:
lib/extract/math_calc.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.method_missing(sym, *args, &b) ⇒ Object



106
107
108
# File 'lib/extract/math_calc.rb', line 106

def method_missing(sym,*args,&b)
  new.send(sym,*args,&b)
end

Instance Method Details

#parse_eval(input) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# 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) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
# 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) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# 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) ⇒ Object



70
71
72
73
74
# 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