00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 package org.antlr.runtime;
00029
00030 import java.util.*;
00031
00083 public class TokenRewriteStream extends CommonTokenStream {
00084 public static final String DEFAULT_PROGRAM_NAME = "default";
00085 public static final int PROGRAM_INIT_SIZE = 100;
00086 public static final int MIN_TOKEN_INDEX = 0;
00087
00088
00089
00090 class RewriteOperation {
00092 protected int instructionIndex;
00094 protected int index;
00095 protected Object text;
00096 protected RewriteOperation(int index, Object text) {
00097 this.index = index;
00098 this.text = text;
00099 }
00103 public int execute(StringBuffer buf) {
00104 return index;
00105 }
00106 public String toString() {
00107 String opName = getClass().getName();
00108 int $index = opName.indexOf('$');
00109 opName = opName.substring($index+1, opName.length());
00110 return "<"+opName+"@"+index+":\""+text+"\">";
00111 }
00112 }
00113
00114 class InsertBeforeOp extends RewriteOperation {
00115 public InsertBeforeOp(int index, Object text) {
00116 super(index,text);
00117 }
00118 public int execute(StringBuffer buf) {
00119 buf.append(text);
00120 buf.append(((Token)tokens.get(index)).getText());
00121 return index+1;
00122 }
00123 }
00124
00128 class ReplaceOp extends RewriteOperation {
00129 protected int lastIndex;
00130 public ReplaceOp(int from, int to, Object text) {
00131 super(from,text);
00132 lastIndex = to;
00133 }
00134 public int execute(StringBuffer buf) {
00135 if ( text!=null ) {
00136 buf.append(text);
00137 }
00138 return lastIndex+1;
00139 }
00140 public String toString() {
00141 return "<ReplaceOp@"+index+".."+lastIndex+":\""+text+"\">";
00142 }
00143 }
00144
00145 class DeleteOp extends ReplaceOp {
00146 public DeleteOp(int from, int to) {
00147 super(from, to, null);
00148 }
00149 public String toString() {
00150 return "<DeleteOp@"+index+".."+lastIndex+">";
00151 }
00152 }
00153
00158 protected Map programs = null;
00159
00161 protected Map lastRewriteTokenIndexes = null;
00162
00163 public TokenRewriteStream() {
00164 init();
00165 }
00166
00167 protected void init() {
00168 programs = new HashMap();
00169 programs.put(DEFAULT_PROGRAM_NAME, new ArrayList(PROGRAM_INIT_SIZE));
00170 lastRewriteTokenIndexes = new HashMap();
00171 }
00172
00173 public TokenRewriteStream(TokenSource tokenSource) {
00174 super(tokenSource);
00175 init();
00176 }
00177
00178 public TokenRewriteStream(TokenSource tokenSource, int channel) {
00179 super(tokenSource, channel);
00180 init();
00181 }
00182
00183 public void rollback(int instructionIndex) {
00184 rollback(DEFAULT_PROGRAM_NAME, instructionIndex);
00185 }
00186
00191 public void rollback(String programName, int instructionIndex) {
00192 List is = (List)programs.get(programName);
00193 if ( is!=null ) {
00194 programs.put(programName, is.subList(MIN_TOKEN_INDEX,instructionIndex));
00195 }
00196 }
00197
00198 public void deleteProgram() {
00199 deleteProgram(DEFAULT_PROGRAM_NAME);
00200 }
00201
00203 public void deleteProgram(String programName) {
00204 rollback(programName, MIN_TOKEN_INDEX);
00205 }
00206
00207 public void insertAfter(Token t, Object text) {
00208 insertAfter(DEFAULT_PROGRAM_NAME, t, text);
00209 }
00210
00211 public void insertAfter(int index, Object text) {
00212 insertAfter(DEFAULT_PROGRAM_NAME, index, text);
00213 }
00214
00215 public void insertAfter(String programName, Token t, Object text) {
00216 insertAfter(programName,t.getTokenIndex(), text);
00217 }
00218
00219 public void insertAfter(String programName, int index, Object text) {
00220
00221 insertBefore(programName,index+1, text);
00222
00223 }
00224
00225 public void insertBefore(Token t, Object text) {
00226 insertBefore(DEFAULT_PROGRAM_NAME, t, text);
00227 }
00228
00229 public void insertBefore(int index, Object text) {
00230 insertBefore(DEFAULT_PROGRAM_NAME, index, text);
00231 }
00232
00233 public void insertBefore(String programName, Token t, Object text) {
00234 insertBefore(programName, t.getTokenIndex(), text);
00235 }
00236
00237 public void insertBefore(String programName, int index, Object text) {
00238
00239 RewriteOperation op = new InsertBeforeOp(index,text);
00240 List rewrites = getProgram(programName);
00241 op.instructionIndex = rewrites.size();
00242 rewrites.add(op);
00243 }
00244
00245 public void replace(int index, Object text) {
00246 replace(DEFAULT_PROGRAM_NAME, index, index, text);
00247 }
00248
00249 public void replace(int from, int to, Object text) {
00250 replace(DEFAULT_PROGRAM_NAME, from, to, text);
00251 }
00252
00253 public void replace(Token indexT, Object text) {
00254 replace(DEFAULT_PROGRAM_NAME, indexT, indexT, text);
00255 }
00256
00257 public void replace(Token from, Token to, Object text) {
00258 replace(DEFAULT_PROGRAM_NAME, from, to, text);
00259 }
00260
00261 public void replace(String programName, int from, int to, Object text) {
00262 if ( from > to || from<0 || to<0 || to >= tokens.size() ) {
00263 throw new IllegalArgumentException("replace: range invalid: "+from+".."+to+"(size="+tokens.size()+")");
00264 }
00265 RewriteOperation op = new ReplaceOp(from, to, text);
00266 List rewrites = getProgram(programName);
00267 op.instructionIndex = rewrites.size();
00268 rewrites.add(op);
00269 }
00270
00271 public void replace(String programName, Token from, Token to, Object text) {
00272 replace(programName,
00273 from.getTokenIndex(),
00274 to.getTokenIndex(),
00275 text);
00276 }
00277
00278 public void delete(int index) {
00279 delete(DEFAULT_PROGRAM_NAME, index, index);
00280 }
00281
00282 public void delete(int from, int to) {
00283 delete(DEFAULT_PROGRAM_NAME, from, to);
00284 }
00285
00286 public void delete(Token indexT) {
00287 delete(DEFAULT_PROGRAM_NAME, indexT, indexT);
00288 }
00289
00290 public void delete(Token from, Token to) {
00291 delete(DEFAULT_PROGRAM_NAME, from, to);
00292 }
00293
00294 public void delete(String programName, int from, int to) {
00295 replace(programName,from,to,null);
00296 }
00297
00298 public void delete(String programName, Token from, Token to) {
00299 replace(programName,from,to,null);
00300 }
00301
00302 public int getLastRewriteTokenIndex() {
00303 return getLastRewriteTokenIndex(DEFAULT_PROGRAM_NAME);
00304 }
00305
00306 protected int getLastRewriteTokenIndex(String programName) {
00307 Integer I = (Integer)lastRewriteTokenIndexes.get(programName);
00308 if ( I==null ) {
00309 return -1;
00310 }
00311 return I.intValue();
00312 }
00313
00314 protected void setLastRewriteTokenIndex(String programName, int i) {
00315 lastRewriteTokenIndexes.put(programName, new Integer(i));
00316 }
00317
00318 protected List getProgram(String name) {
00319 List is = (List)programs.get(name);
00320 if ( is==null ) {
00321 is = initializeProgram(name);
00322 }
00323 return is;
00324 }
00325
00326 private List initializeProgram(String name) {
00327 List is = new ArrayList(PROGRAM_INIT_SIZE);
00328 programs.put(name, is);
00329 return is;
00330 }
00331
00332 public String toOriginalString() {
00333 return toOriginalString(MIN_TOKEN_INDEX, size()-1);
00334 }
00335
00336 public String toOriginalString(int start, int end) {
00337 StringBuffer buf = new StringBuffer();
00338 for (int i=start; i>=MIN_TOKEN_INDEX && i<=end && i<tokens.size(); i++) {
00339 buf.append(get(i).getText());
00340 }
00341 return buf.toString();
00342 }
00343
00344 public String toString() {
00345 return toString(MIN_TOKEN_INDEX, size()-1);
00346 }
00347
00348 public String toString(String programName) {
00349 return toString(programName, MIN_TOKEN_INDEX, size()-1);
00350 }
00351
00352 public String toString(int start, int end) {
00353 return toString(DEFAULT_PROGRAM_NAME, start, end);
00354 }
00355
00356 public String toString(String programName, int start, int end) {
00357 List rewrites = (List)programs.get(programName);
00358
00359
00360 if ( end>tokens.size()-1 ) end = tokens.size()-1;
00361 if ( start<0 ) start = 0;
00362
00363 if ( rewrites==null || rewrites.size()==0 ) {
00364 return toOriginalString(start,end);
00365 }
00366 StringBuffer buf = new StringBuffer();
00367
00368
00369 Map indexToOp = reduceToSingleOperationPerIndex(rewrites);
00370
00371
00372 int i = start;
00373 while ( i <= end && i < tokens.size() ) {
00374 RewriteOperation op = (RewriteOperation)indexToOp.get(new Integer(i));
00375 indexToOp.remove(new Integer(i));
00376 Token t = (Token) tokens.get(i);
00377 if ( op==null ) {
00378
00379 buf.append(t.getText());
00380 i++;
00381 }
00382 else {
00383 i = op.execute(buf);
00384 }
00385 }
00386
00387
00388
00389
00390 if ( end==tokens.size()-1 ) {
00391
00392
00393 Iterator it = indexToOp.values().iterator();
00394 while (it.hasNext()) {
00395 RewriteOperation op = (RewriteOperation)it.next();
00396 if ( op.index >= tokens.size()-1 ) buf.append(op.text);
00397 }
00398 }
00399 return buf.toString();
00400 }
00401
00447 protected Map reduceToSingleOperationPerIndex(List rewrites) {
00448
00449
00450
00451 for (int i = 0; i < rewrites.size(); i++) {
00452 RewriteOperation op = (RewriteOperation)rewrites.get(i);
00453 if ( op==null ) continue;
00454 if ( !(op instanceof ReplaceOp) ) continue;
00455 ReplaceOp rop = (ReplaceOp)rewrites.get(i);
00456
00457 List inserts = getKindOfOps(rewrites, InsertBeforeOp.class, i);
00458 for (int j = 0; j < inserts.size(); j++) {
00459 InsertBeforeOp iop = (InsertBeforeOp) inserts.get(j);
00460 if ( iop.index >= rop.index && iop.index <= rop.lastIndex ) {
00461
00462 rewrites.set(iop.instructionIndex, null);
00463 }
00464 }
00465
00466 List prevReplaces = getKindOfOps(rewrites, ReplaceOp.class, i);
00467 for (int j = 0; j < prevReplaces.size(); j++) {
00468 ReplaceOp prevRop = (ReplaceOp) prevReplaces.get(j);
00469 if ( prevRop.index>=rop.index && prevRop.lastIndex <= rop.lastIndex ) {
00470
00471 rewrites.set(prevRop.instructionIndex, null);
00472 continue;
00473 }
00474
00475 boolean disjoint =
00476 prevRop.lastIndex<rop.index || prevRop.index > rop.lastIndex;
00477 boolean same =
00478 prevRop.index==rop.index && prevRop.lastIndex==rop.lastIndex;
00479 if ( !disjoint && !same ) {
00480 throw new IllegalArgumentException("replace op boundaries of "+rop+
00481 " overlap with previous "+prevRop);
00482 }
00483 }
00484 }
00485
00486
00487 for (int i = 0; i < rewrites.size(); i++) {
00488 RewriteOperation op = (RewriteOperation)rewrites.get(i);
00489 if ( op==null ) continue;
00490 if ( !(op instanceof InsertBeforeOp) ) continue;
00491 InsertBeforeOp iop = (InsertBeforeOp)rewrites.get(i);
00492
00493 List prevInserts = getKindOfOps(rewrites, InsertBeforeOp.class, i);
00494 for (int j = 0; j < prevInserts.size(); j++) {
00495 InsertBeforeOp prevIop = (InsertBeforeOp) prevInserts.get(j);
00496 if ( prevIop.index == iop.index ) {
00497
00498
00499 iop.text = catOpText(iop.text,prevIop.text);
00500
00501 rewrites.set(prevIop.instructionIndex, null);
00502 }
00503 }
00504
00505 List prevReplaces = getKindOfOps(rewrites, ReplaceOp.class, i);
00506 for (int j = 0; j < prevReplaces.size(); j++) {
00507 ReplaceOp rop = (ReplaceOp) prevReplaces.get(j);
00508 if ( iop.index == rop.index ) {
00509 rop.text = catOpText(iop.text,rop.text);
00510 rewrites.set(i, null);
00511 continue;
00512 }
00513 if ( iop.index >= rop.index && iop.index <= rop.lastIndex ) {
00514 throw new IllegalArgumentException("insert op "+iop+
00515 " within boundaries of previous "+rop);
00516 }
00517 }
00518 }
00519
00520 Map m = new HashMap();
00521 for (int i = 0; i < rewrites.size(); i++) {
00522 RewriteOperation op = (RewriteOperation)rewrites.get(i);
00523 if ( op==null ) continue;
00524 if ( m.get(new Integer(op.index))!=null ) {
00525 throw new Error("should only be one op per index");
00526 }
00527 m.put(new Integer(op.index), op);
00528 }
00529
00530 return m;
00531 }
00532
00533 protected String catOpText(Object a, Object b) {
00534 String x = "";
00535 String y = "";
00536 if ( a!=null ) x = a.toString();
00537 if ( b!=null ) y = b.toString();
00538 return x+y;
00539 }
00540 protected List getKindOfOps(List rewrites, Class kind) {
00541 return getKindOfOps(rewrites, kind, rewrites.size());
00542 }
00543
00545 protected List getKindOfOps(List rewrites, Class kind, int before) {
00546 List ops = new ArrayList();
00547 for (int i=0; i<before && i<rewrites.size(); i++) {
00548 RewriteOperation op = (RewriteOperation)rewrites.get(i);
00549 if ( op==null ) continue;
00550 if ( op.getClass() == kind ) ops.add(op);
00551 }
00552 return ops;
00553 }
00554
00555 public String toDebugString() {
00556 return toDebugString(MIN_TOKEN_INDEX, size()-1);
00557 }
00558
00559 public String toDebugString(int start, int end) {
00560 StringBuffer buf = new StringBuffer();
00561 for (int i=start; i>=MIN_TOKEN_INDEX && i<=end && i<tokens.size(); i++) {
00562 buf.append(get(i));
00563 }
00564 return buf.toString();
00565 }
00566 }