#!/usr/bin/ruby # $Id: cinf.rb 114 2006-04-27 07:04:23Z adam $ # cinf.rb - toplevel driver for the compiler # This file is the toplevel driver for the compiler. It builds a parser, # hands it the input file, sets it going, generates code, and writes the output. require 'getoptlong' require 'frontend/cinf.rl.rb' require 'frontend/cinf.tab.rb' require 'tree/tree.rb' require 'tree/stdlib.rb' debug=false debug_parser=false dump_3ac = false def usage $stderr.puts "Usage: cinf.rb [options] infile [outfile]" $stderr.puts "options may be any of:" $stderr.puts "--debug (-d) Print debugging information while compiling" $stderr.puts "--yydebug (-y) Print Racc debugging information while parsing" $stderr.puts "--3ac (-3) Write intermediate code to " + ".3ac" $stderr.puts "--help (-h) This message" $stderr.puts "If outfile is not specified, " + "output will be written to .s" $stderr.puts "If outfile is -, output will be written to standard output" exit 0 end opts = GetoptLong.new( ["--debug", "-d", GetoptLong::NO_ARGUMENT], ["--3ac", "-3", GetoptLong::NO_ARGUMENT], ["--yydebug", "-y", GetoptLong::NO_ARGUMENT], ["--help", "-h", GetoptLong::NO_ARGUMENT]) opts.each do |opt,arg| case opt when "--debug" debug=true when "--3ac" dump_3ac = true when "--yydebug" debug_parser=true when "--help" usage end end if(ARGV.length < 1) usage end import_stdlib begin lexer = CinfLexer.new lexer.load_file(ARGV[0]) rescue CinfLexer::ScanError md = $!.message.match(/'(.*)'/) $stderr.puts "Unrecognized token '#{md[1]}' on line #{lexer.lineno}" $stderr.puts "(exiting)" exit 4 end parser = CinfParser.new(lexer,debug_parser) begin parser.parse ast = parser.tree ast.typecheck ast.emit_3ac rescue Racc::ParseError $stderr.puts $!.message $stderr.puts "(exiting)" exit 1 rescue TypeError $stderr.puts "Type error:" $stderr.puts $!.message $stderr.puts "(exiting)" exit 2 rescue RuntimeError $stderr.puts "Semantic error:" $stderr.puts $!.message $stderr.puts "(exiting" exit 3 end if(debug) then puts ast.inspect puts "\n" puts ast.pp puts "\n" puts CompilerState.instance.symtab.pp puts CompilerState.instance.program.to_s end if(dump_3ac) then md = ARGV[0].match(/(.*)\.cinf/) tac_file = md[1] + ".3ac" File.open(tac_file,"w") do |f| tac_pgm = CompilerState.instance.program.to_s f << tac_pgm end end outstr = CompilerState.instance.program.emit_mips if(ARGV[1] != "-") then if(ARGV[1].nil?) md = ARGV[0].match(/(.*)\.cinf/) filename = md[1] + ".s" else filename = ARGV[1] end File.open(filename,"w") do |f| f.puts outstr end else puts outstr end