class ANTLR3::Rewrite::RewriteProgram

Public Class Methods

new( stream, name = nil ) click to toggle source
# File lib/antlr3/streams/rewrite.rb, line 165
def initialize( stream, name = nil )
  @stream = stream
  @name = name
  @operations = []
end

Public Instance Methods

clear() click to toggle source
# File lib/antlr3/streams/rewrite.rb, line 296
def clear
  @operations.clear
end
delete( *range_arguments ) click to toggle source
# File lib/antlr3/streams/rewrite.rb, line 195
def delete( *range_arguments )
  range, = cast_range( range_arguments )
  op = Delete.new( @stream, range )
  @operations << op
  return op
end
execute( *range_arguments ) click to toggle source
# File lib/antlr3/streams/rewrite.rb, line 264
def execute( *range_arguments )
  if range_arguments.empty?
    range = 0 ... @stream.length
  else
    range, = cast_range( range_arguments )
  end
  
  output = ''
  
  tokens = @stream.tokens
  
  operations = reduce
  
  cursor = range.first
  while range.include?( cursor )
    if operation = operations.delete( cursor )
      cursor = operation.execute( output )
    else
      token = tokens[ cursor ]
      output << token.text if token
      cursor += 1
    end
  end
  if operation = operations.delete( cursor ) and
     operation.is_a?( InsertBefore )
    # catch edge 'insert-after' operations
    operation.execute( output )
  end
  
  return output
end
insert_after( index, text ) click to toggle source
# File lib/antlr3/streams/rewrite.rb, line 187
def insert_after( index, text )
  index = index.to_i
  index < 0 and index += @stream.length
  op = InsertBefore.new( @stream, index + 1, text )
  @operations << op
  return op
end
insert_before( index, text ) click to toggle source
# File lib/antlr3/streams/rewrite.rb, line 179
def insert_before( index, text )
  index = index.to_i
  index < 0 and index += @stream.length
  op = InsertBefore.new( @stream, index, text )
  @operations << op
  return op
end
reduce() click to toggle source
# File lib/antlr3/streams/rewrite.rb, line 202
    def reduce
      operations = @operations.reverse
      reduced = []
      
      until operations.empty?
        operation = operations.shift
        location = operation.location
        
        case operation
        when Replace
          operations.delete_if do |prior_operation|
            prior_location = prior_operation.location
            
            case prior_operation
            when InsertBefore
              location.include?( prior_location )
            when Replace
              if location.covers?( prior_location )
                true
              elsif location.overlaps?( prior_location )
                conflict!( operation, prior_operation )
              end
            end
          end
        when InsertBefore
          operations.delete_if do |prior_operation|
            prior_location = prior_operation.location
            
            case prior_operation
            when InsertBefore
              if prior_location == location
                operation.text += prior_operation.text
                true
              end
            when Replace
              if location == prior_location.first
                prior_operation.text = operation.text << prior_operation.text.to_s
                operation = nil
                break( false )
              elsif prior_location.include?( location )
                conflict!( operation, prior_operation )
              end
            end
          end
        end
        
        reduced.unshift( operation ) if operation
      end
      
      @operations.replace( reduced )
      
      @operations.inject( {} ) do |map, operation|
        other_operaiton = map[ operation.index ] and
          ANTLR3.bug!( Util.tidy( <<-END ) % [ self.class, operation, other_operaiton ] )
          | %s#reduce! should have left only one operation per index,
          | but %p conflicts with %p
          END
        map[ operation.index ] = operation
        map
      end
    end
replace( *range_arguments ) click to toggle source
# File lib/antlr3/streams/rewrite.rb, line 171
def replace( *range_arguments )
  range, text = cast_range( range_arguments, 1 )
  
  op = Replace.new( @stream, range, text )
  @operations << op
  return op
end
undo( number_of_operations = 1 ) click to toggle source
# File lib/antlr3/streams/rewrite.rb, line 300
def undo( number_of_operations = 1 )
  @operations.pop( number_of_operations )
end

Private Instance Methods

cast_range( args, extra = 0 ) click to toggle source
# File lib/antlr3/streams/rewrite.rb, line 309
def cast_range( args, extra = 0 )
  single, pair = extra + 1, extra + 2
  case check_arguments( args, single, pair )
  when single
    loc = args.shift
    
    if loc.is_a?( Range )
      first, last = loc.first.to_i, loc.last.to_i
      loc.exclude_end? and last -= 1
      return cast_range( args.unshift( first, last ), extra )
    else
      loc = loc.to_i
      return cast_range( args.unshift( loc, loc ), extra )
    end
  when pair
    first, last = args.shift( 2 ).map! { |arg| arg.to_i }
    if first < 0 and last < 0
      first += @stream.length
      last += @stream.length
    else
      last < 0 and last += @stream.length
      first = first.at_least( 0 )
    end
    return( args.unshift( first .. last ) )
  end
end
check_arguments( args, min, max ) click to toggle source
# File lib/antlr3/streams/rewrite.rb, line 336
def check_arguments( args, min, max )
  n = args.length
  if n < min
    raise ArgumentError,
      "wrong number of arguments (#{ args.length } for #{ min })",
      caller
  elsif n > max
    raise ArgumentError,
      "wrong number of arguments (#{ args.length } for #{ max })",
      caller
  else return n
  end
end
conflict!( current, previous ) click to toggle source
# File lib/antlr3/streams/rewrite.rb, line 304
def conflict!( current, previous )
  message = 'operation %p overlaps with previous operation %p' % [ current, previous ]
  raise( RangeError, message, caller )
end