1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#!/usr/bin/ruby 2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver# encoding: utf-8 3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=begin LICENSE 5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver[The "BSD licence"] 7324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverCopyright (c) 2009-2010 Kyle Yetter 8324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverAll rights reserved. 9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 10324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverRedistribution and use in source and binary forms, with or without 11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvermodification, are permitted provided that the following conditions 12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverare met: 13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1. Redistributions of source code must retain the above copyright 15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver notice, this list of conditions and the following disclaimer. 16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 2. Redistributions in binary form must reproduce the above copyright 17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver notice, this list of conditions and the following disclaimer in the 18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver documentation and/or other materials provided with the distribution. 19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 3. The name of the author may not be used to endorse or promote products 20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver derived from this software without specific prior written permission. 21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 22324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverIN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=end 34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvermodule ANTLR3 36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=begin rdoc ANTLR3::TokenRewriteStream 38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 39324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverTokenRewriteStream is a specialized form of CommonTokenStream that provides simple stream editing functionality. By creating <i>rewrite programs</i>, new text output can be created based upon the tokens in the stream. The basic token stream itself is preserved, and text output is rendered on demand using the #to_s method. 40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=end 42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass TokenRewriteStream < CommonTokenStream 44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver unless defined?( RewriteOperation ) 46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver RewriteOperation = Struct.new( :stream, :location, :text ) 47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=begin rdoc ANTLR3::TokenRewriteStream::RewriteOperation 50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 51324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverRewiteOperation objects represent some particular editing command that should 52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverbe executed by a token rewrite stream at some time in future when the stream is 53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverrendering a rewritten stream. 54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 55324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverTo perform token stream rewrites safely and efficiently, the rewrites are 56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverexecuted lazily (that is, only when the rewritten text is explicitly requested). 57324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverRewrite streams implement lazy rewriting by storing the parameters of 58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruveredit-inducing methods like +delete+ and +insert+ as RewriteOperation objects in 59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvera rewrite program list. 60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 61324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverThe three subclasses of RewriteOperation, InsertBefore, Delete, and Replace, 62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverdefine specific implementations of stream edits. 63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=end 65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver class RewriteOperation 67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver extend ClassMacros 68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @operation_name = '' 69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver class << self 71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ## 72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver # the printable name of operations represented by the class -- used for inspection 73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver attr_reader :operation_name 74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ## 77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver # :method: execute( buffer ) 78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver # run the rewrite operation represented by this object and append the output to +buffer+ 79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver abstract :execute 80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ## 82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver # return the name of this operation as set by its class 83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def name 84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver self.class.operation_name 85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ## 88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver # return a compact, readable representation of this operation 89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def inspect 90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return "(%s @ %p : %p)" % [ name, location, text ] 91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=begin rdoc ANTLR3::TokenRewriteStream::InsertBefore 96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 97324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverRepresents rewrite operation: 98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruveradd string <tt>op.text</tt> to the rewrite output immediately before adding the 100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvertext content of the token at index <tt>op.index</tt> 101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=end 103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver class InsertBefore < RewriteOperation 105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @operation_name = 'insert-before'.freeze 106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver alias index location 108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver alias index= location= 109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def execute( buffer ) 111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver buffer << text.to_s 112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver token = stream[ location ] 113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver buffer << token.text.to_s if token 114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return location + 1 115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=begin rdoc ANTLR3::TokenRewriteStream::Replace 119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 120324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverRepresents rewrite operation: 121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruveradd text <tt>op.text</tt> to the rewrite buffer in lieu of the text of tokens 123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverindexed within the range <tt>op.index .. op.last_index</tt> 124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=end 126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver class Replace < RewriteOperation 128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @operation_name = 'replace'.freeze 130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def initialize( stream, location, text ) 132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver super( stream, nil, text ) 133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver self.location = location 134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def location=( val ) 137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver case val 138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver when Range then super( val ) 139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else 140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver val = val.to_i 141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver super( val..val ) 142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def execute( buffer ) 146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver buffer << text.to_s unless text.nil? 147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return( location.end + 1 ) 148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def index 151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver location.first 152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=begin rdoc ANTLR3::TokenRewriteStream::Delete 157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 158324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverRepresents rewrite operation: 159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverskip over the tokens indexed within the range <tt>op.index .. op.last_index</tt> 161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverand do not add any text to the rewrite buffer 162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=end 164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver class Delete < Replace 166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @operation_name = 'delete'.freeze 167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def initialize( stream, location ) 169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver super( stream, location, nil ) 170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver class RewriteProgram 174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def initialize( stream, name = nil ) 175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @stream = stream 176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @name = name 177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @operations = [] 178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def replace( *range_arguments ) 181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver range, text = cast_range( range_arguments, 1 ) 182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver op = Replace.new( @stream, range, text ) 184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @operations << op 185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return op 186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def insert_before( index, text ) 189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver index = index.to_i 190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver index < 0 and index += @stream.length 191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver op = InsertBefore.new( @stream, index, text ) 192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @operations << op 193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return op 194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def insert_after( index, text ) 197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver index = index.to_i 198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver index < 0 and index += @stream.length 199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver op = InsertBefore.new( @stream, index + 1, text ) 200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @operations << op 201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return op 202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def delete( *range_arguments ) 205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver range, = cast_range( range_arguments ) 206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver op = Delete.new( @stream, range ) 207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @operations << op 208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return op 209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def reduce 212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver operations = @operations.reverse 213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver reduced = [] 214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver until operations.empty? 216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver operation = operations.shift 217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver location = operation.location 218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver case operation 220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver when Replace 221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver operations.delete_if do |prior_operation| 222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver prior_location = prior_operation.location 223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver case prior_operation 225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver when InsertBefore 226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver location.include?( prior_location ) 227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver when Replace 228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if location.covers?( prior_location ) 229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver true 230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver elsif location.overlaps?( prior_location ) 231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver conflict!( operation, prior_operation ) 232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver when InsertBefore 236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver operations.delete_if do |prior_operation| 237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver prior_location = prior_operation.location 238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver case prior_operation 240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver when InsertBefore 241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if prior_location == location 242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver operation.text += prior_operation.text 243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver true 244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver when Replace 246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if location == prior_location.first 247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver prior_operation.text = operation.text << prior_operation.text.to_s 248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver operation = nil 249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver break( false ) 250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver elsif prior_location.include?( location ) 251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver conflict!( operation, prior_operation ) 252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver reduced.unshift( operation ) if operation 258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @operations.replace( reduced ) 261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @operations.inject( {} ) do |map, operation| 263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver other_operaiton = map[ operation.index ] and 264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ANTLR3.bug!( Util.tidy( <<-END ) % [ self.class, operation, other_operaiton ] ) 265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver | %s#reduce! should have left only one operation per index, 266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver | but %p conflicts with %p 267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver map[ operation.index ] = operation 269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver map 270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def execute( *range_arguments ) 274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if range_arguments.empty? 275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver range = 0 ... @stream.length 276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else 277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver range, = cast_range( range_arguments ) 278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver output = '' 281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver tokens = @stream.tokens 283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver operations = reduce 285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver cursor = range.first 287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver while range.include?( cursor ) 288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if operation = operations.delete( cursor ) 289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver cursor = operation.execute( output ) 290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else 291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver token = tokens[ cursor ] 292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver output << token.text if token 293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver cursor += 1 294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if operation = operations.delete( cursor ) and 297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver operation.is_a?( InsertBefore ) 298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver # catch edge 'insert-after' operations 299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver operation.execute( output ) 300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return output 303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def clear 306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @operations.clear 307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def undo( number_of_operations = 1 ) 310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @operations.pop( number_of_operations ) 311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def conflict!( current, previous ) 314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver message = 'operation %p overlaps with previous operation %p' % [ current, previous ] 315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver raise( RangeError, message, caller ) 316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def cast_range( args, extra = 0 ) 319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver single, pair = extra + 1, extra + 2 320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver case check_arguments( args, single, pair ) 321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver when single 322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver loc = args.shift 323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if loc.is_a?( Range ) 325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver first, last = loc.first.to_i, loc.last.to_i 326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver loc.exclude_end? and last -= 1 327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return cast_range( args.unshift( first, last ), extra ) 328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else 329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver loc = loc.to_i 330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return cast_range( args.unshift( loc, loc ), extra ) 331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver when pair 333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver first, last = args.shift( 2 ).map! { |arg| arg.to_i } 334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if first < 0 and last < 0 335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver first += @stream.length 336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver last += @stream.length 337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else 338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver last < 0 and last += @stream.length 339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver first = first.at_least( 0 ) 340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return( args.unshift( first .. last ) ) 342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def check_arguments( args, min, max ) 346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver n = args.length 347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if n < min 348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver raise ArgumentError, 349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver "wrong number of arguments (#{ args.length } for #{ min })", 350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver caller 351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver elsif n > max 352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver raise ArgumentError, 353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver "wrong number of arguments (#{ args.length } for #{ max })", 354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver caller 355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else return n 356324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 357324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 358324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 359324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver private :conflict!, :cast_range, :check_arguments 360324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 361324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 362324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver attr_reader :programs 363324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 364324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def initialize( token_source, options = {} ) 365324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver super( token_source, options ) 366324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 367324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @programs = Hash.new do |programs, name| 368324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if name.is_a?( String ) 369324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver programs[ name ] = RewriteProgram.new( self, name ) 370324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else programs[ name.to_s ] 371324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 372324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 373324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 374324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @last_rewrite_token_indexes = {} 375324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 376324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 377324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def rewrite( program_name = 'default', range = nil ) 378324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver program = @programs[ program_name ] 379324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if block_given? 380324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver yield( program ) 381324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver program.execute( range ) 382324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else program 383324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 384324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 385324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 386324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def program( name = 'default' ) 387324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return @programs[ name ] 388324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 389324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 390324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def delete_program( name = 'default' ) 391324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @programs.delete( name ) 392324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 393324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 394324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def original_string( start = 0, finish = size - 1 ) 395324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @position == -1 and fill_buffer 396324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 397324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return( self[ start..finish ].map { |t| t.text }.join( '' ) ) 398324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 399324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 400324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def insert_before( *args ) 401324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @programs[ 'default' ].insert_before( *args ) 402324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 403324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 404324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def insert_after( *args ) 405324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @programs[ 'default' ].insert_after( *args ) 406324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 407324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 408324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def replace( *args ) 409324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @programs[ 'default' ].replace( *args ) 410324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 411324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 412324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def delete( *args ) 413324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @programs[ 'default' ].delete( *args ) 414324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 415324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 416324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def render( *arguments ) 417324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver case arguments.first 418324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver when String, Symbol then name = arguments.shift.to_s 419324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else name = 'default' 420324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 421324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @programs[ name ].execute( *arguments ) 422324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 423324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend 424324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend 425