PageRenderTime 44ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/Dependencies/boo/lib/antlr-2.7.5/lib/csharp/src/antlr/TokenStreamRewriteEngine.cs

https://github.com/w4x/boolangstudio
C# | 552 lines | 355 code | 72 blank | 125 comment | 35 complexity | 1d533344c2ea23b2f1d85f22452d70f3 MD5 | raw file
Possible License(s): GPL-2.0
  1. namespace antlr
  2. {
  3. /* ANTLR Translator Generator
  4. * Project led by Terence Parr at http://www.jGuru.com
  5. * Software rights: http://www.antlr.org/license.html
  6. */
  7. //
  8. // ANTLR C# Code Generator by Micheal Jordan
  9. // Kunle Odutola : kunle UNDERSCORE odutola AT hotmail DOT com
  10. // Anthony Oguntimehin
  11. //
  12. using System;
  13. using IList = System.Collections.IList;
  14. using IDictionary = System.Collections.IDictionary;
  15. using ArrayList = System.Collections.ArrayList;
  16. using Hashtable = System.Collections.Hashtable;
  17. using IComparer = System.Collections.IComparer;
  18. using StringBuilder = System.Text.StringBuilder;
  19. using BitSet = antlr.collections.impl.BitSet;
  20. /// <summary>
  21. /// This token stream tracks the *entire* token stream coming from
  22. /// a lexer, but does not pass on the whitespace (or whatever else
  23. /// you want to discard) to the parser.
  24. /// </summary>
  25. /// <remarks>
  26. /// <para>
  27. /// This class can then be asked for the ith token in the input stream.
  28. /// Useful for dumping out the input stream exactly after doing some
  29. /// augmentation or other manipulations. Tokens are index from 0..n-1
  30. /// </para>
  31. /// <para>
  32. /// You can insert stuff, replace, and delete chunks. Note that the
  33. /// operations are done lazily--only if you convert the buffer to a
  34. /// string. This is very efficient because you are not moving data around
  35. /// all the time. As the buffer of tokens is converted to strings, the
  36. /// toString() method(s) check to see if there is an operation at the
  37. /// current index. If so, the operation is done and then normal string
  38. /// rendering continues on the buffer. This is like having multiple Turing
  39. /// machine instruction streams (programs) operating on a single input tape. :)
  40. /// </para>
  41. /// <para>
  42. /// Since the operations are done lazily at toString-time, operations do not
  43. /// screw up the token index values. That is, an insert operation at token
  44. /// index i does not change the index values for tokens i+1..n-1.
  45. /// </para>
  46. /// <para>
  47. /// Because operations never actually alter the buffer, you may always get
  48. /// the original token stream back without undoing anything. Since
  49. /// the instructions are queued up, you can easily simulate transactions and
  50. /// roll back any changes if there is an error just by removing instructions.
  51. /// For example,
  52. /// </para>
  53. /// <example>For example:
  54. /// <code>
  55. /// TokenStreamRewriteEngine rewriteEngine = new TokenStreamRewriteEngine(lexer);
  56. /// JavaRecognizer parser = new JavaRecognizer(rewriteEngine);
  57. /// ...
  58. /// rewriteEngine.insertAfter("pass1", t, "foobar");}
  59. /// rewriteEngine.insertAfter("pass2", u, "start");}
  60. /// System.Console.Out.WriteLine(rewriteEngine.ToString("pass1"));
  61. /// System.Console.Out.WriteLine(rewriteEngine.ToString("pass2"));
  62. /// </code>
  63. /// </example>
  64. /// <para>
  65. /// You can also have multiple "instruction streams" and get multiple
  66. /// rewrites from a single pass over the input. Just name the instruction
  67. /// streams and use that name again when printing the buffer. This could be
  68. /// useful for generating a C file and also its header file--all from the
  69. /// same buffer.
  70. /// </para>
  71. /// <para>
  72. /// If you don't use named rewrite streams, a "default" stream is used.
  73. /// </para>
  74. /// <para>
  75. /// Terence Parr, parrt@cs.usfca.edu
  76. /// University of San Francisco
  77. /// February 2004
  78. /// </para>
  79. /// </remarks>
  80. public class TokenStreamRewriteEngine : TokenStream
  81. {
  82. public const int MIN_TOKEN_INDEX = 0;
  83. protected class RewriteOperation
  84. {
  85. protected internal int index;
  86. protected internal string text;
  87. protected RewriteOperation(int index, string text)
  88. {
  89. this.index = index;
  90. this.text = text;
  91. }
  92. /// <summary>
  93. /// Execute the rewrite operation by possibly adding to the buffer.
  94. /// </summary>
  95. /// <param name="buf">rewrite buffer</param>
  96. /// <returns>The index of the next token to operate on.</returns>
  97. public virtual int execute(StringBuilder buf)
  98. {
  99. return index;
  100. }
  101. }
  102. protected class InsertBeforeOp : RewriteOperation
  103. {
  104. public InsertBeforeOp(int index, string text) : base(index, text)
  105. {
  106. }
  107. public override int execute(StringBuilder buf)
  108. {
  109. buf.Append(text);
  110. return index;
  111. }
  112. }
  113. protected class ReplaceOp : RewriteOperation
  114. {
  115. protected int lastIndex;
  116. public ReplaceOp(int from, int to, string text) : base(from, text)
  117. {
  118. lastIndex = to;
  119. }
  120. public override int execute(StringBuilder buf)
  121. {
  122. if ( text != null )
  123. {
  124. buf.Append(text);
  125. }
  126. return lastIndex+1;
  127. }
  128. }
  129. protected class DeleteOp : ReplaceOp
  130. {
  131. public DeleteOp(int from, int to) : base(from, to, null)
  132. {
  133. }
  134. }
  135. public const string DEFAULT_PROGRAM_NAME = "default";
  136. public const int PROGRAM_INIT_SIZE = 100;
  137. /// <summary>
  138. /// Track the incoming list of tokens
  139. /// </summary>
  140. protected IList tokens;
  141. /// <summary>
  142. /// You may have multiple, named streams of rewrite operations.
  143. /// I'm calling these things "programs."
  144. /// Maps string (name) -> rewrite (List)
  145. /// </summary>
  146. protected IDictionary programs = null;
  147. /// <summary>
  148. /// Map string (program name) -> Integer index
  149. /// </summary>
  150. protected IDictionary lastRewriteTokenIndexes = null;
  151. /// <summary>
  152. /// track index of tokens
  153. /// </summary>
  154. protected int index = MIN_TOKEN_INDEX;
  155. /// <summary>
  156. /// Who do we suck tokens from?
  157. /// </summary>
  158. protected TokenStream stream;
  159. /// <summary>
  160. /// Which (whitespace) token(s) to throw out
  161. /// </summary>
  162. protected BitSet discardMask = new BitSet();
  163. public TokenStreamRewriteEngine(TokenStream upstream) : this(upstream, 1000)
  164. {
  165. }
  166. public TokenStreamRewriteEngine(TokenStream upstream, int initialSize)
  167. {
  168. stream = upstream;
  169. tokens = new ArrayList(initialSize);
  170. programs = new Hashtable();
  171. programs[DEFAULT_PROGRAM_NAME] = new ArrayList(PROGRAM_INIT_SIZE);
  172. lastRewriteTokenIndexes = new Hashtable();
  173. }
  174. public IToken nextToken() // throws TokenStreamException
  175. {
  176. TokenWithIndex t;
  177. // suck tokens until end of stream or we find a non-discarded token
  178. do
  179. {
  180. t = (TokenWithIndex) stream.nextToken();
  181. if ( t != null )
  182. {
  183. t.setIndex(index); // what is t's index in list?
  184. if ( t.Type != Token.EOF_TYPE )
  185. {
  186. tokens.Add(t); // track all tokens except EOF
  187. }
  188. index++; // move to next position
  189. }
  190. } while ( (t != null) && (discardMask.member(t.Type)) );
  191. return t;
  192. }
  193. public void rollback(int instructionIndex)
  194. {
  195. rollback(DEFAULT_PROGRAM_NAME, instructionIndex);
  196. }
  197. /// <summary>
  198. /// Rollback the instruction stream for a program so that
  199. /// the indicated instruction (via instructionIndex) is no
  200. /// longer in the stream.
  201. /// </summary>
  202. /// <remarks>
  203. /// UNTESTED!
  204. /// </remarks>
  205. /// <param name="programName"></param>
  206. /// <param name="instructionIndex"></param>
  207. public void rollback(string programName, int instructionIndex)
  208. {
  209. ArrayList il = (ArrayList) programs[programName];
  210. if ( il != null )
  211. {
  212. programs[programName] = il.GetRange(MIN_TOKEN_INDEX, (instructionIndex - MIN_TOKEN_INDEX));
  213. }
  214. }
  215. public void deleteProgram()
  216. {
  217. deleteProgram(DEFAULT_PROGRAM_NAME);
  218. }
  219. /// <summary>
  220. /// Reset the program so that no instructions exist
  221. /// </summary>
  222. /// <param name="programName"></param>
  223. public void deleteProgram(string programName)
  224. {
  225. rollback(programName, MIN_TOKEN_INDEX);
  226. }
  227. /// <summary>
  228. /// If op.index > lastRewriteTokenIndexes, just add to the end.
  229. /// Otherwise, do linear
  230. /// </summary>
  231. /// <param name="op"></param>
  232. protected void addToSortedRewriteList(RewriteOperation op)
  233. {
  234. addToSortedRewriteList(DEFAULT_PROGRAM_NAME, op);
  235. }
  236. protected void addToSortedRewriteList(string programName, RewriteOperation op)
  237. {
  238. ArrayList rewrites = (ArrayList) getProgram(programName);
  239. // if at or beyond last op's index, just append
  240. if ( op.index >= getLastRewriteTokenIndex(programName) )
  241. {
  242. rewrites.Add(op); // append to list of operations
  243. // record the index of this operation for next time through
  244. setLastRewriteTokenIndex(programName, op.index);
  245. return;
  246. }
  247. // not after the last one, so must insert to ordered list
  248. int pos = rewrites.BinarySearch(op, RewriteOperationComparer.Default);
  249. if (pos < 0)
  250. {
  251. rewrites.Insert(-pos-1, op);
  252. }
  253. }
  254. public void insertAfter(IToken t, string text)
  255. {
  256. insertAfter(DEFAULT_PROGRAM_NAME, t, text);
  257. }
  258. public void insertAfter(int index, string text)
  259. {
  260. insertAfter(DEFAULT_PROGRAM_NAME, index, text);
  261. }
  262. public void insertAfter(string programName, IToken t, string text)
  263. {
  264. insertAfter(programName,((TokenWithIndex) t).getIndex(), text);
  265. }
  266. public void insertAfter(string programName, int index, string text)
  267. {
  268. // to insert after, just insert before next index (even if past end)
  269. insertBefore(programName, index+1, text);
  270. }
  271. public void insertBefore(IToken t, string text)
  272. {
  273. insertBefore(DEFAULT_PROGRAM_NAME, t, text);
  274. }
  275. public void insertBefore(int index, string text)
  276. {
  277. insertBefore(DEFAULT_PROGRAM_NAME, index, text);
  278. }
  279. public void insertBefore(string programName, IToken t, string text)
  280. {
  281. insertBefore(programName, ((TokenWithIndex) t).getIndex(), text);
  282. }
  283. public void insertBefore(string programName, int index, string text)
  284. {
  285. addToSortedRewriteList(programName, new InsertBeforeOp(index, text));
  286. }
  287. public void replace(int index, string text)
  288. {
  289. replace(DEFAULT_PROGRAM_NAME, index, index, text);
  290. }
  291. public void replace(int from, int to, string text)
  292. {
  293. replace(DEFAULT_PROGRAM_NAME, from, to, text);
  294. }
  295. public void replace(IToken indexT, string text)
  296. {
  297. replace(DEFAULT_PROGRAM_NAME, indexT, indexT, text);
  298. }
  299. public void replace(IToken from, IToken to, string text)
  300. {
  301. replace(DEFAULT_PROGRAM_NAME, from, to, text);
  302. }
  303. public void replace(string programName, int from, int to, string text)
  304. {
  305. addToSortedRewriteList(new ReplaceOp(from, to, text));
  306. }
  307. public void replace(string programName, IToken from, IToken to, string text)
  308. {
  309. replace(programName,
  310. ((TokenWithIndex) from).getIndex(),
  311. ((TokenWithIndex) to).getIndex(),
  312. text);
  313. }
  314. public void delete(int index)
  315. {
  316. delete(DEFAULT_PROGRAM_NAME, index, index);
  317. }
  318. public void delete(int from, int to)
  319. {
  320. delete(DEFAULT_PROGRAM_NAME, from, to);
  321. }
  322. public void delete(IToken indexT)
  323. {
  324. delete(DEFAULT_PROGRAM_NAME, indexT, indexT);
  325. }
  326. public void delete(IToken from, IToken to)
  327. {
  328. delete(DEFAULT_PROGRAM_NAME, from, to);
  329. }
  330. public void delete(string programName, int from, int to)
  331. {
  332. replace(programName, from, to, null);
  333. }
  334. public void delete(string programName, IToken from, IToken to)
  335. {
  336. replace(programName, from, to, null);
  337. }
  338. public void discard(int ttype)
  339. {
  340. discardMask.add(ttype);
  341. }
  342. public TokenWithIndex getToken(int i)
  343. {
  344. return (TokenWithIndex) tokens[i];
  345. }
  346. public int getTokenStreamSize()
  347. {
  348. return tokens.Count;
  349. }
  350. public string ToOriginalString()
  351. {
  352. return ToOriginalString(MIN_TOKEN_INDEX, getTokenStreamSize()-1);
  353. }
  354. public string ToOriginalString(int start, int end)
  355. {
  356. StringBuilder buf = new StringBuilder();
  357. for (int i = start; (i >= MIN_TOKEN_INDEX) && (i <= end) && (i < tokens.Count); i++)
  358. {
  359. buf.Append(getToken(i).getText());
  360. }
  361. return buf.ToString();
  362. }
  363. public override string ToString()
  364. {
  365. return ToString(MIN_TOKEN_INDEX, getTokenStreamSize());
  366. }
  367. public string ToString(string programName)
  368. {
  369. return ToString(programName, MIN_TOKEN_INDEX, getTokenStreamSize());
  370. }
  371. public string ToString(int start, int end)
  372. {
  373. return ToString(DEFAULT_PROGRAM_NAME, start, end);
  374. }
  375. public string ToString(string programName, int start, int end)
  376. {
  377. IList rewrites = (IList) programs[programName];
  378. if (rewrites == null)
  379. {
  380. return null; // invalid program
  381. }
  382. StringBuilder buf = new StringBuilder();
  383. // Index of first rewrite we have not done
  384. int rewriteOpIndex = 0;
  385. int tokenCursor = start;
  386. while ( (tokenCursor >= MIN_TOKEN_INDEX) &&
  387. (tokenCursor <= end) &&
  388. (tokenCursor < tokens.Count) )
  389. {
  390. if (rewriteOpIndex < rewrites.Count)
  391. {
  392. RewriteOperation op = (RewriteOperation) rewrites[rewriteOpIndex];
  393. while ( (tokenCursor == op.index) && (rewriteOpIndex < rewrites.Count) )
  394. {
  395. /*
  396. Console.Out.WriteLine("execute op "+rewriteOpIndex+
  397. " (type "+op.GetType().FullName+")"
  398. +" at index "+op.index);
  399. */
  400. tokenCursor = op.execute(buf);
  401. rewriteOpIndex++;
  402. if (rewriteOpIndex < rewrites.Count)
  403. {
  404. op = (RewriteOperation) rewrites[rewriteOpIndex];
  405. }
  406. }
  407. }
  408. if ( tokenCursor < end )
  409. {
  410. buf.Append(getToken(tokenCursor).getText());
  411. tokenCursor++;
  412. }
  413. }
  414. // now see if there are operations (append) beyond last token index
  415. for (int opi = rewriteOpIndex; opi < rewrites.Count; opi++)
  416. {
  417. RewriteOperation op = (RewriteOperation) rewrites[opi];
  418. op.execute(buf); // must be insertions if after last token
  419. }
  420. return buf.ToString();
  421. }
  422. public string ToDebugString()
  423. {
  424. return ToDebugString(MIN_TOKEN_INDEX, getTokenStreamSize());
  425. }
  426. public string ToDebugString(int start, int end)
  427. {
  428. StringBuilder buf = new StringBuilder();
  429. for (int i = start; (i >= MIN_TOKEN_INDEX) && (i <= end) && (i < tokens.Count); i++)
  430. {
  431. buf.Append(getToken(i));
  432. }
  433. return buf.ToString();
  434. }
  435. public int getLastRewriteTokenIndex()
  436. {
  437. return getLastRewriteTokenIndex(DEFAULT_PROGRAM_NAME);
  438. }
  439. protected int getLastRewriteTokenIndex(string programName)
  440. {
  441. object i = lastRewriteTokenIndexes[programName];
  442. if (i == null)
  443. {
  444. return -1;
  445. }
  446. return (int) i;
  447. }
  448. protected void setLastRewriteTokenIndex(string programName, int i)
  449. {
  450. lastRewriteTokenIndexes[programName] = (object) i;
  451. }
  452. protected IList getProgram(string name)
  453. {
  454. IList il = (IList) programs[name];
  455. if ( il == null )
  456. {
  457. il = initializeProgram(name);
  458. }
  459. return il;
  460. }
  461. private IList initializeProgram(string name)
  462. {
  463. IList il = new ArrayList(PROGRAM_INIT_SIZE);
  464. programs[name] = il;
  465. return il;
  466. }
  467. public class RewriteOperationComparer : IComparer
  468. {
  469. public static readonly RewriteOperationComparer Default = new RewriteOperationComparer();
  470. public virtual int Compare(object o1, object o2)
  471. {
  472. RewriteOperation rop1 = (RewriteOperation) o1;
  473. RewriteOperation rop2 = (RewriteOperation) o2;
  474. if (rop1.index < rop2.index) return -1;
  475. if (rop1.index > rop2.index) return 1;
  476. return 0;
  477. }
  478. }
  479. }
  480. }