1 class Preprocessor
2 def initialize(input, output, filename)
3 @input = input
4 @output = output
5 @filename = filename
6 @linenum = 1
7 end
8
9 def getline
10 line = @input.gets
11 @linenum += 1 if not line.nil?
12 return line
13 end
14
15 def preprocess
16 success = false
17 begin
18 loop do
19 line = getline
20 break if line.nil?
21 case line
22 when /(.*[^\\]|^)\#\{(.*?)\}(.*)/
23 puts "#{$1}#{evaluate($2, @linenum)}#{$3}"
24 when /^\#ruby\s+<<(.*)/
25 marker = $1
26 str = ''
27 evalstart = @linenum
28 loop do
29 line = getline
30 if line.nil? then
31 raise "End of input without #{marker}"
32 end
33 break if line.chomp == marker
34 str << line
35 end
36 result = evaluate(str, evalstart)
37 puts result if not result.nil?
38 when /^\#ruby\s+(.*)/
39 str = line = $1
40 while line[-1] == ?\\
41 str.chop!
42 line = getline
43 break if line.nil?
44 line.chomp!
45 str << line
46 end
47 result = evaluate(str, @linenum)
48 puts result if not result.nil?
49 else
50 puts line
51 end
52 end
53 success = true
54 ensure
55 if not success then
56 $stderr.puts "Error on line #{@linenum}:"
57 end
58 end
59 end
60
61 def evaluate(str, linenum)
62 result = eval(str, TOPLEVEL_BINDING, @filename, linenum)
63 success = true
64 return result
65 end
66
67 def puts(line)
68 @output.puts(line)
69 end
70 end
71
72 def puts(line)
73 $preprocessor.puts(line)
74 end
75
76 if __FILE__ == $0 then
77 input_file = ARGV[0]
78 output_file = ARGV[1]
79
80 input = input_file ? File.open(input_file) : $stdin
81 output = output_file ? File.open(output_file, 'w') : $stdout
82
83 success = false
84 begin
85 $preprocessor = Preprocessor.new(input, output, input_file || "(stdin)")
86 $preprocessor.preprocess()
87 success = true
88 ensure
89 if not success then
90 File.unlink(output_file) rescue Errno::ENOENT
91 end
92 end
93 end