You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
1.5 KiB
Ruby

# 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!
while input.length > 0
case input
when /\A-?\d+(\.\d+)?/
stack << Number.new($&.to_i)
else
second, first = stack.pop(), 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