1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver/* 2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver [The "BSD licence"] 3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Copyright (c) 2005-2006 Terence Parr 4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver All rights reserved. 5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Redistribution and use in source and binary forms, with or without 7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver modification, are permitted provided that the following conditions 8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver are met: 9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1. Redistributions of source code must retain the above copyright 10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver notice, this list of conditions and the following disclaimer. 11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 2. Redistributions in binary form must reproduce the above copyright 12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver notice, this list of conditions and the following disclaimer in the 13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver documentation and/or other materials provided with the distribution. 14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 3. The name of the author may not be used to endorse or promote products 15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver derived from this software without specific prior written permission. 16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver*/ 28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverpackage org.antlr.runtime { 29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver import flash.utils.getQualifiedClassName; 30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** Useful for dumping out the input stream after doing some 33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * augmentation or other manipulations. 34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * You can insert stuff, replace, and delete chunks. Note that the 36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * operations are done lazily--only if you convert the buffer to a 37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * String. This is very efficient because you are not moving data around 38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * all the time. As the buffer of tokens is converted to strings, the 39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * toString() method(s) check to see if there is an operation at the 40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * current index. If so, the operation is done and then normal String 41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * rendering continues on the buffer. This is like having multiple Turing 42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * machine instruction streams (programs) operating on a single input tape. :) 43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Since the operations are done lazily at toString-time, operations do not 45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * screw up the token index values. That is, an insert operation at token 46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * index i does not change the index values for tokens i+1..n-1. 47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Because operations never actually alter the buffer, you may always get 49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * the original token stream back without undoing anything. Since 50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * the instructions are queued up, you can easily simulate transactions and 51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * roll back any changes if there is an error just by removing instructions. 52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * For example, 53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * var input:CharStream = new ANTLRFileStream("input"); 55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * var lex:TLexer = new TLexer(input); 56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * var tokens:TokenRewriteStream = new TokenRewriteStream(lex); 57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * var parser:T = new T(tokens); 58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * parser.startRule(); 59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Then in the rules, you can execute 61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * var t:Token t, u:Token; 62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * ... 63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * input.insertAfter(t, "text to put after t");} 64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * input.insertAfter(u, "text after u");} 65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * trace(tokens.toString()); 66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Actually, you have to cast the 'input' to a TokenRewriteStream. :( 68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * You can also have multiple "instruction streams" and get multiple 70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * rewrites from a single pass over the input. Just name the instruction 71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * streams and use that name again when printing the buffer. This could be 72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * useful for generating a C file and also its header file--all from the 73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * same buffer: 74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * tokens.insertAfter("pass1", t, "text to put after t");} 76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * tokens.insertAfter("pass2", u, "text after u");} 77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * trace(tokens.toString("pass1")); 78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * trace(tokens.toString("pass2")); 79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * If you don't use named rewrite streams, a "default" stream is used as 81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * the first example shows. 82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public class TokenRewriteStream extends CommonTokenStream { 84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public static const DEFAULT_PROGRAM_NAME:String = "default"; 85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public static const MIN_TOKEN_INDEX:int = 0; 86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** You may have multiple, named streams of rewrite operations. 88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * I'm calling these things "programs." 89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Maps String (name) -> rewrite (List) 90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected var programs:Object = new Object(); 92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** Map String (program name) -> Integer index */ 94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected var lastRewriteTokenIndexes:Object = new Object(); 95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function TokenRewriteStream(tokenSource:TokenSource = null, channel:int = TokenConstants.DEFAULT_CHANNEL) { 97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver super(tokenSource, channel); 98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver programs[DEFAULT_PROGRAM_NAME] = new Array(); 99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** Rollback the instruction stream for a program so that 102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * the indicated instruction (via instructionIndex) is no 103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * longer in the stream. UNTESTED! 104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function rollback(instructionIndex:int, programName:String = DEFAULT_PROGRAM_NAME):void { 106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var isn:Array = programs[programName] as Array; 107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( isn != null ) { 108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver programs[programName] = isn.slice(MIN_TOKEN_INDEX,instructionIndex); 109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** Reset the program so that no instructions exist */ 113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function deleteProgram(programName:String = DEFAULT_PROGRAM_NAME):void { 114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rollback(MIN_TOKEN_INDEX, programName); 115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function insertAfterToken(t:Token, text:Object, programName:String = DEFAULT_PROGRAM_NAME):void { 118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver insertAfter(t.tokenIndex, text, programName); 119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function insertAfter(index:int, text:Object, programName:String = DEFAULT_PROGRAM_NAME):void { 122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // to insert after, just insert before next index (even if past end) 123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver insertBefore(index+1, text, programName); 124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function insertBeforeToken(t:Token, text:Object, programName:String = DEFAULT_PROGRAM_NAME):void { 127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver insertBefore(t.tokenIndex, text, programName); 128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function insertBefore(index:int, text:Object, programName:String = DEFAULT_PROGRAM_NAME):void { 131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var op:RewriteOperation = new InsertBeforeOp(index,text); 132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var rewrites:Array = getProgram(programName); 133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver op.instructionIndex = rewrites.length; 134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rewrites.push(op); 135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function replace(index:int, text:Object, programName:String = DEFAULT_PROGRAM_NAME):void { 138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver replaceRange(index, index, text, programName); 139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function replaceRange(fromIndex:int, toIndex:int, text:Object, programName:String = DEFAULT_PROGRAM_NAME):void { 142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( fromIndex > toIndex || fromIndex<0 || toIndex<0 || toIndex >= tokens.length ) { 143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver throw new Error("replace: range invalid: "+fromIndex+".."+toIndex+"(size="+tokens.length+")"); 144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var op:RewriteOperation = new ReplaceOp(fromIndex, toIndex, text); 146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var rewrites:Array = getProgram(programName); 147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver op.instructionIndex = rewrites.length; 148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rewrites.push(op); 149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function replaceToken(indexT:Token, text:Object, programName:String = DEFAULT_PROGRAM_NAME):void { 152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver replaceTokenRange(indexT, indexT, text, programName); 153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function replaceTokenRange(fromToken:Token, toToken:Token, text:Object, programName:String = DEFAULT_PROGRAM_NAME):void { 156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver replaceRange(fromToken.tokenIndex, toToken.tokenIndex, text, programName); 157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function remove(index:int, programName:String = DEFAULT_PROGRAM_NAME):void { 160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver removeRange(index, index, programName); 161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function removeRange(fromIndex:int, toIndex:int, programName:String = DEFAULT_PROGRAM_NAME):void { 164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver replaceRange(fromIndex, toIndex, null, programName); 165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function removeToken(token:Token, programName:String = DEFAULT_PROGRAM_NAME):void { 168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver removeTokenRange(token, token, programName); 169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function removeTokenRange(fromToken:Token, toToken:Token, programName:String = DEFAULT_PROGRAM_NAME):void { 172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver replaceTokenRange(fromToken, toToken, null, programName); 173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function getLastRewriteTokenIndex(programName:String = DEFAULT_PROGRAM_NAME):int { 176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var i:* = lastRewriteTokenIndexes[programName]; 177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( i == undefined ) { 178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return -1; 179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return i as int; 181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected function setLastRewriteTokenIndex(programName:String, i:int):void { 184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver lastRewriteTokenIndexes[programName] = i; 185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected function getProgram(name:String):Array { 188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var isn:Array = programs[name] as Array; 189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( isn==null ) { 190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver isn = initializeProgram(name); 191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return isn; 193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver private function initializeProgram(name:String):Array { 196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var isn:Array = new Array(); 197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver programs[name] = isn; 198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return isn; 199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function toOriginalString():String { 202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return toOriginalStringWithRange(MIN_TOKEN_INDEX, size-1); 203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function toOriginalStringWithRange(start:int, end:int):String { 206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var buf:String = new String(); 207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for (var i:int=start; i>=MIN_TOKEN_INDEX && i<=end && i<tokens.length; i++) { 208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver buf += getToken(i).text; 209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return buf.toString(); 211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public override function toString():String { 214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return toStringWithRange(MIN_TOKEN_INDEX, size-1); 215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public override function toStringWithRange(start:int, end:int):String { 218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return toStringWithRangeAndProgram(start, end, DEFAULT_PROGRAM_NAME); 219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function toStringWithRangeAndProgram(start:int, end:int, programName:String):String { 222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var rewrites:Array = programs[programName] as Array; 223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // ensure start/end are in range 225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( end > tokens.length-1 ) end = tokens.length-1; 226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( start < 0 ) start = 0; 227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( rewrites==null || rewrites.length==0 ) { 229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return toOriginalStringWithRange(start,end); // no instructions to execute 230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var state:RewriteState = new RewriteState(); 232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.tokens = tokens; 233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // First, optimize instruction stream 235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var indexToOp:Array = reduceToSingleOperationPerIndex(rewrites); 236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // Walk buffer, executing instructions and emitting tokens 238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var i:int = start; 239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver while ( i <= end && i < tokens.length ) { 240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var op:RewriteOperation = RewriteOperation(indexToOp[i]); 241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver indexToOp[i] = undefined; // remove so any left have index size-1 242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var t:Token = Token(tokens[i]); 243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( op==null ) { 244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // no operation at that index, just dump token 245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.buf += t.text; 246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver i++; // move to next token 247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else { 249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver i = op.execute(state); // execute operation and skip 250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // include stuff after end if it's last index in buffer 254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // So, if they did an insertAfter(lastValidIndex, "foo"), include 255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // foo if end==lastValidIndex. 256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( end==tokens.length-1 ) { 257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // Scan any remaining operations after last token 258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // should be included (they will be inserts). 259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for each (op in indexToOp) { 260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (op == null) continue; 261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( op.index >= tokens.length-1 ) state.buf += op.text; 262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return state.buf; 266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** We need to combine operations and report invalid operations (like 269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * overlapping replaces that are not completed nested). Inserts to 270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * same index need to be combined etc... Here are the cases: 271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * I.i.u I.j.v leave alone, nonoverlapping 273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * I.i.u I.i.v combine: Iivu 274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.i-j.u R.x-y.v | i-j in x-y delete first R 276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.i-j.u R.i-j.v delete first R 277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.i-j.u R.x-y.v | x-y in i-j ERROR 278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.i-j.u R.x-y.v | boundaries overlap ERROR 279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * I.i.u R.x-y.v | i in x-y delete I 281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * I.i.u R.x-y.v | i not in x-y leave alone, nonoverlapping 282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.x-y.v I.i.u | i in x-y ERROR 283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.x-y.v I.x.u R.x-y.uv (combine, delete I) 284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.x-y.v I.i.u | i not in x-y leave alone, nonoverlapping 285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * I.i.u = insert u before op @ index i 287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.x-y.u = replace x-y indexed tokens with u 288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * First we need to examine replaces. For any replace op: 290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 1. wipe out any insertions before op within that range. 292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 2. Drop any replace op before that is contained completely within 293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * that range. 294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 3. Throw exception upon boundary overlap with any previous replace. 295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Then we can deal with inserts: 297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 1. for any inserts to same index, combine even if not adjacent. 299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 2. for any prior replace with same left boundary, combine this 300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * insert with replace and delete this replace. 301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 3. throw exception if index in same range as previous replace 302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Don't actually delete; make op null in list. Easier to walk list. 304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Later we can throw as we add to index -> op map. 305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Note that I.2 R.2-2 will wipe out I.2 even though, technically, the 307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * inserted stuff would be before the replace range. But, if you 308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * add tokens in front of a method body '{' and then delete the method 309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * body, I think the stuff before the '{' you added should disappear too. 310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Return a map from token index to operation. 312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected function reduceToSingleOperationPerIndex(rewrites:Array):Array { 314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //System.out.println("rewrites="+rewrites); 315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // WALK REPLACES 317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for (var i:int = 0; i < rewrites.length; i++) { 318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var op:RewriteOperation = RewriteOperation(rewrites[i]); 319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( op==null ) continue; 320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( !(op is ReplaceOp) ) continue; 321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var rop:ReplaceOp = ReplaceOp(rewrites[i]); 322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // Wipe prior inserts within range 323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var inserts:Array = getKindOfOps(rewrites, InsertBeforeOp, i); 324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for (var j:int = 0; j < inserts.length; j++) { 325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var iop:InsertBeforeOp = InsertBeforeOp(inserts[j]); 326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( iop.index >= rop.index && iop.index <= rop.lastIndex ) { 327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rewrites[iop.instructionIndex] = null; // delete insert as it's a no-op. 328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // Drop any prior replaces contained within 331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var prevReplaces:Array = getKindOfOps(rewrites, ReplaceOp, i); 332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for (j = 0; j < prevReplaces.length; j++) { 333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var prevRop:ReplaceOp = ReplaceOp(prevReplaces[j]); 334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( prevRop.index>=rop.index && prevRop.lastIndex <= rop.lastIndex ) { 335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rewrites[prevRop.instructionIndex] = null; // delete replace as it's a no-op. 336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver continue; 337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // throw exception unless disjoint or identical 339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var disjoint:Boolean = 340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver prevRop.lastIndex<rop.index || prevRop.index > rop.lastIndex; 341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var same:Boolean = 342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver prevRop.index==rop.index && prevRop.lastIndex==rop.lastIndex; 343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( !disjoint && !same ) { 344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver throw new Error("replace op boundaries of "+rop+ 345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver " overlap with previous "+prevRop); 346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // WALK INSERTS 351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for (i = 0; i < rewrites.length; i++) { 352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver op = RewriteOperation(rewrites[i]); 353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( op==null ) continue; 354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( !(op is InsertBeforeOp) ) continue; 355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver iop = InsertBeforeOp(rewrites[i]); 356324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // combine current insert with prior if any at same index 357324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var prevInserts:Array = getKindOfOps(rewrites, InsertBeforeOp, i); 358324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for (j = 0; j < prevInserts.length; j++) { 359324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var prevIop:InsertBeforeOp = InsertBeforeOp(prevInserts[j]); 360324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( prevIop.index == iop.index ) { // combine objects 361324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // convert to strings...we're in process of toString'ing 362324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // whole token buffer so no lazy eval issue with any templates 363324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver iop.text = catOpText(iop.text,prevIop.text); 364324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rewrites[prevIop.instructionIndex] = null; // delete redundant prior insert 365324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 366324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 367324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // look for replaces where iop.index is in range; error 368324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver prevReplaces = getKindOfOps(rewrites, ReplaceOp, i); 369324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for (j = 0; j < prevReplaces.length; j++) { 370324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rop = ReplaceOp(prevReplaces[j]); 371324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( iop.index == rop.index ) { 372324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rop.text = catOpText(iop.text,rop.text); 373324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rewrites[i] = null; // delete current insert 374324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver continue; 375324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 376324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( iop.index >= rop.index && iop.index <= rop.lastIndex ) { 377324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver throw new Error("insert op "+iop+ 378324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver " within boundaries of previous "+rop); 379324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 380324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 381324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 382324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // System.out.println("rewrites after="+rewrites); 383324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var m:Array = new Array(); 384324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for (i = 0; i < rewrites.length; i++) { 385324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver op = RewriteOperation(rewrites[i]); 386324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( op==null ) continue; // ignore deleted ops 387324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( m[op.index] != undefined ) { 388324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver throw new Error("should only be one op per index"); 389324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 390324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver m[op.index] = op; 391324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 392324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //System.out.println("index to op: "+m); 393324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return m; 394324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 395324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 396324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected function catOpText(a:Object, b:Object):String { 397324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var x:String = ""; 398324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var y:String = ""; 399324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( a!=null ) x = a.toString(); 400324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( b!=null ) y = b.toString(); 401324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return x+y; 402324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 403324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 404324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** Get all operations before an index of a particular kind */ 405324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected function getKindOfOps(rewrites:Array, kind:Class, before:int = -1):Array { 406324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (before == -1) { 407324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver before = rewrites.length; 408324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 409324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var ops:Array = new Array(); 410324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for (var i:int=0; i<before && i<rewrites.length; i++) { 411324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var op:RewriteOperation = RewriteOperation(rewrites[i]); 412324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( op==null ) continue; // ignore deleted 413324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( getQualifiedClassName(op) == getQualifiedClassName(kind) ) ops.push(op); 414324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 415324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return ops; 416324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 417324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 418324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 419324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function toDebugString():String { 420324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return toDebugStringWithRange(MIN_TOKEN_INDEX, size-1); 421324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 422324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 423324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function toDebugStringWithRange(start:int, end:int):String { 424324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var buf:String = new String(); 425324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for (var i:int=start; i>=MIN_TOKEN_INDEX && i<=end && i<tokens.length; i++) { 426324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver buf += getToken(i); 427324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 428324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return buf; 429324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 430324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 431324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 432324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 433324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver} 434324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver import org.antlr.runtime.Token; 435324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 436324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 437324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// Define the rewrite operation hierarchy 438324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 439324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass RewriteState { 440324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public var buf:String = new String(); 441324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public var tokens:Array; 442324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver} 443324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 444324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass RewriteOperation { 445324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** What index into rewrites List are we? */ 446324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver internal var instructionIndex:int; 447324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** Token buffer index. */ 448324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public var index:int; 449324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver internal var text:Object; 450324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function RewriteOperation(index:int, text:Object) { 451324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.index = index; 452324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.text = text; 453324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 454324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** Execute the rewrite operation by possibly adding to the buffer. 455324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Return the index of the next token to operate on. 456324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 457324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function execute(state:RewriteState):int { 458324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return index; 459324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 460324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver} 461324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 462324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass InsertBeforeOp extends RewriteOperation { 463324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function InsertBeforeOp(index:int, text:Object) { 464324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver super(index,text); 465324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 466324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 467324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public override function execute(state:RewriteState):int { 468324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.buf += text; 469324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.buf += Token(state.tokens[index]).text; 470324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return index + 1; 471324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 472324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 473324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function toString():String { 474324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return "<InsertBeforeOp@" + index + ":\"" + text + "\">"; 475324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 476324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver} 477324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 478324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver/** I'm going to try replacing range from x..y with (y-x)+1 ReplaceOp 479324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * instructions. 480324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 481324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass ReplaceOp extends RewriteOperation { 482324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public var lastIndex:int; 483324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 484324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function ReplaceOp(fromIndex:int, toIndex:int, text:Object) { 485324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver super(fromIndex, text); 486324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver lastIndex = toIndex; 487324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 488324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 489324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public override function execute(state:RewriteState):int { 490324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( text!=null ) { 491324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.buf += text; 492324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 493324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return lastIndex+1; 494324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 495324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 496324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function toString():String { 497324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return "<ReplaceOp@" + index + ".." + lastIndex + ":\"" + text + "\">"; 498324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 499324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver} 500324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 501324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass DeleteOp extends ReplaceOp { 502324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public function DeleteOp(fromIndex:int, toIndex:int) { 503324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver super(fromIndex, toIndex, null); 504324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 505324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 506324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public override function toString():String { 507324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return "<DeleteOp@" + index + ".." + lastIndex + ">"; 508324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 509324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver} 510