Skip to content

Instantly share code, notes, and snippets.

@wnoizumi
Created July 26, 2012 19:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wnoizumi/3184103 to your computer and use it in GitHub Desktop.
Save wnoizumi/3184103 to your computer and use it in GitHub Desktop.
Shunting Yard algorithm
class ShuntingYard
@@op_precedence = {
'+' => 2,
'-' => 2,
'*' => 3,
'/' => 3,
'^' => 4
}
def op_is_left?(operator)
return (operator =~ /\^/) == nil
end
def initialize(expression)
@output = []
@stack = []
@expression = expression.delete(" ")
@pc = 0
end
def result
while has_tokens
parse_number if token_is_number?
parse_operator if token_is_operator?
parse_left_parenthesis if token_is_left_parenthesis?
parse_right_parenthesis if token_is_right_parenthesis?
end
consume_full_stack
@output.join(" ")
end
private
def token
@expression[@pc]
end
def has_tokens
return @pc < @expression.length
end
def token_is_number?
return (token =~ /[0-9]/) != nil
end
def token_is_operator?
return @@op_precedence.has_key?(token)
end
def token_is_left_parenthesis?
return token == "("
end
def token_is_right_parenthesis?
return token == ")"
end
def parse_number
number = ""
while token_is_number?
number << token
@pc += 1
end
@output.push(number)
end
def parse_operator
while @stack.length > 0 and @@op_precedence.has_key?(@stack.last)
if @@op_precedence[token] < @@op_precedence[@stack.last] or (op_is_left?(token) and @@op_precedence[token] <= @@op_precedence[@stack.last])
@output.push(@stack.pop)
else
break
end
end
@stack.push(token)
@pc += 1
end
def parse_left_parenthesis
@stack.push(token)
@pc += 1
end
def parse_right_parenthesis
@pc += 1
while @stack.length > 0
t = @stack.pop
break if t == "("
@output.push(t)
end
#TODO validade if ( was found
end
def consume_full_stack
while @stack.length > 0
@output.push(@stack.pop)
end
end
end
require_relative "shunting_yard"
describe ShuntingYard do
it "Only a number" do
ShuntingYard.new('1').result.should == '1'
ShuntingYard.new('12').result.should == '12'
ShuntingYard.new('34534').result.should == '34534'
end
it "Simple Operation" do
ShuntingYard.new('1+2').result.should == '1 2 +'
ShuntingYard.new('33*345').result.should == '33 345 *'
end
it "Multiple Operations" do
ShuntingYard.new('1+2*3').result.should == '1 2 3 * +'
ShuntingYard.new('23+6*12/2^2').result.should == '23 6 12 * 2 2 ^ / +'
end
it "Operations with parenthesis" do
ShuntingYard.new('(1+2)*3').result.should == '1 2 + 3 *'
ShuntingYard.new('3 + 4 * 2 / (1 - 5) ^ 2 ^ 3').result.should == '3 4 2 * 1 5 - 2 3 ^ ^ / +'
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment