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