Class: MathExpression::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/math_expression/parser.rb

Instance Method Summary collapse

Constructor Details

#initialize(expression) ⇒ Parser

Returns a new instance of Parser.



4
5
6
# File 'lib/math_expression/parser.rb', line 4

def initialize(expression)
  @expression = expression
end

Instance Method Details

#evaluateObject



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/math_expression/parser.rb', line 73

def evaluate
  stack = []
  to_postfix.each do |token|
    result = case token
    when '+'
      stack.pop + stack.pop
    when '-'
      first, second = stack.pop, stack.pop
      second - first
    when '*'
      stack.pop * stack.pop
    when '/'
      first, second = stack.pop, stack.pop
      second / first
    else
      token.to_f
    end
    stack.push(result)
  end
  stack.pop
end

#to_postfixObject



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/math_expression/parser.rb', line 36

def to_postfix
  output_queue = []
  operator_stack = []

  to_tokens.each do |token|
    type, value = token[:type], token[:value]

    case type
    when :number
      output_queue << value
    when :operator
      loop do
        break if operator_stack.empty?
        break if left_parenthesis?(operator_stack.last)
        operator_on_stack_precedence = operator_precedence(operator_stack.last)
        current_operator_precedence = operator_precedence(value)
        break if operator_on_stack_precedence <= current_operator_precedence

        output_queue << operator_stack.pop
      end
      operator_stack.push(value)
    when :parenthesis
      if left_parenthesis?(value)
        operator_stack.push(value)
      else
        while !left_parenthesis?(operator_stack.last)
          output_queue << operator_stack.pop
        end
        if left_parenthesis?(operator_stack.last)
          operator_stack.pop
        end
      end
    end
  end
  (output_queue + operator_stack.reverse)
end

#to_tokensObject



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/math_expression/parser.rb', line 8

def to_tokens
  tokens = []
  reading_number = []

  form_number = lambda do
    return if reading_number.empty?
    num = reading_number.join.to_f
    tokens << { type: :number, value: num }
    reading_number = []
  end

  printable_chars = expression.chars.reject { |c| c == ' ' }

  printable_chars.each do |character|
    if operator?(character)
      form_number.call
      tokens << { type: :operator, value: character }
    elsif parenthesis?(character)
      form_number.call
      tokens << { type: :parenthesis, value: character }
    else
      reading_number << character
    end
  end
  form_number.call
  tokens
end