PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/antlr-3.4/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeWizard.cs

https://bitbucket.org/cyanogenmod/android_external_antlr
C# | 736 lines | 440 code | 53 blank | 243 comment | 79 complexity | 136c9874475cc53ae6acc8637e82e76c 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. // TODO: build indexes for wizard
  33. //#define BUILD_INDEXES
  34. namespace Antlr.Runtime.Tree
  35. {
  36. using System.Collections.Generic;
  37. using IList = System.Collections.IList;
  38. #if BUILD_INDEXES
  39. using IDictionary = System.Collections.IDictionary;
  40. #endif
  41. /** <summary>
  42. * Build and navigate trees with this object. Must know about the names
  43. * of tokens so you have to pass in a map or array of token names (from which
  44. * this class can build the map). I.e., Token DECL means nothing unless the
  45. * class can translate it to a token type.
  46. * </summary>
  47. *
  48. * <remarks>
  49. * In order to create nodes and navigate, this class needs a TreeAdaptor.
  50. *
  51. * This class can build a token type -> node index for repeated use or for
  52. * iterating over the various nodes with a particular type.
  53. *
  54. * This class works in conjunction with the TreeAdaptor rather than moving
  55. * all this functionality into the adaptor. An adaptor helps build and
  56. * navigate trees using methods. This class helps you do it with string
  57. * patterns like "(A B C)". You can create a tree from that pattern or
  58. * match subtrees against it.
  59. * </remarks>
  60. */
  61. public class TreeWizard
  62. {
  63. protected ITreeAdaptor adaptor;
  64. protected IDictionary<string, int> tokenNameToTypeMap;
  65. public interface IContextVisitor
  66. {
  67. // TODO: should this be called visit or something else?
  68. void Visit( object t, object parent, int childIndex, IDictionary<string, object> labels );
  69. }
  70. public abstract class Visitor : IContextVisitor
  71. {
  72. public virtual void Visit( object t, object parent, int childIndex, IDictionary<string, object> labels )
  73. {
  74. Visit( t );
  75. }
  76. public abstract void Visit( object t );
  77. }
  78. class ActionVisitor : Visitor
  79. {
  80. System.Action<object> _action;
  81. public ActionVisitor( System.Action<object> action )
  82. {
  83. _action = action;
  84. }
  85. public override void Visit( object t )
  86. {
  87. _action( t );
  88. }
  89. }
  90. /** <summary>
  91. * When using %label:TOKENNAME in a tree for parse(), we must
  92. * track the label.
  93. * </summary>
  94. */
  95. public class TreePattern : CommonTree
  96. {
  97. public string label;
  98. public bool hasTextArg;
  99. public TreePattern( IToken payload ) :
  100. base( payload )
  101. {
  102. }
  103. public override string ToString()
  104. {
  105. if ( label != null )
  106. {
  107. return "%" + label + ":"; //+ base.ToString();
  108. }
  109. else
  110. {
  111. return base.ToString();
  112. }
  113. }
  114. }
  115. public class WildcardTreePattern : TreePattern
  116. {
  117. public WildcardTreePattern( IToken payload ) :
  118. base( payload )
  119. {
  120. }
  121. }
  122. /** <summary>This adaptor creates TreePattern objects for use during scan()</summary> */
  123. public class TreePatternTreeAdaptor : CommonTreeAdaptor
  124. {
  125. public override object Create( IToken payload )
  126. {
  127. return new TreePattern( payload );
  128. }
  129. }
  130. #if BUILD_INDEXES
  131. // TODO: build indexes for the wizard
  132. /** <summary>
  133. * During fillBuffer(), we can make a reverse index from a set
  134. * of token types of interest to the list of indexes into the
  135. * node stream. This lets us convert a node pointer to a
  136. * stream index semi-efficiently for a list of interesting
  137. * nodes such as function definition nodes (you'll want to seek
  138. * to their bodies for an interpreter). Also useful for doing
  139. * dynamic searches; i.e., go find me all PLUS nodes.
  140. * </summary>
  141. */
  142. protected IDictionary<int, IList<int>> tokenTypeToStreamIndexesMap;
  143. /** <summary>
  144. * If tokenTypesToReverseIndex set to INDEX_ALL then indexing
  145. * occurs for all token types.
  146. * </summary>
  147. */
  148. public static readonly HashSet<int> INDEX_ALL = new HashSet<int>();
  149. /** <summary>
  150. * A set of token types user would like to index for faster lookup.
  151. * If this is INDEX_ALL, then all token types are tracked. If null,
  152. * then none are indexed.
  153. * </summary>
  154. */
  155. protected HashSet<int> tokenTypesToReverseIndex = null;
  156. #endif
  157. public TreeWizard( ITreeAdaptor adaptor )
  158. {
  159. this.adaptor = adaptor;
  160. }
  161. public TreeWizard( ITreeAdaptor adaptor, IDictionary<string, int> tokenNameToTypeMap )
  162. {
  163. this.adaptor = adaptor;
  164. this.tokenNameToTypeMap = tokenNameToTypeMap;
  165. }
  166. public TreeWizard( ITreeAdaptor adaptor, string[] tokenNames )
  167. {
  168. this.adaptor = adaptor;
  169. this.tokenNameToTypeMap = ComputeTokenTypes( tokenNames );
  170. }
  171. public TreeWizard( string[] tokenNames )
  172. : this( new CommonTreeAdaptor(), tokenNames )
  173. {
  174. }
  175. /** <summary>
  176. * Compute a Map&lt;String, Integer&gt; that is an inverted index of
  177. * tokenNames (which maps int token types to names).
  178. * </summary>
  179. */
  180. public virtual IDictionary<string, int> ComputeTokenTypes( string[] tokenNames )
  181. {
  182. IDictionary<string, int> m = new Dictionary<string, int>();
  183. if ( tokenNames == null )
  184. {
  185. return m;
  186. }
  187. for ( int ttype = TokenTypes.Min; ttype < tokenNames.Length; ttype++ )
  188. {
  189. string name = tokenNames[ttype];
  190. m[name] = ttype;
  191. }
  192. return m;
  193. }
  194. /** <summary>Using the map of token names to token types, return the type.</summary> */
  195. public virtual int GetTokenType( string tokenName )
  196. {
  197. if ( tokenNameToTypeMap == null )
  198. {
  199. return TokenTypes.Invalid;
  200. }
  201. int value;
  202. if ( tokenNameToTypeMap.TryGetValue( tokenName, out value ) )
  203. return value;
  204. return TokenTypes.Invalid;
  205. }
  206. /** <summary>
  207. * Walk the entire tree and make a node name to nodes mapping.
  208. * For now, use recursion but later nonrecursive version may be
  209. * more efficient. Returns Map&lt;Integer, List&gt; where the List is
  210. * of your AST node type. The Integer is the token type of the node.
  211. * </summary>
  212. *
  213. * <remarks>
  214. * TODO: save this index so that find and visit are faster
  215. * </remarks>
  216. */
  217. public IDictionary<int, IList> Index( object t )
  218. {
  219. IDictionary<int, IList> m = new Dictionary<int, IList>();
  220. IndexCore( t, m );
  221. return m;
  222. }
  223. /** <summary>Do the work for index</summary> */
  224. protected virtual void IndexCore( object t, IDictionary<int, IList> m )
  225. {
  226. if ( t == null )
  227. {
  228. return;
  229. }
  230. int ttype = adaptor.GetType( t );
  231. IList elements;
  232. if ( !m.TryGetValue( ttype, out elements ) || elements == null )
  233. {
  234. elements = new List<object>();
  235. m[ttype] = elements;
  236. }
  237. elements.Add( t );
  238. int n = adaptor.GetChildCount( t );
  239. for ( int i = 0; i < n; i++ )
  240. {
  241. object child = adaptor.GetChild( t, i );
  242. IndexCore( child, m );
  243. }
  244. }
  245. class FindTreeWizardVisitor : TreeWizard.Visitor
  246. {
  247. IList _nodes;
  248. public FindTreeWizardVisitor( IList nodes )
  249. {
  250. _nodes = nodes;
  251. }
  252. public override void Visit( object t )
  253. {
  254. _nodes.Add( t );
  255. }
  256. }
  257. class FindTreeWizardContextVisitor : TreeWizard.IContextVisitor
  258. {
  259. TreeWizard _outer;
  260. TreePattern _tpattern;
  261. IList _subtrees;
  262. public FindTreeWizardContextVisitor( TreeWizard outer, TreePattern tpattern, IList subtrees )
  263. {
  264. _outer = outer;
  265. _tpattern = tpattern;
  266. _subtrees = subtrees;
  267. }
  268. public void Visit( object t, object parent, int childIndex, IDictionary<string, object> labels )
  269. {
  270. if ( _outer.ParseCore( t, _tpattern, null ) )
  271. {
  272. _subtrees.Add( t );
  273. }
  274. }
  275. }
  276. /** <summary>Return a List of tree nodes with token type ttype</summary> */
  277. public virtual IList Find( object t, int ttype )
  278. {
  279. IList nodes = new List<object>();
  280. Visit( t, ttype, new FindTreeWizardVisitor( nodes ) );
  281. return nodes;
  282. }
  283. /** <summary>Return a List of subtrees matching pattern.</summary> */
  284. public virtual IList Find( object t, string pattern )
  285. {
  286. IList subtrees = new List<object>();
  287. // Create a TreePattern from the pattern
  288. TreePatternLexer tokenizer = new TreePatternLexer( pattern );
  289. TreePatternParser parser =
  290. new TreePatternParser( tokenizer, this, new TreePatternTreeAdaptor() );
  291. TreePattern tpattern = (TreePattern)parser.Pattern();
  292. // don't allow invalid patterns
  293. if ( tpattern == null ||
  294. tpattern.IsNil ||
  295. tpattern.GetType() == typeof( WildcardTreePattern ) )
  296. {
  297. return null;
  298. }
  299. int rootTokenType = tpattern.Type;
  300. Visit( t, rootTokenType, new FindTreeWizardContextVisitor( this, tpattern, subtrees ) );
  301. return subtrees;
  302. }
  303. public virtual object FindFirst( object t, int ttype )
  304. {
  305. return null;
  306. }
  307. public virtual object FindFirst( object t, string pattern )
  308. {
  309. return null;
  310. }
  311. /** <summary>
  312. * Visit every ttype node in t, invoking the visitor. This is a quicker
  313. * version of the general visit(t, pattern) method. The labels arg
  314. * of the visitor action method is never set (it's null) since using
  315. * a token type rather than a pattern doesn't let us set a label.
  316. * </summary>
  317. */
  318. public void Visit( object t, int ttype, IContextVisitor visitor )
  319. {
  320. VisitCore( t, null, 0, ttype, visitor );
  321. }
  322. public void Visit( object t, int ttype, System.Action<object> action )
  323. {
  324. Visit( t, ttype, new ActionVisitor( action ) );
  325. }
  326. /** <summary>Do the recursive work for visit</summary> */
  327. protected virtual void VisitCore( object t, object parent, int childIndex, int ttype, IContextVisitor visitor )
  328. {
  329. if ( t == null )
  330. {
  331. return;
  332. }
  333. if ( adaptor.GetType( t ) == ttype )
  334. {
  335. visitor.Visit( t, parent, childIndex, null );
  336. }
  337. int n = adaptor.GetChildCount( t );
  338. for ( int i = 0; i < n; i++ )
  339. {
  340. object child = adaptor.GetChild( t, i );
  341. VisitCore( child, t, i, ttype, visitor );
  342. }
  343. }
  344. class VisitTreeWizardContextVisitor : TreeWizard.IContextVisitor
  345. {
  346. TreeWizard _outer;
  347. IContextVisitor _visitor;
  348. IDictionary<string, object> _labels;
  349. TreePattern _tpattern;
  350. public VisitTreeWizardContextVisitor( TreeWizard outer, IContextVisitor visitor, IDictionary<string, object> labels, TreePattern tpattern )
  351. {
  352. _outer = outer;
  353. _visitor = visitor;
  354. _labels = labels;
  355. _tpattern = tpattern;
  356. }
  357. public void Visit( object t, object parent, int childIndex, IDictionary<string, object> unusedlabels )
  358. {
  359. // the unusedlabels arg is null as visit on token type doesn't set.
  360. _labels.Clear();
  361. if ( _outer.ParseCore( t, _tpattern, _labels ) )
  362. {
  363. _visitor.Visit( t, parent, childIndex, _labels );
  364. }
  365. }
  366. }
  367. /** <summary>
  368. * For all subtrees that match the pattern, execute the visit action.
  369. * The implementation uses the root node of the pattern in combination
  370. * with visit(t, ttype, visitor) so nil-rooted patterns are not allowed.
  371. * Patterns with wildcard roots are also not allowed.
  372. * </summary>
  373. */
  374. public void Visit( object t, string pattern, IContextVisitor visitor )
  375. {
  376. // Create a TreePattern from the pattern
  377. TreePatternLexer tokenizer = new TreePatternLexer( pattern );
  378. TreePatternParser parser =
  379. new TreePatternParser( tokenizer, this, new TreePatternTreeAdaptor() );
  380. TreePattern tpattern = (TreePattern)parser.Pattern();
  381. // don't allow invalid patterns
  382. if ( tpattern == null ||
  383. tpattern.IsNil ||
  384. tpattern.GetType() == typeof( WildcardTreePattern ) )
  385. {
  386. return;
  387. }
  388. IDictionary<string, object> labels = new Dictionary<string, object>(); // reused for each _parse
  389. int rootTokenType = tpattern.Type;
  390. Visit( t, rootTokenType, new VisitTreeWizardContextVisitor( this, visitor, labels, tpattern ) );
  391. }
  392. /** <summary>
  393. * Given a pattern like (ASSIGN %lhs:ID %rhs:.) with optional labels
  394. * on the various nodes and '.' (dot) as the node/subtree wildcard,
  395. * return true if the pattern matches and fill the labels Map with
  396. * the labels pointing at the appropriate nodes. Return false if
  397. * the pattern is malformed or the tree does not match.
  398. * </summary>
  399. *
  400. * <remarks>
  401. * If a node specifies a text arg in pattern, then that must match
  402. * for that node in t.
  403. *
  404. * TODO: what's a better way to indicate bad pattern? Exceptions are a hassle
  405. * </remarks>
  406. */
  407. public bool Parse( object t, string pattern, IDictionary<string, object> labels )
  408. {
  409. TreePatternLexer tokenizer = new TreePatternLexer( pattern );
  410. TreePatternParser parser =
  411. new TreePatternParser( tokenizer, this, new TreePatternTreeAdaptor() );
  412. TreePattern tpattern = (TreePattern)parser.Pattern();
  413. /*
  414. System.out.println("t="+((Tree)t).toStringTree());
  415. System.out.println("scant="+tpattern.toStringTree());
  416. */
  417. bool matched = ParseCore( t, tpattern, labels );
  418. return matched;
  419. }
  420. public bool Parse( object t, string pattern )
  421. {
  422. return Parse( t, pattern, null );
  423. }
  424. /** <summary>
  425. * Do the work for parse. Check to see if the t2 pattern fits the
  426. * structure and token types in t1. Check text if the pattern has
  427. * text arguments on nodes. Fill labels map with pointers to nodes
  428. * in tree matched against nodes in pattern with labels.
  429. * </summary>
  430. */
  431. protected virtual bool ParseCore( object t1, TreePattern tpattern, IDictionary<string, object> labels )
  432. {
  433. // make sure both are non-null
  434. if ( t1 == null || tpattern == null )
  435. {
  436. return false;
  437. }
  438. // check roots (wildcard matches anything)
  439. if ( tpattern.GetType() != typeof( WildcardTreePattern ) )
  440. {
  441. if ( adaptor.GetType( t1 ) != tpattern.Type )
  442. {
  443. return false;
  444. }
  445. // if pattern has text, check node text
  446. if ( tpattern.hasTextArg && !adaptor.GetText( t1 ).Equals( tpattern.Text ) )
  447. {
  448. return false;
  449. }
  450. }
  451. if ( tpattern.label != null && labels != null )
  452. {
  453. // map label in pattern to node in t1
  454. labels[tpattern.label] = t1;
  455. }
  456. // check children
  457. int n1 = adaptor.GetChildCount( t1 );
  458. int n2 = tpattern.ChildCount;
  459. if ( n1 != n2 )
  460. {
  461. return false;
  462. }
  463. for ( int i = 0; i < n1; i++ )
  464. {
  465. object child1 = adaptor.GetChild( t1, i );
  466. TreePattern child2 = (TreePattern)tpattern.GetChild( i );
  467. if ( !ParseCore( child1, child2, labels ) )
  468. {
  469. return false;
  470. }
  471. }
  472. return true;
  473. }
  474. /** <summary>
  475. * Create a tree or node from the indicated tree pattern that closely
  476. * follows ANTLR tree grammar tree element syntax:
  477. *
  478. * (root child1 ... child2).
  479. * </summary>
  480. *
  481. * <remarks>
  482. * You can also just pass in a node: ID
  483. *
  484. * Any node can have a text argument: ID[foo]
  485. * (notice there are no quotes around foo--it's clear it's a string).
  486. *
  487. * nil is a special name meaning "give me a nil node". Useful for
  488. * making lists: (nil A B C) is a list of A B C.
  489. * </remarks>
  490. */
  491. public virtual object Create( string pattern )
  492. {
  493. TreePatternLexer tokenizer = new TreePatternLexer( pattern );
  494. TreePatternParser parser = new TreePatternParser( tokenizer, this, adaptor );
  495. object t = parser.Pattern();
  496. return t;
  497. }
  498. /** <summary>
  499. * Compare t1 and t2; return true if token types/text, structure match exactly.
  500. * The trees are examined in their entirety so that (A B) does not match
  501. * (A B C) nor (A (B C)).
  502. * </summary>
  503. *
  504. * <remarks>
  505. * TODO: allow them to pass in a comparator
  506. * TODO: have a version that is nonstatic so it can use instance adaptor
  507. *
  508. * I cannot rely on the tree node's equals() implementation as I make
  509. * no constraints at all on the node types nor interface etc...
  510. * </remarks>
  511. */
  512. public static bool Equals( object t1, object t2, ITreeAdaptor adaptor )
  513. {
  514. return EqualsCore( t1, t2, adaptor );
  515. }
  516. /** <summary>
  517. * Compare type, structure, and text of two trees, assuming adaptor in
  518. * this instance of a TreeWizard.
  519. * </summary>
  520. */
  521. public new bool Equals( object t1, object t2 )
  522. {
  523. return EqualsCore( t1, t2, adaptor );
  524. }
  525. protected static bool EqualsCore( object t1, object t2, ITreeAdaptor adaptor )
  526. {
  527. // make sure both are non-null
  528. if ( t1 == null || t2 == null )
  529. {
  530. return false;
  531. }
  532. // check roots
  533. if ( adaptor.GetType( t1 ) != adaptor.GetType( t2 ) )
  534. {
  535. return false;
  536. }
  537. if ( !adaptor.GetText( t1 ).Equals( adaptor.GetText( t2 ) ) )
  538. {
  539. return false;
  540. }
  541. // check children
  542. int n1 = adaptor.GetChildCount( t1 );
  543. int n2 = adaptor.GetChildCount( t2 );
  544. if ( n1 != n2 )
  545. {
  546. return false;
  547. }
  548. for ( int i = 0; i < n1; i++ )
  549. {
  550. object child1 = adaptor.GetChild( t1, i );
  551. object child2 = adaptor.GetChild( t2, i );
  552. if ( !EqualsCore( child1, child2, adaptor ) )
  553. {
  554. return false;
  555. }
  556. }
  557. return true;
  558. }
  559. #if BUILD_INDEXES
  560. // TODO: next stuff taken from CommonTreeNodeStream
  561. /** <summary>
  562. * Given a node, add this to the reverse index tokenTypeToStreamIndexesMap.
  563. * You can override this method to alter how indexing occurs. The
  564. * default is to create a
  565. *
  566. * Map&lt;Integer token type,ArrayList&lt;Integer stream index&gt;&gt;
  567. * </summary>
  568. *
  569. * <remarks>
  570. * This data structure allows you to find all nodes with type INT in order.
  571. *
  572. * If you really need to find a node of type, say, FUNC quickly then perhaps
  573. *
  574. * Map&lt;Integertoken type,Map&lt;Object tree node,Integer stream index&gt;&gt;
  575. *
  576. * would be better for you. The interior maps map a tree node to
  577. * the index so you don't have to search linearly for a specific node.
  578. *
  579. * If you change this method, you will likely need to change
  580. * getNodeIndex(), which extracts information.
  581. * </remarks>
  582. */
  583. protected void fillReverseIndex( object node, int streamIndex )
  584. {
  585. //System.out.println("revIndex "+node+"@"+streamIndex);
  586. if ( tokenTypesToReverseIndex == null )
  587. {
  588. return; // no indexing if this is empty (nothing of interest)
  589. }
  590. if ( tokenTypeToStreamIndexesMap == null )
  591. {
  592. tokenTypeToStreamIndexesMap = new Dictionary<int, IList<int>>(); // first indexing op
  593. }
  594. int tokenType = adaptor.getType( node );
  595. if ( !( tokenTypesToReverseIndex == INDEX_ALL ||
  596. tokenTypesToReverseIndex.Contains( tokenType ) ) )
  597. {
  598. return; // tokenType not of interest
  599. }
  600. IList<int> indexes;
  601. if ( !tokenTypeToStreamIndexesMap.TryGetValue( tokenType, out indexes ) || indexes == null )
  602. {
  603. indexes = new List<int>(); // no list yet for this token type
  604. indexes.Add( streamIndex ); // not there yet, add
  605. tokenTypeToStreamIndexesMap[tokenType] = indexes;
  606. }
  607. else
  608. {
  609. if ( !indexes.Contains( streamIndex ) )
  610. {
  611. indexes.Add( streamIndex ); // not there yet, add
  612. }
  613. }
  614. }
  615. /** <summary>
  616. * Track the indicated token type in the reverse index. Call this
  617. * repeatedly for each type or use variant with Set argument to
  618. * set all at once.
  619. * </summary>
  620. *
  621. * <param name="tokenType" />
  622. */
  623. public void reverseIndex( int tokenType )
  624. {
  625. if ( tokenTypesToReverseIndex == null )
  626. {
  627. tokenTypesToReverseIndex = new HashSet<int>();
  628. }
  629. else if ( tokenTypesToReverseIndex == INDEX_ALL )
  630. {
  631. return;
  632. }
  633. tokenTypesToReverseIndex.add( tokenType );
  634. }
  635. /** <summary>
  636. * Track the indicated token types in the reverse index. Set
  637. * to INDEX_ALL to track all token types.
  638. * </summary>
  639. */
  640. public void reverseIndex( HashSet<int> tokenTypes )
  641. {
  642. tokenTypesToReverseIndex = tokenTypes;
  643. }
  644. /** <summary>
  645. * Given a node pointer, return its index into the node stream.
  646. * This is not its Token stream index. If there is no reverse map
  647. * from node to stream index or the map does not contain entries
  648. * for node's token type, a linear search of entire stream is used.
  649. * </summary>
  650. *
  651. * <remarks>
  652. * Return -1 if exact node pointer not in stream.
  653. * </remarks>
  654. */
  655. public int getNodeIndex( object node )
  656. {
  657. //System.out.println("get "+node);
  658. if ( tokenTypeToStreamIndexesMap == null )
  659. {
  660. return getNodeIndexLinearly( node );
  661. }
  662. int tokenType = adaptor.getType( node );
  663. IList<int> indexes;
  664. if ( !tokenTypeToStreamIndexesMap.TryGetValue( tokenType, out indexes ) || indexes == null )
  665. {
  666. //System.out.println("found linearly; stream index = "+getNodeIndexLinearly(node));
  667. return getNodeIndexLinearly( node );
  668. }
  669. for ( int i = 0; i < indexes.size(); i++ )
  670. {
  671. int streamIndex = indexes[i];
  672. object n = get( streamIndex );
  673. if ( n == node )
  674. {
  675. //System.out.println("found in index; stream index = "+streamIndexI);
  676. return streamIndex; // found it!
  677. }
  678. }
  679. return -1;
  680. }
  681. #endif
  682. }
  683. }