1#!/usr/bin/ruby
2# encoding: utf-8
3
4module ANTLR3
5module Util
6
7module_function
8  
9  def snake_case( str )
10    str = str.to_s.gsub( /([A-Z]+)([A-Z][a-z])/,'\1_\2' )
11    str.gsub!( /([a-z\d])([A-Z])/,'\1_\2' )
12    str.tr!( "-", "_" )
13    str.downcase!
14    str
15  end
16  
17  def parse_version( version_string )
18    version_string.split( '.' ).map! do | segment |
19      segment.to_i
20    end.freeze
21  end
22  
23  def tidy( here_doc, flow = false )
24    here_doc.gsub!( /^ *\| ?/, '' )
25    if flow
26      here_doc.strip!
27      here_doc.gsub!( /\s+/, ' ' )
28    end
29    return here_doc
30  end
31  
32  def silence_warnings
33    verbosity, $VERBOSE = $VERBOSE, nil
34    return yield
35  ensure
36    $VERBOSE = verbosity
37  end
38  
39end
40
41module ClassMacros
42
43private
44  
45  def shared_attribute( name, *additional_members )
46    attr_reader name
47    
48    additional_writers = additional_members.inject( '' ) do |src, attr|
49      src << "@#{ attr } = value if @#{ attr }\n"
50    end
51    
52    file, line, = caller[ 1 ].split( ':', 3 )
53    class_eval( <<-END, file, line.to_i )
54      def #{ name }= value
55        @#{ name } = value
56        
57        each_delegate do |del|
58          del.#{ name } = value
59        end
60        
61        #{ additional_writers }
62      end
63    END
64  end
65  
66  def abstract( name, message = nil )
67    message ||= "abstract method -- #{ self.class }::#{ name } has not been implemented"
68    file, line, = caller[ 1 ].split( ':', 3 )
69    class_eval( <<-END, file, line.to_i )
70      def #{ name }( * )
71        raise TypeError, #{ message.to_s.inspect }
72      end
73    END
74  end
75  
76  def deprecate( name, extra_message = nil )
77    hidden_name = "deprecated_#{ name }"
78    method_defined?( hidden_name ) and return
79    
80    alias_method( hidden_name, name )
81    private( hidden_name )
82    
83    message = "warning: method #{ self }##{ name } is deprecated"
84    extra_message and message << '; ' << extra_message.to_s
85    
86    class_eval( <<-END )
87      def #{ name }( *args, &block )
88        warn( #{ message.inspect } )
89        #{ hidden_name }( *args, &block )
90      end
91    END
92  end
93  
94  def alias_accessor( alias_name, attr_name )
95    alias_method( alias_name, attr_name )
96    alias_method( :"#{ alias_name }=", :"#{ attr_name }=" )
97  end
98
99end
100
101end
102
103class Integer
104
105  # Returns the lower of self or x.
106  #
107  #   4.at_least(5)  #=> 5
108  #   6.at_least(5)  #=> 6
109  #
110  #   CREDIT Florian Gross
111
112  def at_least( x )
113    ( self >= x ) ? self : x
114  end
115
116  # Returns the greater of self or x.
117  #
118  #   4.at_most(5)  #=> 4
119  #   6.at_most(5)  #=> 5
120  #
121  #   CREDIT Florian Gross
122
123  def at_most( x )
124    ( self <= x ) ? self : x
125  end
126
127  # Returns self if above the given lower bound, or
128  # within the given lower and upper bounds,
129  # otherwise returns the the bound of which the
130  # value falls outside.
131  #
132  #   4.bound(3)    #=> 4
133  #   4.bound(5)    #=> 5
134  #   4.bound(2,7)  #=> 4
135  #   9.bound(2,7)  #=> 7
136  #   1.bound(2,7)  #=> 2
137  #
138  #   CREDIT Trans
139
140  def bound( lower, upper=nil )
141    return lower if self < lower
142    return self unless upper
143    return upper if self > upper
144    return self
145  end
146
147end
148
149
150class Range
151  def covers?( range )
152    range.first >= first or return false
153    if exclude_end?
154      range.exclude_end? ? last >= range.last : last > range.last
155    else
156      range.exclude_end? ? last.succ >= range.last : last >= range.last
157    end
158  end
159  
160  def covered_by?( range )
161    range.covers?( self )
162  end
163  
164  def overlaps?( range )
165    range.include?( first ) or include?( range.first )
166  end
167  
168  def disjoint?( range )
169    not overlaps?( range )
170  end
171  
172end
173