JSDOC/Walker2.js
[gnome.introspection-doc-generator] / JSDOC / TokenStream.js
1 //<script type="text/javscript">
2
3
4 XObject = imports.XObject.XObject;
5  
6
7
8 console = imports.console.console;
9 Token   = imports.Token.Token;
10 Lang    = imports.Lang.Lang;
11
12
13 /**
14  * @class TokenStream
15  * 
16  * BC notes:
17  * 
18  * nextT => nextTok
19  * lookT => lookTok
20  * 
21  */
22         
23  
24 TokenStream = XObject.define(
25
26     /**
27      * @constructor
28      * 
29      * 
30      */
31
32     function(tokens) {
33      
34         
35         this.tokens = (tokens || []);
36        // Seed.print(this.tokens.length);
37         this.rewind();
38     },
39     Object,
40     {
41         cursor : -1, // where are we in the stream.
42         
43         rewind : function() {
44             this.cursor = -1;
45         },
46
47         /**
48             @type JSDOC.Token
49         */
50         look : function(/**Number*/n, /**Boolean*/considerWhitespace) {
51             if (typeof n == "undefined") n = 0;
52
53             if (considerWhitespace == true) {
54                 if (this.cursor+n < 0 || this.cursor+n > (this.tokens.length -1)) {
55                     return new Token("", "VOID", "START_OF_STREAM");
56                 }
57                 return this.tokens[this.cursor+n];
58             }
59             else {
60                 var count = 0;
61                 var i = this.cursor;
62
63                 while (true) {
64                     if (i < 0) return new Token("", "VOID", "START_OF_STREAM");
65                     else if (i > this.tokens.length) return new Token("", "VOID", "END_OF_STREAM");
66
67                     if (i != this.cursor && (this.tokens[i] === undefined || this.tokens[i].is("WHIT"))) {
68                         if (n < 0) i--; else i++;
69                         continue;
70                     }
71                     
72                     if (count == Math.abs(n)) {
73                         return this.tokens[i];
74                     }
75                     count++;
76                     (n < 0)? i-- : i++;
77                 }
78
79                 return new Token("", "VOID", "STREAM_ERROR"); // because null isn't an object and caller always expects an object
80             }
81         },
82
83         lookFor : function (data)
84         {
85             // non tree version..
86             var i = this.cursor < 0 ? 0 : this.cursor ;
87             
88             while (true) {
89                 if (i >= this.tokens.length) return -1;
90                 if (this.tokens[i].data == data) {
91                     return i;
92                 }
93                 i++;
94                 
95             }
96             // should not get here!
97             return -1;
98
99         },
100
101
102         /**
103          * look ahead (or back) x number of tokens (which are not comment or whitespace)
104          * ?? used any more?
105          */
106         lookTok : function(/**Number*/n) {
107             if (typeof n == "undefined") n = 1;
108
109             
110             var count = 0;
111             var i = this.cursor;
112
113             while (true) {
114                // print(i);
115                 if (i < 0) {
116                     if (n > -1) {
117                         i = 0; continue;
118                     }
119                     return   new Token("", "VOID", "END_OF_STREAM");
120                 }
121                 else if (i > this.tokens.length) return  new Token("", "VOID", "END_OF_STREAM");
122
123                 if (i != this.cursor && (this.tokens[i] === undefined || this.tokens[i].is("WHIT") || this.tokens[i].is("COMM"))) {
124                     if (n < 0) i--; else i++;
125                     continue;
126                 }
127                 
128                 if (count == Math.abs(n)) {
129                     return this.tokens[i];
130                 }
131                 count++;
132                 (n < 0)? i-- : i++;
133             }
134         // should never get here..
135             return false; // because null isn't an object and caller always expects an object;
136             
137         },
138
139         /**
140          *  @return {Token|null}
141          * next token (with white space)
142          */
143             
144            
145         next : function(/**Number*/howMany) {
146             if (typeof howMany == "undefined") howMany = 1;
147             if (howMany < 1) return null;
148             var got = [];
149
150             for (var i = 1; i <= howMany; i++) {
151                 if (this.cursor+i >= this.tokens.length) {
152                     return null;
153                 }
154                 got.push(this.tokens[this.cursor+i]);
155             }
156             this.cursor += howMany;
157
158             if (howMany == 1) {
159                 return got[0];
160             }
161             else return got;
162         },
163         // what about comments after 'function'...
164         // is this used ???
165         nextTok  : function() {
166             return this.nextNonSpace();
167         },
168         nextNonSpace : function ()
169         {
170             
171             while (true) {
172                 tok = this.next(1);
173                 if (!tok) {
174                     return false;
175                 }
176                 if (tok.is('WHIT') ||  tok.is('COMM')) {
177                     continue;
178                 }
179                 return tok;
180             }
181         },
182         /**
183          *    @type JSDOC.Token[]
184          * @param start {String}  token name or data (eg. '{'
185          * @param stop {String} (Optional) token name or data (eg. '}'
186          */
187         balance : function(/**String*/start, /**String*/stop) {
188             
189             
190             start = typeof(Lang.punc(start)) == 'undefined' ? start : Lang.punc(start);
191             
192             if (!stop) stop = Lang.matching(start);
193             
194             var depth = 0;
195             var got = [];
196             var started = false;
197             //Seed.print("START:" + start);
198             //Seed.print("STOP:" + stop);
199             while ((token = this.look())) {
200                 if (token.is(start)) {
201               //      Seed.print("balance: START : " + depth + " " + token.data);
202                     depth++;
203                     started = true;
204                 }
205                 
206                 if (started) {
207                     got.push(token);
208                 }
209                 
210                 if (token.is(stop)) {
211                     depth--;
212                 //    Seed.print("balance: STOP: "  + depth + " " + token.data);
213                     if (depth < 1) return got;
214                 }
215                 if (!this.next()) break;
216             }
217         },
218
219         getMatchingToken : function(/**String*/start, /**String*/stop) {
220             var depth = 0;
221             var cursor = this.cursor;
222             
223             if (!start) {
224                 start = Lang.matching(stop);
225                 depth = 1;
226             }
227             if (!stop) stop = Lang.matching(start);
228             
229             while ((token = this.tokens[cursor])) {
230                 if (token.is(start)) {
231                     depth++;
232                 }
233                 
234                 if (token.is(stop) && cursor) {
235                     depth--;
236                     if (depth == 0) return this.tokens[cursor];
237                 }
238                 cursor++;
239             }
240         },
241
242         insertAhead : function(/**JSDOC.Token*/token) {
243             this.tokens.splice(this.cursor+1, 0, token);
244         },
245          
246         remaining : function() {
247             var ret = [];
248             while (true) {
249                 var tok = this.look(1,true);
250                 if (!tok || !tok.is || tok.is('VOID')) {
251                     return ret;
252                 }
253                 ret.push(this.next(1));
254             }
255         },
256          
257
258         arrayToString : function(ar) {
259             console.log(typeof(ar));
260             var ret = [];
261             ar.forEach(function(e) {
262                 ret.push(e.data);
263             })
264             return ret.join('');
265         },
266         dump: function(start, end)
267         {
268             start = Math.max(start || 0, 0);
269             end = Math.min(end || this.tokens.length, this.tokens.length);
270             var out='';
271             for (var i =start;i < end; i++) {
272                 
273                 out += (this.tokens[i].outData == false) ? this.tokens[i].data : this.tokens[i].outData;
274             };
275             print(out);
276         }
277 });
278