1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver/** A generic list of elements tracked in an alternative to be used in 2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * a -> rewrite rule. We need to subclass to fill in the next() method, 3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * which returns either an AST node wrapped around a token payload or 4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * an existing subtree. 5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Once you start next()ing, do not try to add more elements. It will 7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * break the cursor tracking I believe. 8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * @see org.antlr.runtime.tree.RewriteRuleSubtreeStream 10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * @see org.antlr.runtime.tree.RewriteRuleTokenStream 11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * TODO: add mechanism to detect/puke on modification after reading from stream 13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverorg.antlr.runtime.tree.RewriteRuleElementStream = function(adaptor, elementDescription, el) { 15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** Cursor 0..n-1. If singleElement!=null, cursor is 0 until you next(), 16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * which bumps it to 1 meaning no more elements. 17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.cursor = 0; 19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** Once a node / subtree has been used in a stream, it must be dup'd 21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * from then on. Streams are reset after subrules so that the streams 22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * can be reused in future subrules. So, reset must set a dirty bit. 23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * If dirty, then next() always returns a dup. 24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * I wanted to use "naughty bit" here, but couldn't think of a way 26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * to use "naughty". 27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.dirty = false; 29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.elementDescription = elementDescription; 31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.adaptor = adaptor; 32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (el) { 33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (org.antlr.lang.isArray(el)) { 34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.singleElement = null; 35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.elements = el; 36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } else { 37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.add(el); 38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}; 41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverorg.antlr.runtime.tree.RewriteRuleElementStream.prototype = { 43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** Reset the condition of this stream so that it appears we have 44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * not consumed any of its elements. Elements themselves are untouched. 45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Once we reset the stream, any future use will need duplicates. Set 46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * the dirty bit. 47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver reset: function() { 49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.cursor = 0; 50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.dirty = true; 51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver }, 52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver add: function(el) { 54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( !org.antlr.lang.isValue(el) ) { 55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return; 56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( this.elements ) { // if in list, just add 58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.elements.push(el); 59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return; 60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( !org.antlr.lang.isValue(this.singleElement) ) { // no elements yet, track w/o list 62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.singleElement = el; 63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return; 64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // adding 2nd element, move to list 66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.elements = []; 67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.elements.push(this.singleElement); 68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.singleElement = null; 69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.elements.push(el); 70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver }, 71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** Return the next element in the stream. If out of elements, throw 73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * an exception unless size()==1. If size is 1, then return elements[0]. 74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Return a duplicate node/subtree if stream is out of elements and 75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * size==1. If we've already used the element, dup (dirty bit set). 76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver nextTree: function() { 78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var n = this.size(), 79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver el; 80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( this.dirty || (this.cursor>=n && n==1) ) { 81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // if out of elements and size is 1, dup 82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver el = this._next(); 83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return this.dup(el); 84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // test size above then fetch 86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver el = this._next(); 87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return el; 88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver }, 89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** do the work of getting the next element, making sure that it's 91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * a tree node or subtree. Deal with the optimization of single- 92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * element list versus list of size > 1. Throw an exception 93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * if the stream is empty or we're out of elements and size>1. 94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * protected so you can override in a subclass if necessary. 95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver _next: function() { 97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var n = this.size(); 98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (n===0) { 99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver throw new org.antlr.runtime.tree.RewriteEmptyStreamException(this.elementDescription); 100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( this.cursor>= n) { // out of elements? 102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( n===1 ) { // if size is 1, it's ok; return and we'll dup 103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return this.toTree(this.singleElement); 104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // out of elements and size was not 1, so we can't dup 106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver throw new org.antlr.runtime.tree.RewriteCardinalityException(this.elementDescription); 107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // we have elements 109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( org.antlr.lang.isValue(this.singleElement) ) { 110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.cursor++; // move cursor even for single element list 111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return this.toTree(this.singleElement); 112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // must have more than one in list, pull from elements 114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var o = this.toTree(this.elements[this.cursor]); 115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.cursor++; 116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return o; 117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver }, 118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** Ensure stream emits trees; tokens must be converted to AST nodes. 120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * AST nodes can be passed through unmolested. 121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver toTree: function(el) { 123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (el && el.getTree) { 124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return el.getTree(); 125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return el; 127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver }, 128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver hasNext: function() { 130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return (org.antlr.lang.isValue(this.singleElement) && this.cursor < 1) || 131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver (this.elements && this.cursor < this.elements.length); 132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver }, 133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver size: function() { 135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var n = 0; 136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( org.antlr.lang.isValue(this.singleElement) ) { 137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver n = 1; 138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( this.elements ) { 140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return this.elements.length; 141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return n; 143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver }, 144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver getDescription: function() { 146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return this.elementDescription; 147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}; 149