#!/usr/bin/ruby # whitepsace-ruby # Copyright (C) 2003 by Wayne E. Conrad # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Opcodes = [ [' ', :push, :signed], [' \n ', :dup], [' \n\t', :swap], [' \n\n', :discard], ['\t ', :add], ['\t \t', :sub], ['\t \n', :mul], ['\t \t ', :div], ['\t \t\t', :mod], ['\t\t ', :store], ['\t\t\t', :retrieve], ['\n ', :label, :unsigned], ['\n \t', :call, :unsigned], ['\n \n', :jump, :unsigned], ['\n\t ', :jz, :unsigned], ['\n\t\t', :jn, :unsigned], ['\n\t\n', :ret], ['\n\n\n', :exit], ['\t\n ', :outchar], ['\t\n \t', :outnum], ['\t\n\t ', :readchar], ['\t\n\t\t', :readnum], ] def error(message) $stderr.puts "Error: #{message}" exit 1 end class Tokenizer attr_reader :tokens def initialize @tokens = [] @program = $<.read.tr("^ \t\n", "") while @program != "" do @tokens << tokenize end end private def tokenize for ws, opcode, arg in Opcodes if @program =~ /\A#{ws}#{arg ? '([ \t]*)\n' : '()'}(.*)\z/m @program = $2 case arg when :unsigned return [opcode, eval "0b#{$1.tr(" \t", "01")}"] when :signed value = eval "0b#{$1[1..-1].tr(" \t", "01")}" value *= -1 if ($1[0] == ?\t) return [opcode, value] else return [opcode] end end end error("Unknown command: #{@program.inspect}") end end class Disassembler def disassemble(tokens) for token in tokens if token[0] == :label puts "#{token[1]}:" else puts "%8s%-8s%s" % [nil, token[0], token[1]] end end end end Disassembler.new.disassemble(Tokenizer.new.tokens) if $0 == __FILE__