PageRenderTime 37ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/Dependencies/boo/lib/antlr-2.7.5/antlr/TokenStreamRewriteEngine.java

https://github.com/w4x/boolangstudio
Java | 422 lines | 277 code | 62 blank | 83 comment | 26 complexity | 346e267b27ab55324f54018bba6e5304 MD5 | raw file
Possible License(s): GPL-2.0
  1. package antlr;
  2. /* ANTLR Translator Generator
  3. * Project led by Terence Parr at http://www.jGuru.com
  4. * Software rights: http://www.antlr.org/license.html
  5. */
  6. import antlr.collections.impl.BitSet;
  7. import java.util.*;
  8. /** This token stream tracks the *entire* token stream coming from
  9. * a lexer, but does not pass on the whitespace (or whatever else
  10. * you want to discard) to the parser.
  11. *
  12. * This class can then be asked for the ith token in the input stream.
  13. * Useful for dumping out the input stream exactly after doing some
  14. * augmentation or other manipulations. Tokens are index from 0..n-1
  15. *
  16. * You can insert stuff, replace, and delete chunks. Note that the
  17. * operations are done lazily--only if you convert the buffer to a
  18. * String. This is very efficient because you are not moving data around
  19. * all the time. As the buffer of tokens is converted to strings, the
  20. * toString() method(s) check to see if there is an operation at the
  21. * current index. If so, the operation is done and then normal String
  22. * rendering continues on the buffer. This is like having multiple Turing
  23. * machine instruction streams (programs) operating on a single input tape. :)
  24. *
  25. * Since the operations are done lazily at toString-time, operations do not
  26. * screw up the token index values. That is, an insert operation at token
  27. * index i does not change the index values for tokens i+1..n-1.
  28. *
  29. * Because operations never actually alter the buffer, you may always get
  30. * the original token stream back without undoing anything. Since
  31. * the instructions are queued up, you can easily simulate transactions and
  32. * roll back any changes if there is an error just by removing instructions.
  33. * For example,
  34. *
  35. * TokenStreamRewriteEngine rewriteEngine =
  36. * new TokenStreamRewriteEngine(lexer);
  37. * JavaRecognizer parser = new JavaRecognizer(rewriteEngine);
  38. * ...
  39. * rewriteEngine.insertAfter("pass1", t, "foobar");}
  40. * rewriteEngine.insertAfter("pass2", u, "start");}
  41. * System.out.println(rewriteEngine.toString("pass1"));
  42. * System.out.println(rewriteEngine.toString("pass2"));
  43. *
  44. * You can also have multiple "instruction streams" and get multiple
  45. * rewrites from a single pass over the input. Just name the instruction
  46. * streams and use that name again when printing the buffer. This could be
  47. * useful for generating a C file and also its header file--all from the
  48. * same buffer.
  49. *
  50. * If you don't use named rewrite streams, a "default" stream is used.
  51. *
  52. * Terence Parr, parrt@cs.usfca.edu
  53. * University of San Francisco
  54. * February 2004
  55. */
  56. public class TokenStreamRewriteEngine implements TokenStream {
  57. public static final int MIN_TOKEN_INDEX = 0;
  58. static class RewriteOperation {
  59. protected int index;
  60. protected String text;
  61. protected RewriteOperation(int index, String text) {
  62. this.index = index;
  63. this.text = text;
  64. }
  65. /** Execute the rewrite operation by possibly adding to the buffer.
  66. * Return the index of the next token to operate on.
  67. */
  68. public int execute(StringBuffer buf) {
  69. return index;
  70. }
  71. }
  72. static class InsertBeforeOp extends RewriteOperation {
  73. public InsertBeforeOp(int index, String text) {
  74. super(index,text);
  75. }
  76. public int execute(StringBuffer buf) {
  77. buf.append(text);
  78. return index;
  79. }
  80. }
  81. static class ReplaceOp extends RewriteOperation {
  82. protected int lastIndex;
  83. public ReplaceOp(int from, int to, String text) {
  84. super(from,text);
  85. lastIndex = to;
  86. }
  87. public int execute(StringBuffer buf) {
  88. if ( text!=null ) {
  89. buf.append(text);
  90. }
  91. return lastIndex+1;
  92. }
  93. }
  94. static class DeleteOp extends ReplaceOp {
  95. public DeleteOp(int from, int to) {
  96. super(from, to, null);
  97. }
  98. }
  99. public static final String DEFAULT_PROGRAM_NAME = "default";
  100. public static final int PROGRAM_INIT_SIZE = 100;
  101. /** Track the incoming list of tokens */
  102. protected List tokens;
  103. /** You may have multiple, named streams of rewrite operations.
  104. * I'm calling these things "programs."
  105. * Maps String (name) -> rewrite (List)
  106. */
  107. protected Map programs = null;
  108. /** Map String (program name) -> Integer index */
  109. protected Map lastRewriteTokenIndexes = null;
  110. /** track index of tokens */
  111. protected int index = MIN_TOKEN_INDEX;
  112. /** Who do we suck tokens from? */
  113. protected TokenStream stream;
  114. /** Which (whitespace) token(s) to throw out */
  115. protected BitSet discardMask = new BitSet();
  116. public TokenStreamRewriteEngine(TokenStream upstream) {
  117. this(upstream,1000);
  118. }
  119. public TokenStreamRewriteEngine(TokenStream upstream, int initialSize) {
  120. stream = upstream;
  121. tokens = new ArrayList(initialSize);
  122. programs = new HashMap();
  123. programs.put(DEFAULT_PROGRAM_NAME,
  124. new ArrayList(PROGRAM_INIT_SIZE));
  125. lastRewriteTokenIndexes = new HashMap();
  126. }
  127. public Token nextToken() throws TokenStreamException {
  128. TokenWithIndex t;
  129. // suck tokens until end of stream or we find a non-discarded token
  130. do {
  131. t = (TokenWithIndex)stream.nextToken();
  132. if ( t!=null ) {
  133. t.setIndex(index); // what is t's index in list?
  134. if ( t.getType()!=Token.EOF_TYPE ) {
  135. tokens.add(t); // track all tokens except EOF
  136. }
  137. index++; // move to next position
  138. }
  139. } while ( t!=null && discardMask.member(t.getType()) );
  140. return t;
  141. }
  142. public void rollback(int instructionIndex) {
  143. rollback(DEFAULT_PROGRAM_NAME, instructionIndex);
  144. }
  145. /** Rollback the instruction stream for a program so that
  146. * the indicated instruction (via instructionIndex) is no
  147. * longer in the stream. UNTESTED!
  148. */
  149. public void rollback(String programName, int instructionIndex) {
  150. List is = (List)programs.get(programName);
  151. if ( is!=null ) {
  152. programs.put(programName, is.subList(MIN_TOKEN_INDEX,instructionIndex));
  153. }
  154. }
  155. public void deleteProgram() {
  156. deleteProgram(DEFAULT_PROGRAM_NAME);
  157. }
  158. /** Reset the program so that no instructions exist */
  159. public void deleteProgram(String programName) {
  160. rollback(programName, MIN_TOKEN_INDEX);
  161. }
  162. /** If op.index > lastRewriteTokenIndexes, just add to the end.
  163. * Otherwise, do linear */
  164. protected void addToSortedRewriteList(RewriteOperation op) {
  165. addToSortedRewriteList(DEFAULT_PROGRAM_NAME, op);
  166. }
  167. protected void addToSortedRewriteList(String programName, RewriteOperation op) {
  168. List rewrites = getProgram(programName);
  169. // if at or beyond last op's index, just append
  170. if ( op.index>=getLastRewriteTokenIndex(programName) ) {
  171. rewrites.add(op); // append to list of operations
  172. // record the index of this operation for next time through
  173. setLastRewriteTokenIndex(programName, op.index);
  174. return;
  175. }
  176. // not after the last one, so must insert to ordered list
  177. Comparator comparator = new Comparator() {
  178. public int compare(Object o, Object o1) {
  179. RewriteOperation a = (RewriteOperation)o;
  180. RewriteOperation b = (RewriteOperation)o1;
  181. if ( a.index<b.index ) return -1;
  182. if ( a.index>b.index ) return 1;
  183. return 0;
  184. }
  185. };
  186. int pos = Collections.binarySearch(rewrites, op, comparator);
  187. if ( pos<0 ) {
  188. rewrites.add(-pos-1, op);
  189. }
  190. }
  191. public void insertAfter(Token t, String text) {
  192. insertAfter(DEFAULT_PROGRAM_NAME, t, text);
  193. }
  194. public void insertAfter(int index, String text) {
  195. insertAfter(DEFAULT_PROGRAM_NAME, index, text);
  196. }
  197. public void insertAfter(String programName, Token t, String text) {
  198. insertAfter(programName,((TokenWithIndex)t).getIndex(), text);
  199. }
  200. public void insertAfter(String programName, int index, String text) {
  201. // to insert after, just insert before next index (even if past end)
  202. insertBefore(programName,index+1, text);
  203. }
  204. public void insertBefore(Token t, String text) {
  205. insertBefore(DEFAULT_PROGRAM_NAME, t, text);
  206. }
  207. public void insertBefore(int index, String text) {
  208. insertBefore(DEFAULT_PROGRAM_NAME, index, text);
  209. }
  210. public void insertBefore(String programName, Token t, String text) {
  211. insertBefore(programName, ((TokenWithIndex)t).getIndex(), text);
  212. }
  213. public void insertBefore(String programName, int index, String text) {
  214. addToSortedRewriteList(programName, new InsertBeforeOp(index,text));
  215. }
  216. public void replace(int index, String text) {
  217. replace(DEFAULT_PROGRAM_NAME, index, index, text);
  218. }
  219. public void replace(int from, int to, String text) {
  220. replace(DEFAULT_PROGRAM_NAME, from, to, text);
  221. }
  222. public void replace(Token indexT, String text) {
  223. replace(DEFAULT_PROGRAM_NAME, indexT, indexT, text);
  224. }
  225. public void replace(Token from, Token to, String text) {
  226. replace(DEFAULT_PROGRAM_NAME, from, to, text);
  227. }
  228. public void replace(String programName, int from, int to, String text) {
  229. addToSortedRewriteList(new ReplaceOp(from, to, text));
  230. }
  231. public void replace(String programName, Token from, Token to, String text) {
  232. replace(programName,
  233. ((TokenWithIndex)from).getIndex(),
  234. ((TokenWithIndex)to).getIndex(),
  235. text);
  236. }
  237. public void delete(int index) {
  238. delete(DEFAULT_PROGRAM_NAME, index, index);
  239. }
  240. public void delete(int from, int to) {
  241. delete(DEFAULT_PROGRAM_NAME, from, to);
  242. }
  243. public void delete(Token indexT) {
  244. delete(DEFAULT_PROGRAM_NAME, indexT, indexT);
  245. }
  246. public void delete(Token from, Token to) {
  247. delete(DEFAULT_PROGRAM_NAME, from, to);
  248. }
  249. public void delete(String programName, int from, int to) {
  250. replace(programName,from,to,null);
  251. }
  252. public void delete(String programName, Token from, Token to) {
  253. replace(programName,from,to,null);
  254. }
  255. public void discard(int ttype) {
  256. discardMask.add(ttype);
  257. }
  258. public TokenWithIndex getToken(int i) {
  259. return (TokenWithIndex)tokens.get(i);
  260. }
  261. public int getTokenStreamSize() {
  262. return tokens.size();
  263. }
  264. public String toOriginalString() {
  265. return toOriginalString(MIN_TOKEN_INDEX, getTokenStreamSize()-1);
  266. }
  267. public String toOriginalString(int start, int end) {
  268. StringBuffer buf = new StringBuffer();
  269. for (int i=start; i>=MIN_TOKEN_INDEX && i<=end && i<tokens.size(); i++) {
  270. buf.append(getToken(i).getText());
  271. }
  272. return buf.toString();
  273. }
  274. public String toString() {
  275. return toString(MIN_TOKEN_INDEX, getTokenStreamSize());
  276. }
  277. public String toString(String programName) {
  278. return toString(programName, MIN_TOKEN_INDEX, getTokenStreamSize());
  279. }
  280. public String toString(int start, int end) {
  281. return toString(DEFAULT_PROGRAM_NAME, start, end);
  282. }
  283. public String toString(String programName, int start, int end) {
  284. List rewrites = (List)programs.get(programName);
  285. if ( rewrites==null ) {
  286. return null; // invalid program
  287. }
  288. StringBuffer buf = new StringBuffer();
  289. /** Index of first rewrite we have not done */
  290. int rewriteOpIndex = 0;
  291. int tokenCursor=start;
  292. while ( tokenCursor>=MIN_TOKEN_INDEX &&
  293. tokenCursor<=end &&
  294. tokenCursor<tokens.size() )
  295. {
  296. if ( rewriteOpIndex<rewrites.size() ) {
  297. RewriteOperation op =
  298. (RewriteOperation)rewrites.get(rewriteOpIndex);
  299. while ( tokenCursor==op.index && rewriteOpIndex<rewrites.size() ) {
  300. /*
  301. System.out.println("execute op "+rewriteOpIndex+
  302. " (type "+op.getClass().getName()+")"
  303. +" at index "+op.index);
  304. */
  305. tokenCursor = op.execute(buf);
  306. rewriteOpIndex++;
  307. if ( rewriteOpIndex<rewrites.size() ) {
  308. op = (RewriteOperation)rewrites.get(rewriteOpIndex);
  309. }
  310. }
  311. }
  312. if ( tokenCursor<end ) {
  313. buf.append(getToken(tokenCursor).getText());
  314. tokenCursor++;
  315. }
  316. }
  317. // now see if there are operations (append) beyond last token index
  318. for (int opi=rewriteOpIndex; opi<rewrites.size(); opi++) {
  319. RewriteOperation op =
  320. (RewriteOperation)rewrites.get(opi);
  321. op.execute(buf); // must be insertions if after last token
  322. }
  323. return buf.toString();
  324. }
  325. public String toDebugString() {
  326. return toDebugString(MIN_TOKEN_INDEX, getTokenStreamSize());
  327. }
  328. public String toDebugString(int start, int end) {
  329. StringBuffer buf = new StringBuffer();
  330. for (int i=start; i>=MIN_TOKEN_INDEX && i<=end && i<tokens.size(); i++) {
  331. buf.append(getToken(i));
  332. }
  333. return buf.toString();
  334. }
  335. public int getLastRewriteTokenIndex() {
  336. return getLastRewriteTokenIndex(DEFAULT_PROGRAM_NAME);
  337. }
  338. protected int getLastRewriteTokenIndex(String programName) {
  339. Integer I = (Integer)lastRewriteTokenIndexes.get(programName);
  340. if ( I==null ) {
  341. return -1;
  342. }
  343. return I.intValue();
  344. }
  345. protected void setLastRewriteTokenIndex(String programName, int i) {
  346. lastRewriteTokenIndexes.put(programName, new Integer(i));
  347. }
  348. protected List getProgram(String name) {
  349. List is = (List)programs.get(name);
  350. if ( is==null ) {
  351. is = initializeProgram(name);
  352. }
  353. return is;
  354. }
  355. private List initializeProgram(String name) {
  356. List is = new ArrayList(PROGRAM_INIT_SIZE);
  357. programs.put(name, is);
  358. return is;
  359. }
  360. }