1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver/* 2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * [The "BSD licence"] 3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Copyright (c) 2005-2008 Terence Parr 4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * All rights reserved. 5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Conversion to C#: 7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc. 8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * All rights reserved. 9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Redistribution and use in source and binary forms, with or without 11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * modification, are permitted provided that the following conditions 12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * are met: 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 Gruver * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * THEORY 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 Gruver * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvernamespace Antlr.Runtime 34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver{ 35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using System.Collections.Generic; 36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using ArgumentException = System.ArgumentException; 38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using Console = System.Console; 39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using Math = System.Math; 40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using DebuggerDisplay = System.Diagnostics.DebuggerDisplayAttribute; 41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using Exception = System.Exception; 42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using StringBuilder = System.Text.StringBuilder; 43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using Type = System.Type; 44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** Useful for dumping out the input stream after doing some 46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * augmentation or other manipulations. 47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * You can insert stuff, replace, and delete chunks. Note that the 49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * operations are done lazily--only if you convert the buffer to a 50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * String. This is very efficient because you are not moving data around 51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * all the time. As the buffer of tokens is converted to strings, the 52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * toString() method(s) check to see if there is an operation at the 53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * current index. If so, the operation is done and then normal String 54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * rendering continues on the buffer. This is like having multiple Turing 55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * machine instruction streams (programs) operating on a single input tape. :) 56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Since the operations are done lazily at toString-time, operations do not 58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * screw up the token index values. That is, an insert operation at token 59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * index i does not change the index values for tokens i+1..n-1. 60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Because operations never actually alter the buffer, you may always get 62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * the original token stream back without undoing anything. Since 63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * the instructions are queued up, you can easily simulate transactions and 64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * roll back any changes if there is an error just by removing instructions. 65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * For example, 66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * CharStream input = new ANTLRFileStream("input"); 68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * TLexer lex = new TLexer(input); 69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * TokenRewriteStream tokens = new TokenRewriteStream(lex); 70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * T parser = new T(tokens); 71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * parser.startRule(); 72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Then in the rules, you can execute 74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Token t,u; 75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * ... 76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * input.insertAfter(t, "text to put after t");} 77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * input.insertAfter(u, "text after u");} 78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * System.out.println(tokens.toString()); 79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Actually, you have to cast the 'input' to a TokenRewriteStream. :( 81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * You can also have multiple "instruction streams" and get multiple 83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * rewrites from a single pass over the input. Just name the instruction 84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * streams and use that name again when printing the buffer. This could be 85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * useful for generating a C file and also its header file--all from the 86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * same buffer: 87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * tokens.insertAfter("pass1", t, "text to put after t");} 89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * tokens.insertAfter("pass2", u, "text after u");} 90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * System.out.println(tokens.toString("pass1")); 91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * System.out.println(tokens.toString("pass2")); 92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * If you don't use named rewrite streams, a "default" stream is used as 94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * the first example shows. 95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver [System.Serializable] 97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver [DebuggerDisplay( "TODO: TokenRewriteStream debugger display" )] 98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public class TokenRewriteStream : CommonTokenStream 99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public const string DEFAULT_PROGRAM_NAME = "default"; 101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public const int PROGRAM_INIT_SIZE = 100; 102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public const int MIN_TOKEN_INDEX = 0; 103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // Define the rewrite operation hierarchy 105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected class RewriteOperation 107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>What index into rewrites List are we?</summary> */ 109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public int instructionIndex; 110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>Token buffer index.</summary> */ 111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public int index; 112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public object text; 113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // outer 114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected TokenRewriteStream stream; 115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected RewriteOperation(TokenRewriteStream stream, int index) 117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.stream = stream; 119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.index = index; 120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected RewriteOperation( TokenRewriteStream stream, int index, object text ) 123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.index = index; 125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.text = text; 126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.stream = stream; 127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Execute the rewrite operation by possibly adding to the buffer. 131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Return the index of the next token to operate on. 132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual int Execute( StringBuilder buf ) 135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return index; 137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public override string ToString() 140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver string opName = this.GetType().Name; 142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver int dindex = opName.IndexOf( '$' ); 143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver opName = opName.Substring( dindex + 1 ); 144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return string.Format("<{0}@{1}:\"{2}\">", opName, stream._tokens[index], text); 145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver private class InsertBeforeOp : RewriteOperation 149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public InsertBeforeOp( TokenRewriteStream stream, int index, object text ) : 151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver base( stream, index, text ) 152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public override int Execute( StringBuilder buf ) 156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver buf.Append( text ); 158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (stream._tokens[index].Type != CharStreamConstants.EndOfFile) 159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver buf.Append(stream._tokens[index].Text); 160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return index + 1; 161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * I'm going to try replacing range from x..y with (y-x)+1 ReplaceOp 166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * instructions. 167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver private class ReplaceOp : RewriteOperation 170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public int lastIndex; 172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public ReplaceOp( TokenRewriteStream stream, int from, int to, object text ) 173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver : base( stream, from, text ) 174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver lastIndex = to; 176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public override int Execute( StringBuilder buf ) 179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( text != null ) 181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver buf.Append( text ); 183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return lastIndex + 1; 185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public override string ToString() 188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (text == null) 190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return string.Format("<DeleteOp@{0}..{1}>", stream._tokens[index], stream._tokens[lastIndex]); 192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return string.Format("<ReplaceOp@{0}..{1}:\"{2}\">", stream._tokens[index], stream._tokens[lastIndex], text); 195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * You may have multiple, named streams of rewrite operations. 200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * I'm calling these things "programs." 201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Maps String (name) -> rewrite (List) 202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected IDictionary<string, IList<RewriteOperation>> programs = null; 205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>Map String (program name) -> Integer index</summary> */ 207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected IDictionary<string, int> lastRewriteTokenIndexes = null; 208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public TokenRewriteStream() 210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Init(); 212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected void Init() 215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver programs = new Dictionary<string, IList<RewriteOperation>>(); 217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver programs[DEFAULT_PROGRAM_NAME] = new List<RewriteOperation>( PROGRAM_INIT_SIZE ); 218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver lastRewriteTokenIndexes = new Dictionary<string, int>(); 219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public TokenRewriteStream( ITokenSource tokenSource ) 222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver : base( tokenSource ) 223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Init(); 225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public TokenRewriteStream( ITokenSource tokenSource, int channel ) 228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver : base( tokenSource, channel ) 229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Init(); 231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Rollback( int instructionIndex ) 234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Rollback( DEFAULT_PROGRAM_NAME, instructionIndex ); 236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Rollback the instruction stream for a program so that 240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * the indicated instruction (via instructionIndex) is no 241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * longer in the stream. UNTESTED! 242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Rollback( string programName, int instructionIndex ) 245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IList<RewriteOperation> @is; 247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( programs.TryGetValue( programName, out @is ) && @is != null ) 248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver List<RewriteOperation> sublist = new List<RewriteOperation>(); 250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for ( int i = MIN_TOKEN_INDEX; i <= instructionIndex; i++ ) 251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver sublist.Add( @is[i] ); 252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver programs[programName] = sublist; 254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void DeleteProgram() 258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver DeleteProgram( DEFAULT_PROGRAM_NAME ); 260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>Reset the program so that no instructions exist</summary> */ 263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void DeleteProgram( string programName ) 264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Rollback( programName, MIN_TOKEN_INDEX ); 266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void InsertAfter( IToken t, object text ) 269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver InsertAfter( DEFAULT_PROGRAM_NAME, t, text ); 271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void InsertAfter( int index, object text ) 274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver InsertAfter( DEFAULT_PROGRAM_NAME, index, text ); 276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void InsertAfter( string programName, IToken t, object text ) 279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver InsertAfter( programName, t.TokenIndex, text ); 281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void InsertAfter( string programName, int index, object text ) 284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // to insert after, just insert before next index (even if past end) 286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver InsertBefore( programName, index + 1, text ); 287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void InsertBefore( IToken t, object text ) 290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver InsertBefore( DEFAULT_PROGRAM_NAME, t, text ); 292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void InsertBefore( int index, object text ) 295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver InsertBefore( DEFAULT_PROGRAM_NAME, index, text ); 297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void InsertBefore( string programName, IToken t, object text ) 300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver InsertBefore( programName, t.TokenIndex, text ); 302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void InsertBefore( string programName, int index, object text ) 305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver RewriteOperation op = new InsertBeforeOp( this, index, text ); 307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IList<RewriteOperation> rewrites = GetProgram( programName ); 308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver op.instructionIndex = rewrites.Count; 309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rewrites.Add( op ); 310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Replace( int index, object text ) 313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Replace( DEFAULT_PROGRAM_NAME, index, index, text ); 315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Replace( int from, int to, object text ) 318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Replace( DEFAULT_PROGRAM_NAME, from, to, text ); 320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Replace( IToken indexT, object text ) 323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Replace( DEFAULT_PROGRAM_NAME, indexT, indexT, text ); 325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Replace( IToken from, IToken to, object text ) 328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Replace( DEFAULT_PROGRAM_NAME, from, to, text ); 330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Replace( string programName, int from, int to, object text ) 333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( from > to || from < 0 || to < 0 || to >= _tokens.Count ) 335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver throw new ArgumentException( "replace: range invalid: " + from + ".." + to + "(size=" + _tokens.Count + ")" ); 337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver RewriteOperation op = new ReplaceOp( this, from, to, text ); 339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IList<RewriteOperation> rewrites = GetProgram( programName ); 340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver op.instructionIndex = rewrites.Count; 341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rewrites.Add( op ); 342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Replace( string programName, IToken from, IToken to, object text ) 345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Replace( programName, 347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver from.TokenIndex, 348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver to.TokenIndex, 349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver text ); 350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Delete( int index ) 353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Delete( DEFAULT_PROGRAM_NAME, index, index ); 355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 356324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 357324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Delete( int from, int to ) 358324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 359324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Delete( DEFAULT_PROGRAM_NAME, from, to ); 360324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 361324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 362324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Delete( IToken indexT ) 363324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 364324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Delete( DEFAULT_PROGRAM_NAME, indexT, indexT ); 365324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 366324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 367324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Delete( IToken from, IToken to ) 368324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 369324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Delete( DEFAULT_PROGRAM_NAME, from, to ); 370324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 371324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 372324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Delete( string programName, int from, int to ) 373324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 374324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Replace( programName, from, to, null ); 375324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 376324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 377324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Delete( string programName, IToken from, IToken to ) 378324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 379324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Replace( programName, from, to, null ); 380324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 381324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 382324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual int GetLastRewriteTokenIndex() 383324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 384324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return GetLastRewriteTokenIndex( DEFAULT_PROGRAM_NAME ); 385324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 386324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 387324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual int GetLastRewriteTokenIndex( string programName ) 388324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 389324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver int value; 390324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( lastRewriteTokenIndexes.TryGetValue( programName, out value ) ) 391324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return value; 392324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 393324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return -1; 394324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 395324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 396324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual void SetLastRewriteTokenIndex( string programName, int i ) 397324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 398324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver lastRewriteTokenIndexes[programName] = i; 399324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 400324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 401324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual IList<RewriteOperation> GetProgram( string name ) 402324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 403324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IList<RewriteOperation> @is; 404324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( !programs.TryGetValue( name, out @is ) || @is == null ) 405324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 406324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @is = InitializeProgram( name ); 407324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 408324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return @is; 409324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 410324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 411324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver private IList<RewriteOperation> InitializeProgram( string name ) 412324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 413324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IList<RewriteOperation> @is = new List<RewriteOperation>( PROGRAM_INIT_SIZE ); 414324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver programs[name] = @is; 415324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return @is; 416324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 417324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 418324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual string ToOriginalString() 419324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 420324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Fill(); 421324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return ToOriginalString( MIN_TOKEN_INDEX, Count - 1 ); 422324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 423324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 424324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual string ToOriginalString( int start, int end ) 425324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 426324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver StringBuilder buf = new StringBuilder(); 427324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for ( int i = start; i >= MIN_TOKEN_INDEX && i <= end && i < _tokens.Count; i++ ) 428324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 429324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (Get(i).Type != CharStreamConstants.EndOfFile) 430324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver buf.Append(Get(i).Text); 431324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 432324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return buf.ToString(); 433324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 434324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 435324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public override string ToString() 436324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 437324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Fill(); 438324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return ToString( MIN_TOKEN_INDEX, Count - 1 ); 439324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 440324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 441324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual string ToString( string programName ) 442324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 443324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Fill(); 444324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return ToString(programName, MIN_TOKEN_INDEX, Count - 1); 445324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 446324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 447324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public override string ToString( int start, int end ) 448324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 449324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return ToString( DEFAULT_PROGRAM_NAME, start, end ); 450324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 451324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 452324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual string ToString( string programName, int start, int end ) 453324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 454324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IList<RewriteOperation> rewrites; 455324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( !programs.TryGetValue( programName, out rewrites ) ) 456324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rewrites = null; 457324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 458324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // ensure start/end are in range 459324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( end > _tokens.Count - 1 ) 460324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end = _tokens.Count - 1; 461324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( start < 0 ) 462324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver start = 0; 463324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 464324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( rewrites == null || rewrites.Count == 0 ) 465324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 466324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return ToOriginalString( start, end ); // no instructions to execute 467324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 468324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver StringBuilder buf = new StringBuilder(); 469324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 470324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // First, optimize instruction stream 471324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IDictionary<int, RewriteOperation> indexToOp = ReduceToSingleOperationPerIndex( rewrites ); 472324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 473324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // Walk buffer, executing instructions and emitting tokens 474324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver int i = start; 475324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver while ( i <= end && i < _tokens.Count ) 476324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 477324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver RewriteOperation op; 478324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver bool exists = indexToOp.TryGetValue( i, out op ); 479324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 480324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( exists ) 481324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 482324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // remove so any left have index size-1 483324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver indexToOp.Remove( i ); 484324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 485324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 486324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( !exists || op == null ) 487324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 488324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IToken t = _tokens[i]; 489324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // no operation at that index, just dump token 490324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (t.Type != CharStreamConstants.EndOfFile) 491324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver buf.Append(t.Text); 492324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver i++; // move to next token 493324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 494324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else 495324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 496324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver i = op.Execute( buf ); // execute operation and skip 497324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 498324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 499324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 500324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // include stuff after end if it's last index in buffer 501324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // So, if they did an insertAfter(lastValidIndex, "foo"), include 502324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // foo if end==lastValidIndex. 503324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( end == _tokens.Count - 1 ) 504324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 505324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // Scan any remaining operations after last token 506324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // should be included (they will be inserts). 507324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver foreach ( RewriteOperation op in indexToOp.Values ) 508324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 509324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( op.index >= _tokens.Count - 1 ) 510324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver buf.Append( op.text ); 511324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 512324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 513324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return buf.ToString(); 514324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 515324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 516324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** We need to combine operations and report invalid operations (like 517324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * overlapping replaces that are not completed nested). Inserts to 518324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * same index need to be combined etc... Here are the cases: 519324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 520324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * I.i.u I.j.v leave alone, nonoverlapping 521324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * I.i.u I.i.v combine: Iivu 522324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 523324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.i-j.u R.x-y.v | i-j in x-y delete first R 524324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.i-j.u R.i-j.v delete first R 525324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.i-j.u R.x-y.v | x-y in i-j ERROR 526324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.i-j.u R.x-y.v | boundaries overlap ERROR 527324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 528324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Delete special case of replace (text==null): 529324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * D.i-j.u D.x-y.v | boundaries overlap combine to max(min)..max(right) 530324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 531324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * I.i.u R.x-y.v | i in (x+1)-y delete I (since insert before 532324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * we're not deleting i) 533324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * I.i.u R.x-y.v | i not in (x+1)-y leave alone, nonoverlapping 534324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.x-y.v I.i.u | i in x-y ERROR 535324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.x-y.v I.x.u R.x-y.uv (combine, delete I) 536324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.x-y.v I.i.u | i not in x-y leave alone, nonoverlapping 537324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 538324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * I.i.u = insert u before op @ index i 539324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * R.x-y.u = replace x-y indexed tokens with u 540324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 541324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * First we need to examine replaces. For any replace op: 542324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 543324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 1. wipe out any insertions before op within that range. 544324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 2. Drop any replace op before that is contained completely within 545324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * that range. 546324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 3. Throw exception upon boundary overlap with any previous replace. 547324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 548324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Then we can deal with inserts: 549324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 550324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 1. for any inserts to same index, combine even if not adjacent. 551324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 2. for any prior replace with same left boundary, combine this 552324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * insert with replace and delete this replace. 553324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 3. throw exception if index in same range as previous replace 554324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 555324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Don't actually delete; make op null in list. Easier to walk list. 556324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Later we can throw as we add to index -> op map. 557324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 558324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Note that I.2 R.2-2 will wipe out I.2 even though, technically, the 559324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * inserted stuff would be before the replace range. But, if you 560324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * add tokens in front of a method body '{' and then delete the method 561324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * body, I think the stuff before the '{' you added should disappear too. 562324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 563324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Return a map from token index to operation. 564324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 565324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual IDictionary<int, RewriteOperation> ReduceToSingleOperationPerIndex( IList<RewriteOperation> rewrites ) 566324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 567324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //System.out.println("rewrites="+rewrites); 568324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 569324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // WALK REPLACES 570324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for ( int i = 0; i < rewrites.Count; i++ ) 571324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 572324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver RewriteOperation op = rewrites[i]; 573324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( op == null ) 574324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver continue; 575324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( !( op is ReplaceOp ) ) 576324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver continue; 577324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ReplaceOp rop = (ReplaceOp)rewrites[i]; 578324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // Wipe prior inserts within range 579324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var inserts = GetKindOfOps( rewrites, typeof( InsertBeforeOp ), i ); 580324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for ( int j = 0; j < inserts.Count; j++ ) 581324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 582324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver InsertBeforeOp iop = (InsertBeforeOp)inserts[j]; 583324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (iop.index == rop.index) 584324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 585324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // E.g., insert before 2, delete 2..2; update replace 586324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // text to include insert before, kill insert 587324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rewrites[iop.instructionIndex] = null; 588324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rop.text = iop.text.ToString() + (rop.text != null ? rop.text.ToString() : string.Empty); 589324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 590324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else if (iop.index > rop.index && iop.index <= rop.lastIndex) 591324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 592324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // delete insert as it's a no-op. 593324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rewrites[iop.instructionIndex] = null; 594324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 595324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 596324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // Drop any prior replaces contained within 597324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var prevReplaces = GetKindOfOps( rewrites, typeof( ReplaceOp ), i ); 598324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for ( int j = 0; j < prevReplaces.Count; j++ ) 599324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 600324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ReplaceOp prevRop = (ReplaceOp)prevReplaces[j]; 601324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( prevRop.index >= rop.index && prevRop.lastIndex <= rop.lastIndex ) 602324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 603324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // delete replace as it's a no-op. 604324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rewrites[prevRop.instructionIndex] = null; 605324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver continue; 606324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 607324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // throw exception unless disjoint or identical 608324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver bool disjoint = 609324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver prevRop.lastIndex < rop.index || prevRop.index > rop.lastIndex; 610324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver bool same = 611324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver prevRop.index == rop.index && prevRop.lastIndex == rop.lastIndex; 612324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // Delete special case of replace (text==null): 613324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // D.i-j.u D.x-y.v | boundaries overlap combine to max(min)..max(right) 614324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (prevRop.text == null && rop.text == null && !disjoint) 615324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 616324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //System.out.println("overlapping deletes: "+prevRop+", "+rop); 617324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rewrites[prevRop.instructionIndex] = null; // kill first delete 618324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rop.index = Math.Min(prevRop.index, rop.index); 619324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rop.lastIndex = Math.Max(prevRop.lastIndex, rop.lastIndex); 620324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Console.WriteLine("new rop " + rop); 621324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 622324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else if ( !disjoint && !same ) 623324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 624324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver throw new ArgumentException( "replace op boundaries of " + rop + 625324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver " overlap with previous " + prevRop ); 626324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 627324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 628324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 629324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 630324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // WALK INSERTS 631324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for ( int i = 0; i < rewrites.Count; i++ ) 632324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 633324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver RewriteOperation op = (RewriteOperation)rewrites[i]; 634324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( op == null ) 635324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver continue; 636324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( !( op is InsertBeforeOp ) ) 637324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver continue; 638324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver InsertBeforeOp iop = (InsertBeforeOp)rewrites[i]; 639324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // combine current insert with prior if any at same index 640324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var prevInserts = GetKindOfOps( rewrites, typeof( InsertBeforeOp ), i ); 641324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for ( int j = 0; j < prevInserts.Count; j++ ) 642324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 643324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver InsertBeforeOp prevIop = (InsertBeforeOp)prevInserts[j]; 644324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( prevIop.index == iop.index ) 645324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { // combine objects 646324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // convert to strings...we're in process of toString'ing 647324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // whole token buffer so no lazy eval issue with any templates 648324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver iop.text = CatOpText( iop.text, prevIop.text ); 649324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // delete redundant prior insert 650324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rewrites[prevIop.instructionIndex] = null; 651324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 652324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 653324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // look for replaces where iop.index is in range; error 654324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var prevReplaces = GetKindOfOps( rewrites, typeof( ReplaceOp ), i ); 655324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for ( int j = 0; j < prevReplaces.Count; j++ ) 656324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 657324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ReplaceOp rop = (ReplaceOp)prevReplaces[j]; 658324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( iop.index == rop.index ) 659324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 660324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rop.text = CatOpText( iop.text, rop.text ); 661324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rewrites[i] = null; // delete current insert 662324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver continue; 663324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 664324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( iop.index >= rop.index && iop.index <= rop.lastIndex ) 665324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 666324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver throw new ArgumentException( "insert op " + iop + 667324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver " within boundaries of previous " + rop ); 668324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 669324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 670324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 671324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // System.out.println("rewrites after="+rewrites); 672324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IDictionary<int, RewriteOperation> m = new Dictionary<int, RewriteOperation>(); 673324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for ( int i = 0; i < rewrites.Count; i++ ) 674324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 675324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver RewriteOperation op = (RewriteOperation)rewrites[i]; 676324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( op == null ) 677324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver continue; // ignore deleted ops 678324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 679324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver RewriteOperation existing; 680324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( m.TryGetValue( op.index, out existing ) && existing != null ) 681324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 682324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver throw new Exception( "should only be one op per index" ); 683324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 684324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver m[op.index] = op; 685324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 686324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //System.out.println("index to op: "+m); 687324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return m; 688324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 689324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 690324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual string CatOpText( object a, object b ) 691324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 692324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return string.Concat( a, b ); 693324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 694324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual IList<RewriteOperation> GetKindOfOps( IList<RewriteOperation> rewrites, Type kind ) 695324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 696324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return GetKindOfOps( rewrites, kind, rewrites.Count ); 697324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 698324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 699324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>Get all operations before an index of a particular kind</summary> */ 700324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual IList<RewriteOperation> GetKindOfOps( IList<RewriteOperation> rewrites, Type kind, int before ) 701324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 702324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IList<RewriteOperation> ops = new List<RewriteOperation>(); 703324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for ( int i = 0; i < before && i < rewrites.Count; i++ ) 704324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 705324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver RewriteOperation op = rewrites[i]; 706324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( op == null ) 707324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver continue; // ignore deleted 708324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( op.GetType() == kind ) 709324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ops.Add( op ); 710324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 711324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return ops; 712324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 713324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 714324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual string ToDebugString() 715324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 716324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return ToDebugString( MIN_TOKEN_INDEX, Count - 1 ); 717324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 718324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 719324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual string ToDebugString( int start, int end ) 720324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 721324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver StringBuilder buf = new StringBuilder(); 722324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for ( int i = start; i >= MIN_TOKEN_INDEX && i <= end && i < _tokens.Count; i++ ) 723324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 724324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver buf.Append( Get( i ) ); 725324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 726324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return buf.ToString(); 727324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 728324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 729324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver} 730