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
00097 protected RewriteOperation(int index) {
00098 this.index = index;
00099 }
00100
00101 protected RewriteOperation(int index, Object text) {
00102 this.index = index;
00103 this.text = text;
00104 }
00108 public int execute(StringBuffer buf) {
00109 return index;
00110 }
00111 public String toString() {
00112 String opName = getClass().getName();
00113 int $index = opName.indexOf('$');
00114 opName = opName.substring($index+1, opName.length());
00115 return "<"+opName+"@"+tokens.get(index)+
00116 ":\""+text+"\">";
00117 }
00118 }
00119
00120 class InsertBeforeOp extends RewriteOperation {
00121 public InsertBeforeOp(int index, Object text) {
00122 super(index,text);
00123 }
00124 public int execute(StringBuffer buf) {
00125 buf.append(text);
00126 if ( tokens.get(index).getType()!=Token.EOF ) {
00127 buf.append(tokens.get(index).getText());
00128 }
00129 return index+1;
00130 }
00131 }
00132
00136 class ReplaceOp extends RewriteOperation {
00137 protected int lastIndex;
00138 public ReplaceOp(int from, int to, Object text) {
00139 super(from,text);
00140 lastIndex = to;
00141 }
00142 public int execute(StringBuffer buf) {
00143 if ( text!=null ) {
00144 buf.append(text);
00145 }
00146 return lastIndex+1;
00147 }
00148 public String toString() {
00149 if ( text==null ) {
00150 return "<DeleteOp@"+tokens.get(index)+
00151 ".."+tokens.get(lastIndex)+">";
00152 }
00153 return "<ReplaceOp@"+tokens.get(index)+
00154 ".."+tokens.get(lastIndex)+":\""+text+"\">";
00155 }
00156 }
00157
00162 protected Map programs = null;
00163
00165 protected Map lastRewriteTokenIndexes = null;
00166
00167 public TokenRewriteStream() {
00168 init();
00169 }
00170
00171 protected void init() {
00172 programs = new HashMap();
00173 programs.put(DEFAULT_PROGRAM_NAME, new ArrayList(PROGRAM_INIT_SIZE));
00174 lastRewriteTokenIndexes = new HashMap();
00175 }
00176
00177 public TokenRewriteStream(TokenSource tokenSource) {
00178 super(tokenSource);
00179 init();
00180 }
00181
00182 public TokenRewriteStream(TokenSource tokenSource, int channel) {
00183 super(tokenSource, channel);
00184 init();
00185 }
00186
00187 public void rollback(int instructionIndex) {
00188 rollback(DEFAULT_PROGRAM_NAME, instructionIndex);
00189 }
00190
00195 public void rollback(String programName, int instructionIndex) {
00196 List is = (List)programs.get(programName);
00197 if ( is!=null ) {
00198 programs.put(programName, is.subList(MIN_TOKEN_INDEX,instructionIndex));
00199 }
00200 }
00201
00202 public void deleteProgram() {
00203 deleteProgram(DEFAULT_PROGRAM_NAME);
00204 }
00205
00207 public void deleteProgram(String programName) {
00208 rollback(programName, MIN_TOKEN_INDEX);
00209 }
00210
00211 public void insertAfter(Token t, Object text) {
00212 insertAfter(DEFAULT_PROGRAM_NAME, t, text);
00213 }
00214
00215 public void insertAfter(int index, Object text) {
00216 insertAfter(DEFAULT_PROGRAM_NAME, index, text);
00217 }
00218
00219 public void insertAfter(String programName, Token t, Object text) {
00220 insertAfter(programName,t.getTokenIndex(), text);
00221 }
00222
00223 public void insertAfter(String programName, int index, Object text) {
00224
00225 insertBefore(programName,index+1, text);
00226 }
00227
00228 public void insertBefore(Token t, Object text) {
00229 insertBefore(DEFAULT_PROGRAM_NAME, t, text);
00230 }
00231
00232 public void insertBefore(int index, Object text) {
00233 insertBefore(DEFAULT_PROGRAM_NAME, index, text);
00234 }
00235
00236 public void insertBefore(String programName, Token t, Object text) {
00237 insertBefore(programName, t.getTokenIndex(), text);
00238 }
00239
00240 public void insertBefore(String programName, int index, Object text) {
00241 RewriteOperation op = new InsertBeforeOp(index,text);
00242 List rewrites = getProgram(programName);
00243 op.instructionIndex = rewrites.size();
00244 rewrites.add(op);
00245 }
00246
00247 public void replace(int index, Object text) {
00248 replace(DEFAULT_PROGRAM_NAME, index, index, text);
00249 }
00250
00251 public void replace(int from, int to, Object text) {
00252 replace(DEFAULT_PROGRAM_NAME, from, to, text);
00253 }
00254
00255 public void replace(Token indexT, Object text) {
00256 replace(DEFAULT_PROGRAM_NAME, indexT, indexT, text);
00257 }
00258
00259 public void replace(Token from, Token to, Object text) {
00260 replace(DEFAULT_PROGRAM_NAME, from, to, text);
00261 }
00262
00263 public void replace(String programName, int from, int to, Object text) {
00264 if ( from > to || from<0 || to<0 || to >= tokens.size() ) {
00265 throw new IllegalArgumentException("replace: range invalid: "+from+".."+to+"(size="+tokens.size()+")");
00266 }
00267 RewriteOperation op = new ReplaceOp(from, to, text);
00268 List rewrites = getProgram(programName);
00269 op.instructionIndex = rewrites.size();
00270 rewrites.add(op);
00271 }
00272
00273 public void replace(String programName, Token from, Token to, Object text) {
00274 replace(programName,
00275 from.getTokenIndex(),
00276 to.getTokenIndex(),
00277 text);
00278 }
00279
00280 public void delete(int index) {
00281 delete(DEFAULT_PROGRAM_NAME, index, index);
00282 }
00283
00284 public void delete(int from, int to) {
00285 delete(DEFAULT_PROGRAM_NAME, from, to);
00286 }
00287
00288 public void delete(Token indexT) {
00289 delete(DEFAULT_PROGRAM_NAME, indexT, indexT);
00290 }
00291
00292 public void delete(Token from, Token to) {
00293 delete(DEFAULT_PROGRAM_NAME, from, to);
00294 }
00295
00296 public void delete(String programName, int from, int to) {
00297 replace(programName,from,to,null);
00298 }
00299
00300 public void delete(String programName, Token from, Token to) {
00301 replace(programName,from,to,null);
00302 }
00303
00304 public int getLastRewriteTokenIndex() {
00305 return getLastRewriteTokenIndex(DEFAULT_PROGRAM_NAME);
00306 }
00307
00308 protected int getLastRewriteTokenIndex(String programName) {
00309 Integer I = (Integer)lastRewriteTokenIndexes.get(programName);
00310 if ( I==null ) {
00311 return -1;
00312 }
00313 return I.intValue();
00314 }
00315
00316 protected void setLastRewriteTokenIndex(String programName, int i) {
00317 lastRewriteTokenIndexes.put(programName, new Integer(i));
00318 }
00319
00320 protected List getProgram(String name) {
00321 List is = (List)programs.get(name);
00322 if ( is==null ) {
00323 is = initializeProgram(name);
00324 }
00325 return is;
00326 }
00327
00328 private List initializeProgram(String name) {
00329 List is = new ArrayList(PROGRAM_INIT_SIZE);
00330 programs.put(name, is);
00331 return is;
00332 }
00333
00334 public String toOriginalString() {
00335 fill();
00336 return toOriginalString(MIN_TOKEN_INDEX, size()-1);
00337 }
00338
00339 public String toOriginalString(int start, int end) {
00340 StringBuffer buf = new StringBuffer();
00341 for (int i=start; i>=MIN_TOKEN_INDEX && i<=end && i<tokens.size(); i++) {
00342 if ( get(i).getType()!=Token.EOF ) buf.append(get(i).getText());
00343 }
00344 return buf.toString();
00345 }
00346
00347 public String toString() {
00348 fill();
00349 return toString(MIN_TOKEN_INDEX, size()-1);
00350 }
00351
00352 public String toString(String programName) {
00353 fill();
00354 return toString(programName, MIN_TOKEN_INDEX, size()-1);
00355 }
00356
00357 public String toString(int start, int end) {
00358 return toString(DEFAULT_PROGRAM_NAME, start, end);
00359 }
00360
00361 public String toString(String programName, int start, int end) {
00362 List rewrites = (List)programs.get(programName);
00363
00364
00365 if ( end>tokens.size()-1 ) end = tokens.size()-1;
00366 if ( start<0 ) start = 0;
00367
00368 if ( rewrites==null || rewrites.size()==0 ) {
00369 return toOriginalString(start,end);
00370 }
00371 StringBuffer buf = new StringBuffer();
00372
00373
00374 Map indexToOp = reduceToSingleOperationPerIndex(rewrites);
00375
00376
00377 int i = start;
00378 while ( i <= end && i < tokens.size() ) {
00379 RewriteOperation op = (RewriteOperation)indexToOp.get(new Integer(i));
00380 indexToOp.remove(new Integer(i));
00381 Token t = (Token) tokens.get(i);
00382 if ( op==null ) {
00383
00384 if ( t.getType()!=Token.EOF ) buf.append(t.getText());
00385 i++;
00386 }
00387 else {
00388 i = op.execute(buf);
00389 }
00390 }
00391
00392
00393
00394
00395 if ( end==tokens.size()-1 ) {
00396
00397
00398 Iterator it = indexToOp.values().iterator();
00399 while (it.hasNext()) {
00400 RewriteOperation op = (RewriteOperation)it.next();
00401 if ( op.index >= tokens.size()-1 ) buf.append(op.text);
00402 }
00403 }
00404 return buf.toString();
00405 }
00406
00456 protected Map reduceToSingleOperationPerIndex(List rewrites) {
00457
00458
00459
00460 for (int i = 0; i < rewrites.size(); i++) {
00461 RewriteOperation op = (RewriteOperation)rewrites.get(i);
00462 if ( op==null ) continue;
00463 if ( !(op instanceof ReplaceOp) ) continue;
00464 ReplaceOp rop = (ReplaceOp)rewrites.get(i);
00465
00466 List inserts = getKindOfOps(rewrites, InsertBeforeOp.class, i);
00467 for (int j = 0; j < inserts.size(); j++) {
00468 InsertBeforeOp iop = (InsertBeforeOp) inserts.get(j);
00469 if ( iop.index == rop.index ) {
00470
00471
00472 rewrites.set(iop.instructionIndex, null);
00473 rop.text = iop.text.toString() + (rop.text!=null?rop.text.toString():"");
00474 }
00475 else if ( iop.index > rop.index && iop.index <= rop.lastIndex ) {
00476
00477 rewrites.set(iop.instructionIndex, null);
00478 }
00479 }
00480
00481 List prevReplaces = getKindOfOps(rewrites, ReplaceOp.class, i);
00482 for (int j = 0; j < prevReplaces.size(); j++) {
00483 ReplaceOp prevRop = (ReplaceOp) prevReplaces.get(j);
00484 if ( prevRop.index>=rop.index && prevRop.lastIndex <= rop.lastIndex ) {
00485
00486 rewrites.set(prevRop.instructionIndex, null);
00487 continue;
00488 }
00489
00490 boolean disjoint =
00491 prevRop.lastIndex<rop.index || prevRop.index > rop.lastIndex;
00492 boolean same =
00493 prevRop.index==rop.index && prevRop.lastIndex==rop.lastIndex;
00494
00495
00496 if ( prevRop.text==null && rop.text==null && !disjoint ) {
00497
00498 rewrites.set(prevRop.instructionIndex, null);
00499 rop.index = Math.min(prevRop.index, rop.index);
00500 rop.lastIndex = Math.max(prevRop.lastIndex, rop.lastIndex);
00501 System.out.println("new rop "+rop);
00502 }
00503 else if ( !disjoint && !same ) {
00504 throw new IllegalArgumentException("replace op boundaries of "+rop+
00505 " overlap with previous "+prevRop);
00506 }
00507 }
00508 }
00509
00510
00511 for (int i = 0; i < rewrites.size(); i++) {
00512 RewriteOperation op = (RewriteOperation)rewrites.get(i);
00513 if ( op==null ) continue;
00514 if ( !(op instanceof InsertBeforeOp) ) continue;
00515 InsertBeforeOp iop = (InsertBeforeOp)rewrites.get(i);
00516
00517 List prevInserts = getKindOfOps(rewrites, InsertBeforeOp.class, i);
00518 for (int j = 0; j < prevInserts.size(); j++) {
00519 InsertBeforeOp prevIop = (InsertBeforeOp) prevInserts.get(j);
00520 if ( prevIop.index == iop.index ) {
00521
00522
00523 iop.text = catOpText(iop.text,prevIop.text);
00524
00525 rewrites.set(prevIop.instructionIndex, null);
00526 }
00527 }
00528
00529 List prevReplaces = getKindOfOps(rewrites, ReplaceOp.class, i);
00530 for (int j = 0; j < prevReplaces.size(); j++) {
00531 ReplaceOp rop = (ReplaceOp) prevReplaces.get(j);
00532 if ( iop.index == rop.index ) {
00533 rop.text = catOpText(iop.text,rop.text);
00534 rewrites.set(i, null);
00535 continue;
00536 }
00537 if ( iop.index >= rop.index && iop.index <= rop.lastIndex ) {
00538 throw new IllegalArgumentException("insert op "+iop+
00539 " within boundaries of previous "+rop);
00540 }
00541 }
00542 }
00543
00544 Map m = new HashMap();
00545 for (int i = 0; i < rewrites.size(); i++) {
00546 RewriteOperation op = (RewriteOperation)rewrites.get(i);
00547 if ( op==null ) continue;
00548 if ( m.get(new Integer(op.index))!=null ) {
00549 throw new Error("should only be one op per index");
00550 }
00551 m.put(new Integer(op.index), op);
00552 }
00553
00554 return m;
00555 }
00556
00557 protected String catOpText(Object a, Object b) {
00558 String x = "";
00559 String y = "";
00560 if ( a!=null ) x = a.toString();
00561 if ( b!=null ) y = b.toString();
00562 return x+y;
00563 }
00564 protected List getKindOfOps(List rewrites, Class kind) {
00565 return getKindOfOps(rewrites, kind, rewrites.size());
00566 }
00567
00569 protected List getKindOfOps(List rewrites, Class kind, int before) {
00570 List ops = new ArrayList();
00571 for (int i=0; i<before && i<rewrites.size(); i++) {
00572 RewriteOperation op = (RewriteOperation)rewrites.get(i);
00573 if ( op==null ) continue;
00574 if ( op.getClass() == kind ) ops.add(op);
00575 }
00576 return ops;
00577 }
00578
00579 public String toDebugString() {
00580 return toDebugString(MIN_TOKEN_INDEX, size()-1);
00581 }
00582
00583 public String toDebugString(int start, int end) {
00584 StringBuffer buf = new StringBuffer();
00585 for (int i=start; i>=MIN_TOKEN_INDEX && i<=end && i<tokens.size(); i++) {
00586 buf.append(get(i));
00587 }
00588 return buf.toString();
00589 }
00590 }