#!/usr/bin/ruby # whitepsace-asm # 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 class Assembler 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 assemble(sourceName) destName = sourceName.chomp(".wsa") + ".ws" File.open(destName, "w") do |dest| @dest = dest File.open(sourceName, "r") do |source| @source = source for line in source line = line.strip.gsub(/#.*$/, "") next if line.empty? if line =~ /^(\d+):$/ translate("label #{$1}") else translate(line) end end end end end private def error(message) puts "#{@source.path}:#{@source.lineno}: #{message}" exit 1 end def encodeSignedNumber(n) (n >= 0 ? " " : "\t") + encodeUnsignedNumber(n.abs) end def encodeUnsignedNumber(n) ("%b" % n).tr("01", " \t") + "\n" end def translate(line) for ws, opcode, arg in Opcodes r = "^#{opcode}" if arg r << '\s+(' r << '(-|\+)?' if arg == :signed r << '\d+)' end r << '$' if line =~ Regexp.new(r) @dest.print ws case arg when :signed @dest.print encodeSignedNumber($1.to_i) when :unsigned @dest.print encodeUnsignedNumber($1.to_i) end end end end end for sourceName in ARGV Assembler.new.assemble(sourceName) end