Made parser able to report multiple errors per call, using new Voodoo::Parser::Multip...
[voodoo-lang.git] / lib / voodoo / compiler.rb
blobba1fd1c61ab71cd39ae16aa13b9d776325a35b78
1 require 'voodoo/parser'
3 module Voodoo
4   # Voodoo compiler driver.
5   # The compiler driver reads input from a parser (see
6   # Voodoo::Parser), feeds it to a code generator (see
7   # Voodoo::CommonCodeGenerator), and writes the generated code.
8   #
9   # An example of its usage can be found on the main page for the
10   # Voodoo module.
11   class Compiler
12     class Error < StandardError
13       def initialize errors
14         @errors = errors
15       end
17       attr_reader :errors
19       def message
20         msg = ""
21         @errors.each {|e| msg << e.message << "\n"}
22         msg
23       end
24     end
26     # Initialize a compiler.
27     #
28     # Parameters:
29     # [parser] the parser to be used (see Voodoo::Parser)
30     # [code_generator] the code generator to be used
31     #                  (see Voodoo::CommonCodeGenerator)
32     # [output] an IO object. The generated code will be written to it
33     def initialize parser, code_generator, output
34       @parser = parser
35       @generator = code_generator
36       @output = output
37     end
39     # Perform the compilation.
40     def compile
41       section = :code
42       errors = []
43       while true
44         begin
45           statement = @parser.parse_top_level
47           break if statement == nil
48           next if statement.empty?
50           case statement[0]
51           when :section
52             section = statement[1]
53           else
54             @generator.add section, statement
55           end
57         rescue Parser::MultipleErrors => e
58           errors.concat e.errors
60         rescue Parser::ParseError => e
61           errors << e
62         end
64         if errors.length >= 100
65           # Too many errors, give up.
66           raise Error.new(errors)
67         end
68       end
70       if errors.empty?
71         @generator.write @output
72       else
73         raise Error.new(errors)
74       end
75     end
76   end
77 end