PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/runtime/CSharp2/Sources/Antlr3.Runtime/Antlr.Runtime.Tree/BufferedTreeNodeStream.cs

https://bitbucket.org/jwalton/antlr3
C# | 557 lines | 378 code | 69 blank | 110 comment | 86 complexity | 2b36766ae005ccf31b90026b8f21eb71 MD5 | raw file
  1. /*
  2. * [The "BSD licence"]
  3. * Copyright (c) 2005-2008 Terence Parr
  4. * All rights reserved.
  5. *
  6. * Conversion to C#:
  7. * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. * 3. The name of the author may not be used to endorse or promote products
  19. * derived from this software without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  22. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  23. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  24. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  26. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  30. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. namespace Antlr.Runtime.Tree {
  33. using System.Collections.Generic;
  34. using Console = System.Console;
  35. using IList = System.Collections.IList;
  36. using InvalidOperationException = System.InvalidOperationException;
  37. using StringBuilder = System.Text.StringBuilder;
  38. /** <summary>A buffered stream of tree nodes. Nodes can be from a tree of ANY kind.</summary>
  39. *
  40. * This node stream sucks all nodes out of the tree specified in
  41. * the constructor during construction and makes pointers into
  42. * the tree using an array of Object pointers. The stream necessarily
  43. * includes pointers to DOWN and UP and EOF nodes.
  44. *
  45. * This stream knows how to mark/release for backtracking.
  46. *
  47. * This stream is most suitable for tree interpreters that need to
  48. * jump around a lot or for tree parsers requiring speed (at cost of memory).
  49. * There is some duplicated functionality here with UnBufferedTreeNodeStream
  50. * but just in bookkeeping, not tree walking etc...
  51. *
  52. * TARGET DEVELOPERS:
  53. *
  54. * This is the old CommonTreeNodeStream that buffered up entire node stream.
  55. * No need to implement really as new CommonTreeNodeStream is much better
  56. * and covers what we need.
  57. *
  58. * @see CommonTreeNodeStream
  59. */
  60. public class BufferedTreeNodeStream : ITreeNodeStream, ITokenStreamInformation {
  61. public const int DEFAULT_INITIAL_BUFFER_SIZE = 100;
  62. public const int INITIAL_CALL_STACK_SIZE = 10;
  63. protected sealed class StreamIterator : IEnumerator<object> {
  64. BufferedTreeNodeStream _outer;
  65. int _index;
  66. public StreamIterator(BufferedTreeNodeStream outer) {
  67. _outer = outer;
  68. _index = -1;
  69. }
  70. #region IEnumerator<object> Members
  71. public object Current {
  72. get {
  73. if (_index < _outer.nodes.Count)
  74. return _outer.nodes[_index];
  75. return _outer.eof;
  76. }
  77. }
  78. #endregion
  79. #region IDisposable Members
  80. public void Dispose() {
  81. }
  82. #endregion
  83. #region IEnumerator Members
  84. public bool MoveNext() {
  85. if (_index < _outer.nodes.Count)
  86. _index++;
  87. return _index < _outer.nodes.Count;
  88. }
  89. public void Reset() {
  90. _index = -1;
  91. }
  92. #endregion
  93. }
  94. // all these navigation nodes are shared and hence they
  95. // cannot contain any line/column info
  96. protected object down;
  97. protected object up;
  98. protected object eof;
  99. /** <summary>The complete mapping from stream index to tree node.
  100. * This buffer includes pointers to DOWN, UP, and EOF nodes.
  101. * It is built upon ctor invocation. The elements are type
  102. * Object as we don't what the trees look like.</summary>
  103. *
  104. * Load upon first need of the buffer so we can set token types
  105. * of interest for reverseIndexing. Slows us down a wee bit to
  106. * do all of the if p==-1 testing everywhere though.
  107. */
  108. protected IList nodes;
  109. /** <summary>Pull nodes from which tree?</summary> */
  110. protected object root;
  111. /** <summary>IF this tree (root) was created from a token stream, track it.</summary> */
  112. protected ITokenStream tokens;
  113. /** <summary>What tree adaptor was used to build these trees</summary> */
  114. ITreeAdaptor adaptor;
  115. /** <summary>Reuse same DOWN, UP navigation nodes unless this is true</summary> */
  116. bool uniqueNavigationNodes = false;
  117. /** <summary>The index into the nodes list of the current node (next node
  118. * to consume). If -1, nodes array not filled yet.</summary>
  119. */
  120. protected int p = -1;
  121. /** <summary>Track the last mark() call result value for use in rewind().</summary> */
  122. protected int lastMarker;
  123. /** <summary>Stack of indexes used for push/pop calls</summary> */
  124. protected Stack<int> calls;
  125. public BufferedTreeNodeStream(object tree)
  126. : this(new CommonTreeAdaptor(), tree) {
  127. }
  128. public BufferedTreeNodeStream(ITreeAdaptor adaptor, object tree)
  129. : this(adaptor, tree, DEFAULT_INITIAL_BUFFER_SIZE) {
  130. }
  131. public BufferedTreeNodeStream(ITreeAdaptor adaptor, object tree, int initialBufferSize) {
  132. this.root = tree;
  133. this.adaptor = adaptor;
  134. nodes = new List<object>(initialBufferSize);
  135. down = adaptor.Create(TokenTypes.Down, "DOWN");
  136. up = adaptor.Create(TokenTypes.Up, "UP");
  137. eof = adaptor.Create(TokenTypes.EndOfFile, "EOF");
  138. }
  139. #region Properties
  140. public virtual int Count {
  141. get {
  142. if (p == -1) {
  143. throw new InvalidOperationException("Cannot determine the Count before the buffer is filled.");
  144. }
  145. return nodes.Count;
  146. }
  147. }
  148. public virtual object TreeSource {
  149. get {
  150. return root;
  151. }
  152. }
  153. public virtual string SourceName {
  154. get {
  155. return TokenStream.SourceName;
  156. }
  157. }
  158. public virtual ITokenStream TokenStream {
  159. get {
  160. return tokens;
  161. }
  162. set {
  163. tokens = value;
  164. }
  165. }
  166. public virtual ITreeAdaptor TreeAdaptor {
  167. get {
  168. return adaptor;
  169. }
  170. set {
  171. adaptor = value;
  172. }
  173. }
  174. public virtual bool UniqueNavigationNodes {
  175. get {
  176. return uniqueNavigationNodes;
  177. }
  178. set {
  179. uniqueNavigationNodes = value;
  180. }
  181. }
  182. public virtual IToken LastToken {
  183. get {
  184. return TreeAdaptor.GetToken(LB(1));
  185. }
  186. }
  187. public virtual IToken LastRealToken {
  188. get {
  189. int i = 0;
  190. IToken token;
  191. do {
  192. i++;
  193. token = TreeAdaptor.GetToken(LB(i));
  194. } while (token != null && token.Line <= 0);
  195. return token;
  196. }
  197. }
  198. public virtual int MaxLookBehind {
  199. get {
  200. return int.MaxValue;
  201. }
  202. }
  203. #endregion
  204. /** Walk tree with depth-first-search and fill nodes buffer.
  205. * Don't do DOWN, UP nodes if its a list (t is isNil).
  206. */
  207. protected virtual void FillBuffer() {
  208. FillBuffer(root);
  209. //Console.Out.WriteLine( "revIndex=" + tokenTypeToStreamIndexesMap );
  210. p = 0; // buffer of nodes intialized now
  211. }
  212. public virtual void FillBuffer(object t) {
  213. bool nil = adaptor.IsNil(t);
  214. if (!nil) {
  215. nodes.Add(t); // add this node
  216. }
  217. // add DOWN node if t has children
  218. int n = adaptor.GetChildCount(t);
  219. if (!nil && n > 0) {
  220. AddNavigationNode(TokenTypes.Down);
  221. }
  222. // and now add all its children
  223. for (int c = 0; c < n; c++) {
  224. object child = adaptor.GetChild(t, c);
  225. FillBuffer(child);
  226. }
  227. // add UP node if t has children
  228. if (!nil && n > 0) {
  229. AddNavigationNode(TokenTypes.Up);
  230. }
  231. }
  232. /** What is the stream index for node? 0..n-1
  233. * Return -1 if node not found.
  234. */
  235. protected virtual int GetNodeIndex(object node) {
  236. if (p == -1) {
  237. FillBuffer();
  238. }
  239. for (int i = 0; i < nodes.Count; i++) {
  240. object t = nodes[i];
  241. if (t == node) {
  242. return i;
  243. }
  244. }
  245. return -1;
  246. }
  247. /** As we flatten the tree, we use UP, DOWN nodes to represent
  248. * the tree structure. When debugging we need unique nodes
  249. * so instantiate new ones when uniqueNavigationNodes is true.
  250. */
  251. protected virtual void AddNavigationNode(int ttype) {
  252. object navNode = null;
  253. if (ttype == TokenTypes.Down) {
  254. if (UniqueNavigationNodes) {
  255. navNode = adaptor.Create(TokenTypes.Down, "DOWN");
  256. } else {
  257. navNode = down;
  258. }
  259. } else {
  260. if (UniqueNavigationNodes) {
  261. navNode = adaptor.Create(TokenTypes.Up, "UP");
  262. } else {
  263. navNode = up;
  264. }
  265. }
  266. nodes.Add(navNode);
  267. }
  268. public virtual object this[int i] {
  269. get {
  270. if (p == -1) {
  271. throw new InvalidOperationException("Cannot get the node at index i before the buffer is filled.");
  272. }
  273. return nodes[i];
  274. }
  275. }
  276. public virtual object LT(int k) {
  277. if (p == -1) {
  278. FillBuffer();
  279. }
  280. if (k == 0) {
  281. return null;
  282. }
  283. if (k < 0) {
  284. return LB(-k);
  285. }
  286. //System.out.print("LT(p="+p+","+k+")=");
  287. if ((p + k - 1) >= nodes.Count) {
  288. return eof;
  289. }
  290. return nodes[p + k - 1];
  291. }
  292. public virtual object GetCurrentSymbol() {
  293. return LT(1);
  294. }
  295. #if false
  296. public virtual object getLastTreeNode()
  297. {
  298. int i = Index;
  299. if ( i >= size() )
  300. {
  301. i--; // if at EOF, have to start one back
  302. }
  303. Console.Out.WriteLine( "start last node: " + i + " size==" + nodes.Count );
  304. while ( i >= 0 &&
  305. ( adaptor.getType( this[i] ) == TokenTypes.EOF ||
  306. adaptor.getType( this[i] ) == TokenTypes.UP ||
  307. adaptor.getType( this[i] ) == TokenTypes.DOWN ) )
  308. {
  309. i--;
  310. }
  311. Console.Out.WriteLine( "stop at node: " + i + " " + nodes[i] );
  312. return nodes[i];
  313. }
  314. #endif
  315. /** <summary>Look backwards k nodes</summary> */
  316. protected virtual object LB(int k) {
  317. if (k == 0) {
  318. return null;
  319. }
  320. if ((p - k) < 0) {
  321. return null;
  322. }
  323. return nodes[p - k];
  324. }
  325. public virtual void Consume() {
  326. if (p == -1) {
  327. FillBuffer();
  328. }
  329. p++;
  330. }
  331. public virtual int LA(int i) {
  332. return adaptor.GetType(LT(i));
  333. }
  334. public virtual int Mark() {
  335. if (p == -1) {
  336. FillBuffer();
  337. }
  338. lastMarker = Index;
  339. return lastMarker;
  340. }
  341. public virtual void Release(int marker) {
  342. // no resources to release
  343. }
  344. public virtual int Index {
  345. get {
  346. return p;
  347. }
  348. }
  349. public virtual void Rewind(int marker) {
  350. Seek(marker);
  351. }
  352. public virtual void Rewind() {
  353. Seek(lastMarker);
  354. }
  355. public virtual void Seek(int index) {
  356. if (p == -1) {
  357. FillBuffer();
  358. }
  359. p = index;
  360. }
  361. /** <summary>
  362. * Make stream jump to a new location, saving old location.
  363. * Switch back with pop().
  364. * </summary>
  365. */
  366. public virtual void Push(int index) {
  367. if (calls == null) {
  368. calls = new Stack<int>();
  369. }
  370. calls.Push(p); // save current index
  371. Seek(index);
  372. }
  373. /** <summary>
  374. * Seek back to previous index saved during last push() call.
  375. * Return top of stack (return index).
  376. * </summary>
  377. */
  378. public virtual int Pop() {
  379. int ret = calls.Pop();
  380. Seek(ret);
  381. return ret;
  382. }
  383. public virtual void Reset() {
  384. p = 0;
  385. lastMarker = 0;
  386. if (calls != null) {
  387. calls.Clear();
  388. }
  389. }
  390. public virtual IEnumerator<object> Iterator() {
  391. if (p == -1) {
  392. FillBuffer();
  393. }
  394. return new StreamIterator(this);
  395. }
  396. // TREE REWRITE INTERFACE
  397. public virtual void ReplaceChildren(object parent, int startChildIndex, int stopChildIndex, object t) {
  398. if (parent != null) {
  399. adaptor.ReplaceChildren(parent, startChildIndex, stopChildIndex, t);
  400. }
  401. }
  402. /** <summary>Used for testing, just return the token type stream</summary> */
  403. public virtual string ToTokenTypeString() {
  404. if (p == -1) {
  405. FillBuffer();
  406. }
  407. StringBuilder buf = new StringBuilder();
  408. for (int i = 0; i < nodes.Count; i++) {
  409. object t = nodes[i];
  410. buf.Append(" ");
  411. buf.Append(adaptor.GetType(t));
  412. }
  413. return buf.ToString();
  414. }
  415. /** <summary>Debugging</summary> */
  416. public virtual string ToTokenString(int start, int stop) {
  417. if (p == -1) {
  418. FillBuffer();
  419. }
  420. StringBuilder buf = new StringBuilder();
  421. for (int i = start; i < nodes.Count && i <= stop; i++) {
  422. object t = nodes[i];
  423. buf.Append(" ");
  424. buf.Append(adaptor.GetToken(t));
  425. }
  426. return buf.ToString();
  427. }
  428. public virtual string ToString(object start, object stop) {
  429. Console.Out.WriteLine("toString");
  430. if (start == null || stop == null) {
  431. return null;
  432. }
  433. if (p == -1) {
  434. throw new InvalidOperationException("Buffer is not yet filled.");
  435. }
  436. //Console.Out.WriteLine( "stop: " + stop );
  437. if (start is CommonTree)
  438. Console.Out.Write("toString: " + ((CommonTree)start).Token + ", ");
  439. else
  440. Console.Out.WriteLine(start);
  441. if (stop is CommonTree)
  442. Console.Out.WriteLine(((CommonTree)stop).Token);
  443. else
  444. Console.Out.WriteLine(stop);
  445. // if we have the token stream, use that to dump text in order
  446. if (tokens != null) {
  447. int beginTokenIndex = adaptor.GetTokenStartIndex(start);
  448. int endTokenIndex = adaptor.GetTokenStopIndex(stop);
  449. // if it's a tree, use start/stop index from start node
  450. // else use token range from start/stop nodes
  451. if (adaptor.GetType(stop) == TokenTypes.Up) {
  452. endTokenIndex = adaptor.GetTokenStopIndex(start);
  453. } else if (adaptor.GetType(stop) == TokenTypes.EndOfFile) {
  454. endTokenIndex = Count - 2; // don't use EOF
  455. }
  456. return tokens.ToString(beginTokenIndex, endTokenIndex);
  457. }
  458. // walk nodes looking for start
  459. object t = null;
  460. int i = 0;
  461. for (; i < nodes.Count; i++) {
  462. t = nodes[i];
  463. if (t == start) {
  464. break;
  465. }
  466. }
  467. // now walk until we see stop, filling string buffer with text
  468. StringBuilder buf = new StringBuilder();
  469. t = nodes[i];
  470. while (t != stop) {
  471. string text = adaptor.GetText(t);
  472. if (text == null) {
  473. text = " " + adaptor.GetType(t).ToString();
  474. }
  475. buf.Append(text);
  476. i++;
  477. t = nodes[i];
  478. }
  479. // include stop node too
  480. string text2 = adaptor.GetText(stop);
  481. if (text2 == null) {
  482. text2 = " " + adaptor.GetType(stop).ToString();
  483. }
  484. buf.Append(text2);
  485. return buf.ToString();
  486. }
  487. }
  488. }