class Preprocessor
def initialize(input, output, filename)
@input = input
@output = output
@filename = filename
@linenum = 1
end
def getline
line = @input.gets
@linenum += 1 if not line.nil?
return line
end
def preprocess
success = false
begin
loop do
line = getline
break if line.nil?
case line
when /(.*[^\\]|^)\#\{(.*?)\}(.*)/
puts "#{$1}#{evaluate($2, @linenum)}#{$3}"
when /^\#ruby\s+<<(.*)/
marker = $1
str = ''
evalstart = @linenum
loop do
line = getline
if line.nil? then
raise "End of input without #{marker}"
end
break if line.chomp == marker
str << line
end
result = evaluate(str, evalstart)
puts result if not result.nil?
when /^\#ruby\s+(.*)/
str = line = $1
while line[-1] == ?\\
str.chop!
line = getline
break if line.nil?
line.chomp!
str << line
end
result = evaluate(str, @linenum)
puts result if not result.nil?
else
puts line
end
end
success = true
ensure
if not success then
$stderr.puts "Error on line #{@linenum}:"
end
end
end
def evaluate(str, linenum)
result = eval(str, TOPLEVEL_BINDING, @filename, linenum)
success = true
return result
end
def puts(line='')
@output.puts(line)
end
end
def puts(line='')
$preprocessor.puts(line)
end
def rubypp(input_file, output_file)
input = input_file ? File.open(input_file) : $stdin
output = output_file ? File.open(output_file, 'w') : $stdout
success = false
begin
$preprocessor = Preprocessor.new(input, output, input_file || "(stdin)")
$preprocessor.preprocess()
success = true
ensure
if not success then
File.unlink(output_file) rescue Errno::ENOENT
end
end
end
if __FILE__ == $0 then
input_file = ARGV[0]
output_file = ARGV[1]
rubypp(input_file, output_file)
end