Last active
May 8, 2017 04:00
-
-
Save nnabeyang/ed7b373918ff4c6eb3ee52051fc2a9a9 to your computer and use it in GitHub Desktop.
逆ポーランド記法の電卓
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
#usage: ruby main.rb | |
class Parser | |
def initialize | |
@stack = [] | |
end | |
def parse(line) | |
scanner = Scanner.new(line) | |
while (token = scanner.next) do | |
add_token(token) | |
end | |
@stack.pop | |
end | |
def add_token(token) | |
token.append_to(@stack) | |
end | |
end | |
class Scanner | |
def initialize(line) | |
@buf = line.chomp.split(//) | |
@pos = 0 | |
end | |
def peek | |
while is_space do | |
@pos += 1 | |
end | |
(@buf.size > @pos)? token : nil | |
end | |
def next | |
v = peek; @pos = @e; v | |
end | |
private | |
def token | |
@e = @pos | |
if is_op | |
@e+=1 | |
AST::Op.new(@buf[@e-1]) | |
elsif is_number | |
while @buf.size > @pos && is_number(@e) do | |
@e+=1 | |
end | |
AST::Num.new(@buf[@pos...@e].join) | |
else | |
raise "invalid expression: #{@buf.join}" | |
end | |
end | |
def is_space | |
@buf[@pos] == ' ' | |
end | |
def is_number(pos=@pos) | |
/\d/.match(@buf[pos]) | |
end | |
def is_op | |
/[\+\-\*]/.match(@buf[@pos]) | |
end | |
end | |
module AST | |
class Exp | |
def initialize(l, op, r) | |
@l = l; @op = op; @r = r | |
end | |
def to_s | |
[@l, @r, @op].join(" ") | |
end | |
def append_to(stack) | |
stack.push(self) | |
end | |
def exec | |
case @op.to_s | |
when "+"; @l.exec + @r.exec | |
when "-"; @l.exec - @r.exec | |
when "*"; @l.exec * @r.exec | |
end | |
end | |
end | |
class Num | |
def initialize(v) | |
@v = v.to_i | |
end | |
def to_s; @v.to_s; end | |
def exec; @v; end | |
def append_to(stack) | |
stack.push(self) | |
end | |
end | |
class Op | |
def initialize(op) | |
@op = op | |
end | |
def to_s; @op.to_s; end | |
def append_to(stack) | |
r = stack.pop; l = stack.pop | |
stack.push(AST::Exp.new(l, self, r)) | |
end | |
end | |
end | |
parser = Parser.new | |
DATA.each do |line| | |
prog = parser.parse(line) | |
puts "#{prog.to_s} = #{prog.exec}" | |
end | |
__END__ | |
123 168 77 - + | |
11 7 * 6 + | |
15 7* 43 22 -+ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment