Created
July 26, 2012 19:46
-
-
Save wnoizumi/3184103 to your computer and use it in GitHub Desktop.
Shunting Yard algorithm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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