PageRenderTime 55ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/runtime/Java/src/main/java/org/antlr/runtime/tree/RewriteRuleElementStream.java

https://bitbucket.org/jwalton/antlr3
Java | 211 lines | 101 code | 18 blank | 92 comment | 17 complexity | b97e9f22a035503f0b0ec1b8d790003c MD5 | raw file
  1. /*
  2. [The "BSD license"]
  3. Copyright (c) 2005-2009 Terence Parr
  4. All rights reserved.
  5. Redistribution and use in source and binary forms, with or without
  6. modification, are permitted provided that the following conditions
  7. are met:
  8. 1. Redistributions of source code must retain the above copyright
  9. notice, this list of conditions and the following disclaimer.
  10. 2. Redistributions in binary form must reproduce the above copyright
  11. notice, this list of conditions and the following disclaimer in the
  12. documentation and/or other materials provided with the distribution.
  13. 3. The name of the author may not be used to endorse or promote products
  14. derived from this software without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17. OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  19. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24. THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. package org.antlr.runtime.tree;
  27. import java.util.ArrayList;
  28. import java.util.List;
  29. /** A generic list of elements tracked in an alternative to be used in
  30. * a -> rewrite rule. We need to subclass to fill in the next() method,
  31. * which returns either an AST node wrapped around a token payload or
  32. * an existing subtree.
  33. *
  34. * Once you start next()ing, do not try to add more elements. It will
  35. * break the cursor tracking I believe.
  36. *
  37. * @see org.antlr.runtime.tree.RewriteRuleSubtreeStream
  38. * @see org.antlr.runtime.tree.RewriteRuleTokenStream
  39. *
  40. * TODO: add mechanism to detect/puke on modification after reading from stream
  41. */
  42. public abstract class RewriteRuleElementStream {
  43. /** Cursor 0..n-1. If singleElement!=null, cursor is 0 until you next(),
  44. * which bumps it to 1 meaning no more elements.
  45. */
  46. protected int cursor = 0;
  47. /** Track single elements w/o creating a list. Upon 2nd add, alloc list */
  48. protected Object singleElement;
  49. /** The list of tokens or subtrees we are tracking */
  50. protected List<Object> elements;
  51. /** Once a node / subtree has been used in a stream, it must be dup'd
  52. * from then on. Streams are reset after subrules so that the streams
  53. * can be reused in future subrules. So, reset must set a dirty bit.
  54. * If dirty, then next() always returns a dup.
  55. *
  56. * I wanted to use "naughty bit" here, but couldn't think of a way
  57. * to use "naughty".
  58. *
  59. * TODO: unused?
  60. */
  61. protected boolean dirty = false;
  62. /** The element or stream description; usually has name of the token or
  63. * rule reference that this list tracks. Can include rulename too, but
  64. * the exception would track that info.
  65. */
  66. protected String elementDescription;
  67. protected TreeAdaptor adaptor;
  68. public RewriteRuleElementStream(TreeAdaptor adaptor, String elementDescription) {
  69. this.elementDescription = elementDescription;
  70. this.adaptor = adaptor;
  71. }
  72. /** Create a stream with one element */
  73. @SuppressWarnings("OverridableMethodCallInConstructor")
  74. public RewriteRuleElementStream(TreeAdaptor adaptor,
  75. String elementDescription,
  76. Object oneElement)
  77. {
  78. this(adaptor, elementDescription);
  79. add(oneElement);
  80. }
  81. /** Create a stream, but feed off an existing list */
  82. public RewriteRuleElementStream(TreeAdaptor adaptor,
  83. String elementDescription,
  84. List<Object> elements)
  85. {
  86. this(adaptor, elementDescription);
  87. this.singleElement = null;
  88. this.elements = elements;
  89. }
  90. /** Reset the condition of this stream so that it appears we have
  91. * not consumed any of its elements. Elements themselves are untouched.
  92. * Once we reset the stream, any future use will need duplicates. Set
  93. * the dirty bit.
  94. */
  95. public void reset() {
  96. cursor = 0;
  97. dirty = true;
  98. }
  99. public void add(Object el) {
  100. //System.out.println("add '"+elementDescription+"' is "+el);
  101. if ( el==null ) {
  102. return;
  103. }
  104. if ( elements!=null ) { // if in list, just add
  105. elements.add(el);
  106. return;
  107. }
  108. if ( singleElement == null ) { // no elements yet, track w/o list
  109. singleElement = el;
  110. return;
  111. }
  112. // adding 2nd element, move to list
  113. elements = new ArrayList<Object>(5);
  114. elements.add(singleElement);
  115. singleElement = null;
  116. elements.add(el);
  117. }
  118. /** Return the next element in the stream. If out of elements, throw
  119. * an exception unless size()==1. If size is 1, then return elements[0].
  120. * Return a duplicate node/subtree if stream is out of elements and
  121. * size==1. If we've already used the element, dup (dirty bit set).
  122. */
  123. public Object nextTree() {
  124. int n = size();
  125. if ( dirty || (cursor>=n && n==1) ) {
  126. // if out of elements and size is 1, dup
  127. Object el = _next();
  128. return dup(el);
  129. }
  130. // test size above then fetch
  131. Object el = _next();
  132. return el;
  133. }
  134. /** do the work of getting the next element, making sure that it's
  135. * a tree node or subtree. Deal with the optimization of single-
  136. * element list versus list of size > 1. Throw an exception
  137. * if the stream is empty or we're out of elements and size>1.
  138. * protected so you can override in a subclass if necessary.
  139. */
  140. protected Object _next() {
  141. int n = size();
  142. if ( n ==0 ) {
  143. throw new RewriteEmptyStreamException(elementDescription);
  144. }
  145. if ( cursor>= n) { // out of elements?
  146. if ( n ==1 ) { // if size is 1, it's ok; return and we'll dup
  147. return toTree(singleElement);
  148. }
  149. // out of elements and size was not 1, so we can't dup
  150. throw new RewriteCardinalityException(elementDescription);
  151. }
  152. // we have elements
  153. if ( singleElement!=null ) {
  154. cursor++; // move cursor even for single element list
  155. return toTree(singleElement);
  156. }
  157. // must have more than one in list, pull from elements
  158. Object o = toTree(elements.get(cursor));
  159. cursor++;
  160. return o;
  161. }
  162. /** When constructing trees, sometimes we need to dup a token or AST
  163. * subtree. Dup'ing a token means just creating another AST node
  164. * around it. For trees, you must call the adaptor.dupTree() unless
  165. * the element is for a tree root; then it must be a node dup.
  166. */
  167. protected abstract Object dup(Object el);
  168. /** Ensure stream emits trees; tokens must be converted to AST nodes.
  169. * AST nodes can be passed through unmolested.
  170. */
  171. protected Object toTree(Object el) {
  172. return el;
  173. }
  174. public boolean hasNext() {
  175. return (singleElement != null && cursor < 1) ||
  176. (elements!=null && cursor < elements.size());
  177. }
  178. public int size() {
  179. int n = 0;
  180. if ( singleElement != null ) {
  181. n = 1;
  182. }
  183. if ( elements!=null ) {
  184. return elements.size();
  185. }
  186. return n;
  187. }
  188. public String getDescription() {
  189. return elementDescription;
  190. }
  191. }