1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#!/usr/bin/ruby
2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver# encoding: utf-8
3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=begin LICENSE
5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver[The "BSD licence"]
6324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverCopyright (c) 2009-2010 Kyle Yetter
7324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverAll rights reserved.
8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
9324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverRedistribution and use in source and binary forms, with or without
10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvermodification, are permitted provided that the following conditions
11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverare met:
12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1. Redistributions of source code must retain the above copyright
14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    notice, this list of conditions and the following disclaimer.
15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 2. Redistributions in binary form must reproduce the above copyright
16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    notice, this list of conditions and the following disclaimer in the
17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    documentation and/or other materials provided with the distribution.
18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 3. The name of the author may not be used to endorse or promote products
19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    derived from this software without specific prior written permission.
20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
21324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverIN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=end
33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverrequire 'optparse'
35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverrequire 'antlr3'
36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvermodule ANTLR3
38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=begin rdoc ANTLR3::Main
40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
41324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverNamespace module for the quick script Main classes.
42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=end
44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvermodule Main
46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=begin rdoc ANTLR3::Main::Options
49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
50324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverDefines command-line options and attribute mappings shared by all types of
51324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverMain classes.
52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=end
54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvermodule Options
56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  # the input encoding type; defaults to +nil+ (currently, not used)
57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  attr_accessor :encoding
58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  # the input stream used by the Main script; defaults to <tt>$stdin</tt>
59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  attr_accessor :input
60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  # a boolean flag indicating whether or not to run the Main
61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  # script in interactive mode; defaults to +false+
62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  attr_accessor :interactive
63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  attr_accessor :no_output
64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  attr_accessor :profile
65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  attr_accessor :debug_socket
66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  attr_accessor :ruby_prof
67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def initialize( options = {} )
69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @no_output    = options.fetch( :no_output, false )
70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @profile      = options.fetch( :profile, false )
71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @debug_socket = options.fetch( :debug_socket, false )
72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @ruby_prof    = options.fetch( :ruby_prof, false )
73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @encoding     = options.fetch( :encoding, nil )
74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @interactive  = options.fetch( :interactive, false )
75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @input        = options.fetch( :input, $stdin )
76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  # constructs an OptionParser and parses the argument list provided by +argv+
79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def parse_options( argv = ARGV )
80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    oparser = OptionParser.new do | o |
81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      o.separator 'Input Options:'
82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      o.on( '-i', '--input "text to process"', doc( <<-END ) ) { |val| @input = val }
84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      | a string to use as direct input to the recognizer
85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      END
86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      o.on( '-I', '--interactive', doc( <<-END ) ) { @interactive = true }
88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      | run an interactive session with the recognizer
89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      END
90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    setup_options( oparser )
93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return oparser.parse( argv )
94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverprivate
97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def setup_options( oparser )
99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # overridable hook to modify / append options
100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def doc( description_string )
103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    description_string.chomp!
104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    description_string.gsub!( /^ *\| ?/, '' )
105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    description_string.gsub!( /\s+/, ' ' )
106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return description_string
107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=begin rdoc ANTLR3::Main::Main
112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
113324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverThe base-class for the three primary Main script-runner classes.
114324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverIt defines the skeletal structure shared by all main
115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverscripts, but isn't particularly useful on its own.
116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=end
118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass Main
120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  include Options
121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  include Util
122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  attr_accessor :output, :error
123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def initialize( options = {} )
125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @input  = options.fetch( :input, $stdin )
126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @output = options.fetch( :output, $stdout )
127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @error  = options.fetch( :error, $stderr )
128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @name   = options.fetch( :name, File.basename( $0, '.rb' ) )
129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    super
130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    block_given? and yield( self )
131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  # runs the script
135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def execute( argv = ARGV )
136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    args = parse_options( argv )
137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    setup
138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @interactive and return execute_interactive
140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    in_stream = 
142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      case
143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      when @input.is_a?( ::String ) then StringStream.new( @input )
144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      when args.length == 1 && args.first != '-'
145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        ANTLR3::FileStream.new( args[ 0 ] )
146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      else ANTLR3::FileStream.new( @input )
147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    case
149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    when @ruby_prof
150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      load_ruby_prof
151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      profile = RubyProf.profile do
152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        recognize( in_stream )
153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      printer = RubyProf::FlatPrinter.new( profile )
155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      printer.print( @output )
156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    when @profile
157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      require 'profiler'
158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      Profiler__.start_profile
159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      recognize( in_stream )
160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      Profiler__.print_profile
161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    else
162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      recognize( in_stream )
163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverprivate
167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def recognize( *args )
169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # overriden by subclasses
170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def execute_interactive
173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @output.puts( tidy( <<-END ) )
174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | ===================================================================
175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | Ruby ANTLR Console for #{ $0 }
176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | * Enter source code lines 
178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | * Enter EOF to finish up and exit
179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    |   (control+D on Mac/Linux/Unix or control+Z on Windows)
180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | ===================================================================
181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | 
182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    read_method = 
185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      begin
186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        require 'readline'
187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        line_number = 0
188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        lambda do
189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          begin
190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if line = Readline.readline( "#@name:#{ line_number += 1 }> ", true )
191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver              line << $/
192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            else
193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver              @output.print( "\n" ) # ensures result output is on a new line after EOF is entered
194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver              nil
195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            end
196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          rescue Interrupt, EOFError
197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            retry
198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          end
199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          line << "\n" if line
200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        end
201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        
202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      rescue LoadError
203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        lambda do
204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          begin
205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            printf( "%s:%i> ", @name, @input.lineno )
206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            flush
207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            line = @input.gets or
208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver              @output.print( "\n" ) # ensures result output is on a new line after EOF is entered
209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            line
210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          rescue Interrupt, EOFError
211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            retry
212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          end
213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          line
214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        end
215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    stream = InteractiveStringStream.new( :name => @name, &read_method )
218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    recognize( stream )
219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def screen_width
222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    ( ENV[ 'COLUMNS' ] || 80 ).to_i
223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def attempt( lib, message = nil, exit_status = nil )
226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    yield
227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  rescue LoadError => error
228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    message or raise
229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @error.puts( message )
230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    report_error( error )
231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    report_load_path
232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    exit( exit_status ) if exit_status
233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  rescue => error
234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @error.puts( "received an error while attempting to load %p" % lib )
235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    report_error( error )
236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    exit( exit_status ) if exit_status
237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def report_error( error )
240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    puts!( "~ error details:" )
241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    puts!( '  [ %s ]' % error.class.name )
242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    message = error.to_s.gsub( /\n/, "\n     " )
243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    puts!( '  -> ' << message )
244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    for call in error.backtrace
245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      puts!( '     ' << call )
246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def report_load_path
250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    puts!( "~ content of $LOAD_PATH: " )
251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    for dir in $LOAD_PATH
252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      puts!( "  - #{ dir }" )
253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def setup
257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # hook
258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def fetch_class( name )
261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    name.nil? || name.empty? and return( nil )
262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    unless constant_exists?( name )
263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      try_to_load( name )
264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      constant_exists?( name ) or return( nil )
265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    name.split( /::/ ).inject( Object ) do |mod, name|
268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      # ::SomeModule splits to ['', 'SomeModule'] - so ignore empty strings
269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      name.empty? and next( mod ) 
270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      mod.const_get( name )
271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def constant_exists?( name )
275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    eval( "defined?(#{ name })" ) == 'constant'
276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def try_to_load( name )
279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if name =~ /(\w+)::(Lexer|Parser|TreeParser)$/
280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      retry_ok = true
281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      module_name, recognizer_type = $1, $2
282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      script = name.gsub( /::/, '' )
283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      begin
284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return( require( script ) )
285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      rescue LoadError
286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if retry_ok
287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          script, retry_ok = module_name, false
288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          retry
289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        else
290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          return( nil )
291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        end
292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  %w(puts print printf flush).each do |method|
297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    class_eval( <<-END, __FILE__, __LINE__ )
298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      private
299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      def #{ method }(*args)
301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        @output.#{ method }(*args) unless @no_output
302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      def #{ method }!( *args )
305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        @error.#{ method }(*args) unless @no_output
306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=begin rdoc ANTLR3::Main::LexerMain
313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
314324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverA class which implements a handy test script which is executed whenever an ANTLR
315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvergenerated lexer file is run directly from the command line.
316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=end
318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass LexerMain < Main
319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def initialize( lexer_class, options = {} )
320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    super( options )
321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @lexer_class = lexer_class
322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def recognize( in_stream )
325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    lexer = @lexer_class.new( in_stream )
326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    loop do
328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      begin
329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        token = lexer.next_token
330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if token.nil? || token.type == ANTLR3::EOF then break
331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        else display_token( token )
332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        end
333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      rescue ANTLR3::RecognitionError => error
334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        report_error( error )
335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        break
336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def display_token( token )
341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    case token.channel
342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    when ANTLR3::DEFAULT_CHANNEL
343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      prefix = '-->'
344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      suffix = ''
345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    when ANTLR3::HIDDEN_CHANNEL
346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      prefix = '#  '
347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      suffix = ' (hidden)'
348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    else
349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      prefix = '~~>'
350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      suffix = ' (channel %p)' % token.channel
351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    printf( "%s %-15s %-15p @ line %-3i col %-3i%s\n",
354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver           prefix, token.name, token.text,
355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver           token.line, token.column, suffix )
356324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
357324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
358324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
359324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
360324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=begin rdoc ANTLR3::Main::ParserMain
361324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
362324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverA class which implements a handy test script which is executed whenever an ANTLR
363324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvergenerated parser file is run directly from the command line.
364324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
365324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=end
366324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass ParserMain < Main
367324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  attr_accessor :lexer_class_name,
368324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                :lexer_class,
369324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                :parser_class,
370324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                :parser_rule,
371324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                :port,
372324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                :log
373324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
374324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def initialize( parser_class, options = {} )
375324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    super( options )
376324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @lexer_class_name = options[ :lexer_class_name ]
377324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @lexer_class      = options[ :lexer_class ]
378324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @parser_class     = parser_class
379324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @parser_rule = options[ :parser_rule ]
380324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if @debug = ( @parser_class.debug? rescue false )
381324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @trace = options.fetch( :trace, nil )
382324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @port = options.fetch( :port, ANTLR3::Debug::DEFAULT_PORT )
383324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @log  = options.fetch( :log, @error )
384324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
385324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @profile = ( @parser_class.profile? rescue false )
386324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
387324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
388324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def setup_options( opt )
389324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    super
390324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
391324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    opt.separator ""
392324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    opt.separator( "Parser Configuration:" )
393324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
394324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    opt.on( '--lexer-name CLASS_NAME', "name of the lexer class to use" ) { |val|
395324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @lexer_class_name = val
396324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @lexer_class = nil
397324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
398324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
399324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    opt.on( '--lexer-file PATH_TO_LIBRARY', "path to library defining the lexer class" ) { |val|
400324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      begin
401324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        test( ?f, val ) ? load( val ) : require( val )
402324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      rescue LoadError
403324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        warn( "unable to load the library specified by --lexer-file: #{ $! }" )
404324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
405324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
406324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
407324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    opt.on( '--rule NAME', "name of the parser rule to execute" ) { |val| @parser_rule = val }
408324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
409324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if @debug
410324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      opt.separator ''
411324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      opt.separator "Debug Mode Options:"
412324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
413324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      opt.on( '--trace', '-t', "print rule trace instead of opening a debug socket" ) do
414324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        @trace = true
415324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
416324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
417324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      opt.on( '--port NUMBER', Integer, "port number to use for the debug socket" ) do |number|
418324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        @port = number
419324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
420324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
421324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      opt.on( '--log PATH', "path of file to use to record socket activity",
422324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver             "(stderr by default)" ) do |path|
423324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        @log = open( path, 'w' )
424324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
425324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
426324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
427324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
428324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def setup
429324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    unless @lexer_class ||= fetch_class( @lexer_class_name )
430324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      if @lexer_class_name
431324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        fail( "unable to locate the lexer class ``#@lexer_class_name''" )
432324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      else
433324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        unless @lexer_class = @parser_class.associated_lexer
434324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          fail( doc( <<-END ) )
435324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          | no lexer class has been specified with the --lexer-name option
436324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          | and #@parser_class does not appear to have an associated
437324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          | lexer class
438324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          END
439324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        end
440324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
441324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
442324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @parser_rule ||= @parser_class.default_rule or
443324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      fail( "a parser rule name must be specified via --rule NAME" )
444324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
445324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
446324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def recognize( in_stream )
447324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    parser_options = {}
448324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if @debug
449324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      if @trace
450324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        parser_options[ :debug_listener ] = ANTLR3::Debug::RuleTracer.new
451324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      else
452324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        parser_options[ :port ] = @port
453324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        parser_options[ :log ]  = @log
454324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
455324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
456324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    lexer = @lexer_class.new( in_stream )
457324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # token_stream = CommonTokenStream.new( lexer )
458324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    parser = @parser_class.new( lexer, parser_options )
459324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    result = parser.send( @parser_rule ) and present( result )
460324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @profile and puts( parser.generate_report )
461324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
462324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
463324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def present( return_value )
464324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    ASTBuilder > @parser_class and return_value = return_value.tree
465324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if return_value
466324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      text = 
467324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        begin
468324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          require 'pp'
469324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          return_value.pretty_inspect
470324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        rescue LoadError, NoMethodError
471324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          return_value.inspect
472324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        end
473324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      puts( text )
474324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
475324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
476324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
477324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
478324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
479324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=begin rdoc ANTLR3::Main::WalkerMain
480324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
481324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverA class which implements a handy test script which is executed whenever an ANTLR
482324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvergenerated tree walker (tree parser) file is run directly from the command line.
483324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
484324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=end
485324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
486324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass WalkerMain < Main
487324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  attr_accessor :walker_class, :lexer_class, :parser_class
488324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
489324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def initialize( walker_class, options = {} )
490324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    super( options )
491324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @walker_class = walker_class
492324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @lexer_class_name = options[ :lexer_class_name ]
493324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @lexer_class  = options[ :lexer_class ]
494324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @parser_class_name = options[ :parser_class_name ]
495324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @parser_class = options[ :parser_class ]
496324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if @debug = ( @parser_class.debug? rescue false )
497324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @port = options.fetch( :port, ANTLR3::Debug::DEFAULT_PORT )
498324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @log  = options.fetch( :log, @error )
499324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
500324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
501324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
502324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def setup_options( opt )
503324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    super
504324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
505324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    opt.separator ''
506324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    opt.separator "Tree Parser Configuration:"
507324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
508324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    opt.on( '--lexer-name CLASS_NAME', 'full name of the lexer class to use' ) { |val| @lexer_class_name = val }
509324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    opt.on(
510324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      '--lexer-file PATH_TO_LIBRARY',
511324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      'path to load to make the lexer class available'
512324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    ) { |val|
513324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      begin
514324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        test( ?f, val ) ? load( val ) : require( val )
515324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      rescue LoadError
516324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        warn( "unable to load the library `#{ val }' specified by --lexer-file: #{ $! }" )
517324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
518324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
519324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
520324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    opt.on(
521324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      '--parser-name CLASS_NAME',
522324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      'full name of the parser class to use'
523324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    ) { |val| @parser_class_name = val }
524324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    opt.on(
525324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      '--parser-file PATH_TO_LIBRARY',
526324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      'path to load to make the parser class available'
527324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    ) { |val|
528324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      begin
529324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        test( ?f, val ) ? load( val ) : require( val )
530324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      rescue LoadError
531324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        warn( "unable to load the library specified by --parser-file: #{ $! }" )
532324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
533324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
534324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
535324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    opt.on( '--parser-rule NAME', "name of the parser rule to use on the input" ) { |val| @parser_rule = val }
536324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    opt.on( '--rule NAME', "name of the rule to invoke in the tree parser" ) { |val| @walker_rule = val }
537324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
538324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if @debug
539324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      opt.separator ''
540324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      opt.separator "Debug Mode Options:"
541324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
542324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      opt.on( '--port NUMBER', Integer, "port number to use for the debug socket" ) do |number|
543324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        @port = number
544324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
545324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      opt.on( '--log PATH', "path of file to use to record socket activity",
546324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver             "(stderr by default)" ) do |path|
547324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        @log = open( path, 'w' )
548324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
549324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
550324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
551324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
552324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  # TODO: finish the Main modules
553324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def setup
554324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    unless @lexer_class ||= fetch_class( @lexer_class_name )
555324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      fail( "unable to locate the lexer class #@lexer_class_name" )
556324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
557324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    unless @parser_class ||= fetch_class( @parser_class_name )
558324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      fail( "unable to locate the parser class #@parser_class_name" )
559324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
560324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
561324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
562324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def recognize( in_stream )
563324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    walker_options = {}
564324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if @debug
565324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      walker_options[ :port ] = @port
566324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      walker_options[ :log ] = @log
567324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
568324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @lexer = @lexer_class.new( in_stream )
569324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @token_stream = ANTLR3::CommonTokenStream.new( @lexer )
570324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @parser = @parser_class.new( @token_stream )
571324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if result = @parser.send( @parser_rule )
572324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      result.respond_to?( :tree ) or fail( "Parser did not return an AST for rule #@parser_rule" )
573324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @node_stream = ANTLR3::CommonTreeNodeStream.new( result.tree )
574324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @node_stream.token_stream = @token_stream
575324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @walker = @walker_class.new( @node_stream, walker_options )
576324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      if result = @walker.send( @walker_rule )
577324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        out = result.tree.inspect rescue result.inspect
578324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        puts( out )
579324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      else puts!( "walker.#@walker_rule returned nil" )
580324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
581324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    else puts!( "parser.#@parser_rule returned nil" )
582324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
583324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
584324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
585324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
586324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
587