PageRenderTime 38ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/BufferedTreeNodeStream.cs

https://bitbucket.org/jwalton/antlr3
C# | 663 lines | 484 code | 69 blank | 110 comment | 83 complexity | 4751ec2aaff67bde343acc69deb03646 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. {
  34. using System.Collections.Generic;
  35. using Console = System.Console;
  36. using IList = System.Collections.IList;
  37. using InvalidOperationException = System.InvalidOperationException;
  38. using StringBuilder = System.Text.StringBuilder;
  39. /** <summary>A buffered stream of tree nodes. Nodes can be from a tree of ANY kind.</summary>
  40. *
  41. * This node stream sucks all nodes out of the tree specified in
  42. * the constructor during construction and makes pointers into
  43. * the tree using an array of Object pointers. The stream necessarily
  44. * includes pointers to DOWN and UP and EOF nodes.
  45. *
  46. * This stream knows how to mark/release for backtracking.
  47. *
  48. * This stream is most suitable for tree interpreters that need to
  49. * jump around a lot or for tree parsers requiring speed (at cost of memory).
  50. * There is some duplicated functionality here with UnBufferedTreeNodeStream
  51. * but just in bookkeeping, not tree walking etc...
  52. *
  53. * TARGET DEVELOPERS:
  54. *
  55. * This is the old CommonTreeNodeStream that buffered up entire node stream.
  56. * No need to implement really as new CommonTreeNodeStream is much better
  57. * and covers what we need.
  58. *
  59. * @see CommonTreeNodeStream
  60. */
  61. public class BufferedTreeNodeStream : ITreeNodeStream, ITokenStreamInformation
  62. {
  63. public const int DEFAULT_INITIAL_BUFFER_SIZE = 100;
  64. public const int INITIAL_CALL_STACK_SIZE = 10;
  65. protected sealed class StreamIterator : IEnumerator<object>
  66. {
  67. BufferedTreeNodeStream _outer;
  68. int _index;
  69. public StreamIterator( BufferedTreeNodeStream outer )
  70. {
  71. _outer = outer;
  72. _index = -1;
  73. }
  74. #region IEnumerator<object> Members
  75. public object Current
  76. {
  77. get
  78. {
  79. if ( _index < _outer.nodes.Count )
  80. return _outer.nodes[_index];
  81. return _outer.eof;
  82. }
  83. }
  84. #endregion
  85. #region IDisposable Members
  86. public void Dispose()
  87. {
  88. }
  89. #endregion
  90. #region IEnumerator Members
  91. public bool MoveNext()
  92. {
  93. if ( _index < _outer.nodes.Count )
  94. _index++;
  95. return _index < _outer.nodes.Count;
  96. }
  97. public void Reset()
  98. {
  99. _index = -1;
  100. }
  101. #endregion
  102. }
  103. // all these navigation nodes are shared and hence they
  104. // cannot contain any line/column info
  105. protected object down;
  106. protected object up;
  107. protected object eof;
  108. /** <summary>The complete mapping from stream index to tree node.
  109. * This buffer includes pointers to DOWN, UP, and EOF nodes.
  110. * It is built upon ctor invocation. The elements are type
  111. * Object as we don't what the trees look like.</summary>
  112. *
  113. * Load upon first need of the buffer so we can set token types
  114. * of interest for reverseIndexing. Slows us down a wee bit to
  115. * do all of the if p==-1 testing everywhere though.
  116. */
  117. protected IList nodes;
  118. /** <summary>Pull nodes from which tree?</summary> */
  119. protected object root;
  120. /** <summary>IF this tree (root) was created from a token stream, track it.</summary> */
  121. protected ITokenStream tokens;
  122. /** <summary>What tree adaptor was used to build these trees</summary> */
  123. ITreeAdaptor adaptor;
  124. /** <summary>Reuse same DOWN, UP navigation nodes unless this is true</summary> */
  125. bool uniqueNavigationNodes = false;
  126. /** <summary>The index into the nodes list of the current node (next node
  127. * to consume). If -1, nodes array not filled yet.</summary>
  128. */
  129. protected int p = -1;
  130. /** <summary>Track the last mark() call result value for use in rewind().</summary> */
  131. protected int lastMarker;
  132. /** <summary>Stack of indexes used for push/pop calls</summary> */
  133. protected Stack<int> calls;
  134. public BufferedTreeNodeStream( object tree )
  135. : this( new CommonTreeAdaptor(), tree )
  136. {
  137. }
  138. public BufferedTreeNodeStream( ITreeAdaptor adaptor, object tree )
  139. : this( adaptor, tree, DEFAULT_INITIAL_BUFFER_SIZE )
  140. {
  141. }
  142. public BufferedTreeNodeStream( ITreeAdaptor adaptor, object tree, int initialBufferSize )
  143. {
  144. this.root = tree;
  145. this.adaptor = adaptor;
  146. nodes = new List<object>( initialBufferSize );
  147. down = adaptor.Create( TokenTypes.Down, "DOWN" );
  148. up = adaptor.Create( TokenTypes.Up, "UP" );
  149. eof = adaptor.Create( TokenTypes.EndOfFile, "EOF" );
  150. }
  151. #region Properties
  152. public virtual int Count
  153. {
  154. get
  155. {
  156. if ( p == -1 )
  157. {
  158. throw new InvalidOperationException( "Cannot determine the Count before the buffer is filled." );
  159. }
  160. return nodes.Count;
  161. }
  162. }
  163. public virtual object TreeSource
  164. {
  165. get
  166. {
  167. return root;
  168. }
  169. }
  170. public virtual string SourceName
  171. {
  172. get
  173. {
  174. return TokenStream.SourceName;
  175. }
  176. }
  177. public virtual ITokenStream TokenStream
  178. {
  179. get
  180. {
  181. return tokens;
  182. }
  183. set
  184. {
  185. tokens = value;
  186. }
  187. }
  188. public virtual ITreeAdaptor TreeAdaptor
  189. {
  190. get
  191. {
  192. return adaptor;
  193. }
  194. set
  195. {
  196. adaptor = value;
  197. }
  198. }
  199. public virtual bool UniqueNavigationNodes
  200. {
  201. get
  202. {
  203. return uniqueNavigationNodes;
  204. }
  205. set
  206. {
  207. uniqueNavigationNodes = value;
  208. }
  209. }
  210. public virtual IToken LastToken
  211. {
  212. get
  213. {
  214. return TreeAdaptor.GetToken(LB(1));
  215. }
  216. }
  217. public virtual IToken LastRealToken
  218. {
  219. get
  220. {
  221. int i = 0;
  222. IToken token;
  223. do
  224. {
  225. i++;
  226. token = TreeAdaptor.GetToken(LB(i));
  227. } while (token != null && token.Line <= 0);
  228. return token;
  229. }
  230. }
  231. public virtual int MaxLookBehind
  232. {
  233. get
  234. {
  235. return int.MaxValue;
  236. }
  237. }
  238. #endregion
  239. /** Walk tree with depth-first-search and fill nodes buffer.
  240. * Don't do DOWN, UP nodes if its a list (t is isNil).
  241. */
  242. protected virtual void FillBuffer()
  243. {
  244. FillBuffer( root );
  245. //Console.Out.WriteLine( "revIndex=" + tokenTypeToStreamIndexesMap );
  246. p = 0; // buffer of nodes intialized now
  247. }
  248. public virtual void FillBuffer( object t )
  249. {
  250. bool nil = adaptor.IsNil( t );
  251. if ( !nil )
  252. {
  253. nodes.Add( t ); // add this node
  254. }
  255. // add DOWN node if t has children
  256. int n = adaptor.GetChildCount( t );
  257. if ( !nil && n > 0 )
  258. {
  259. AddNavigationNode( TokenTypes.Down );
  260. }
  261. // and now add all its children
  262. for ( int c = 0; c < n; c++ )
  263. {
  264. object child = adaptor.GetChild( t, c );
  265. FillBuffer( child );
  266. }
  267. // add UP node if t has children
  268. if ( !nil && n > 0 )
  269. {
  270. AddNavigationNode( TokenTypes.Up );
  271. }
  272. }
  273. /** What is the stream index for node? 0..n-1
  274. * Return -1 if node not found.
  275. */
  276. protected virtual int GetNodeIndex( object node )
  277. {
  278. if ( p == -1 )
  279. {
  280. FillBuffer();
  281. }
  282. for ( int i = 0; i < nodes.Count; i++ )
  283. {
  284. object t = nodes[i];
  285. if ( t == node )
  286. {
  287. return i;
  288. }
  289. }
  290. return -1;
  291. }
  292. /** As we flatten the tree, we use UP, DOWN nodes to represent
  293. * the tree structure. When debugging we need unique nodes
  294. * so instantiate new ones when uniqueNavigationNodes is true.
  295. */
  296. protected virtual void AddNavigationNode( int ttype )
  297. {
  298. object navNode = null;
  299. if ( ttype == TokenTypes.Down )
  300. {
  301. if ( UniqueNavigationNodes )
  302. {
  303. navNode = adaptor.Create( TokenTypes.Down, "DOWN" );
  304. }
  305. else
  306. {
  307. navNode = down;
  308. }
  309. }
  310. else
  311. {
  312. if ( UniqueNavigationNodes )
  313. {
  314. navNode = adaptor.Create( TokenTypes.Up, "UP" );
  315. }
  316. else
  317. {
  318. navNode = up;
  319. }
  320. }
  321. nodes.Add( navNode );
  322. }
  323. public virtual object this[int i]
  324. {
  325. get
  326. {
  327. if ( p == -1 )
  328. {
  329. throw new InvalidOperationException( "Cannot get the node at index i before the buffer is filled." );
  330. }
  331. return nodes[i];
  332. }
  333. }
  334. public virtual object LT( int k )
  335. {
  336. if ( p == -1 )
  337. {
  338. FillBuffer();
  339. }
  340. if ( k == 0 )
  341. {
  342. return null;
  343. }
  344. if ( k < 0 )
  345. {
  346. return LB( -k );
  347. }
  348. //System.out.print("LT(p="+p+","+k+")=");
  349. if ( ( p + k - 1 ) >= nodes.Count )
  350. {
  351. return eof;
  352. }
  353. return nodes[p + k - 1];
  354. }
  355. public virtual object GetCurrentSymbol()
  356. {
  357. return LT( 1 );
  358. }
  359. #if false
  360. public virtual object getLastTreeNode()
  361. {
  362. int i = Index;
  363. if ( i >= size() )
  364. {
  365. i--; // if at EOF, have to start one back
  366. }
  367. Console.Out.WriteLine( "start last node: " + i + " size==" + nodes.Count );
  368. while ( i >= 0 &&
  369. ( adaptor.getType( this[i] ) == TokenTypes.EOF ||
  370. adaptor.getType( this[i] ) == TokenTypes.UP ||
  371. adaptor.getType( this[i] ) == TokenTypes.DOWN ) )
  372. {
  373. i--;
  374. }
  375. Console.Out.WriteLine( "stop at node: " + i + " " + nodes[i] );
  376. return nodes[i];
  377. }
  378. #endif
  379. /** <summary>Look backwards k nodes</summary> */
  380. protected virtual object LB( int k )
  381. {
  382. if ( k == 0 )
  383. {
  384. return null;
  385. }
  386. if ( ( p - k ) < 0 )
  387. {
  388. return null;
  389. }
  390. return nodes[p - k];
  391. }
  392. public virtual void Consume()
  393. {
  394. if ( p == -1 )
  395. {
  396. FillBuffer();
  397. }
  398. p++;
  399. }
  400. public virtual int LA( int i )
  401. {
  402. return adaptor.GetType( LT( i ) );
  403. }
  404. public virtual int Mark()
  405. {
  406. if ( p == -1 )
  407. {
  408. FillBuffer();
  409. }
  410. lastMarker = Index;
  411. return lastMarker;
  412. }
  413. public virtual void Release( int marker )
  414. {
  415. // no resources to release
  416. }
  417. public virtual int Index
  418. {
  419. get
  420. {
  421. return p;
  422. }
  423. }
  424. public virtual void Rewind( int marker )
  425. {
  426. Seek( marker );
  427. }
  428. public virtual void Rewind()
  429. {
  430. Seek( lastMarker );
  431. }
  432. public virtual void Seek( int index )
  433. {
  434. if ( p == -1 )
  435. {
  436. FillBuffer();
  437. }
  438. p = index;
  439. }
  440. /** <summary>
  441. * Make stream jump to a new location, saving old location.
  442. * Switch back with pop().
  443. * </summary>
  444. */
  445. public virtual void Push( int index )
  446. {
  447. if ( calls == null )
  448. {
  449. calls = new Stack<int>();
  450. }
  451. calls.Push( p ); // save current index
  452. Seek( index );
  453. }
  454. /** <summary>
  455. * Seek back to previous index saved during last push() call.
  456. * Return top of stack (return index).
  457. * </summary>
  458. */
  459. public virtual int Pop()
  460. {
  461. int ret = calls.Pop();
  462. Seek( ret );
  463. return ret;
  464. }
  465. public virtual void Reset()
  466. {
  467. p = 0;
  468. lastMarker = 0;
  469. if ( calls != null )
  470. {
  471. calls.Clear();
  472. }
  473. }
  474. public virtual IEnumerator<object> Iterator()
  475. {
  476. if ( p == -1 )
  477. {
  478. FillBuffer();
  479. }
  480. return new StreamIterator( this );
  481. }
  482. // TREE REWRITE INTERFACE
  483. public virtual void ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t )
  484. {
  485. if ( parent != null )
  486. {
  487. adaptor.ReplaceChildren( parent, startChildIndex, stopChildIndex, t );
  488. }
  489. }
  490. /** <summary>Used for testing, just return the token type stream</summary> */
  491. public virtual string ToTokenTypeString()
  492. {
  493. if ( p == -1 )
  494. {
  495. FillBuffer();
  496. }
  497. StringBuilder buf = new StringBuilder();
  498. for ( int i = 0; i < nodes.Count; i++ )
  499. {
  500. object t = nodes[i];
  501. buf.Append( " " );
  502. buf.Append( adaptor.GetType( t ) );
  503. }
  504. return buf.ToString();
  505. }
  506. /** <summary>Debugging</summary> */
  507. public virtual string ToTokenString( int start, int stop )
  508. {
  509. if ( p == -1 )
  510. {
  511. FillBuffer();
  512. }
  513. StringBuilder buf = new StringBuilder();
  514. for ( int i = start; i < nodes.Count && i <= stop; i++ )
  515. {
  516. object t = nodes[i];
  517. buf.Append( " " );
  518. buf.Append( adaptor.GetToken( t ) );
  519. }
  520. return buf.ToString();
  521. }
  522. public virtual string ToString( object start, object stop )
  523. {
  524. Console.Out.WriteLine( "toString" );
  525. if ( start == null || stop == null )
  526. {
  527. return null;
  528. }
  529. if ( p == -1 )
  530. {
  531. throw new InvalidOperationException( "Buffer is not yet filled." );
  532. }
  533. //Console.Out.WriteLine( "stop: " + stop );
  534. if ( start is CommonTree )
  535. Console.Out.Write( "toString: " + ( (CommonTree)start ).Token + ", " );
  536. else
  537. Console.Out.WriteLine( start );
  538. if ( stop is CommonTree )
  539. Console.Out.WriteLine( ( (CommonTree)stop ).Token );
  540. else
  541. Console.Out.WriteLine( stop );
  542. // if we have the token stream, use that to dump text in order
  543. if ( tokens != null )
  544. {
  545. int beginTokenIndex = adaptor.GetTokenStartIndex( start );
  546. int endTokenIndex = adaptor.GetTokenStopIndex( stop );
  547. // if it's a tree, use start/stop index from start node
  548. // else use token range from start/stop nodes
  549. if ( adaptor.GetType( stop ) == TokenTypes.Up )
  550. {
  551. endTokenIndex = adaptor.GetTokenStopIndex( start );
  552. }
  553. else if ( adaptor.GetType( stop ) == TokenTypes.EndOfFile )
  554. {
  555. endTokenIndex = Count - 2; // don't use EOF
  556. }
  557. return tokens.ToString( beginTokenIndex, endTokenIndex );
  558. }
  559. // walk nodes looking for start
  560. object t = null;
  561. int i = 0;
  562. for ( ; i < nodes.Count; i++ )
  563. {
  564. t = nodes[i];
  565. if ( t == start )
  566. {
  567. break;
  568. }
  569. }
  570. // now walk until we see stop, filling string buffer with text
  571. StringBuilder buf = new StringBuilder();
  572. t = nodes[i];
  573. while ( t != stop )
  574. {
  575. string text = adaptor.GetText( t );
  576. if ( text == null )
  577. {
  578. text = " " + adaptor.GetType( t ).ToString();
  579. }
  580. buf.Append( text );
  581. i++;
  582. t = nodes[i];
  583. }
  584. // include stop node too
  585. string text2 = adaptor.GetText( stop );
  586. if ( text2 == null )
  587. {
  588. text2 = " " + adaptor.GetType( stop ).ToString();
  589. }
  590. buf.Append( text2 );
  591. return buf.ToString();
  592. }
  593. }
  594. }