# This pattern provides an interpreter to deal with an abstract language. Using
# classes we can understand the inputs for parse them

# Parsing entity
class Number
  attr_reader :value

  def initialize(value)
    @value = value
  end

  def execute
    value
  end
end

# Operation interface
class Operation
  attr_reader :left, :right

  def initialize(left, right)
    @left = left
    @right = right
  end

  def execute
    raise NotImplementedError
  end
end

# Operations
class Plus < Operation
  def execute
    left.execute + right.execute
  end
end

class Minus < Operation
  def execute
    left.execute - right.execute
  end
end

class Multiply < Operation
  def execute
    left.execute * right.execute
  end
end

class Devide < Operation
  def execute
    left.execute / right.execute
  end
end

# Interpreter class
class Interpreter
  def self.parse(input)
    stack = []

    input.lstrip!
    until input.empty?
      case input
      when /\A-?\d+(\.\d+)?/
        stack << Number.new($&.to_i)
      else
        second = stack.pop
        first = stack.pop

        case input
        when /\A\+/
          stack << Plus.new(first, second)
        when /\A\-/
          stack << Minus.new(first, second)
        when /\A\*/
          stack << Multiply.new(first, second)
        else
          raise SyntaxError
        end
      end

      input = $'
      input.lstrip!
    end

    raise SyntaxError unless stack.size == 1

    stack.first.execute
  end
end

# Usage
puts Interpreter.parse('1 + 1 + 2 - 1') # => 3
