JSDOC/TokenStream.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 < 0) {
117                         return  new Token("", "VOID", "END_OF_STREAM");
118                     }
119                     
120                 }
121                 else if (i > this.tokens.length)  {
122                     return  new Token("", "VOID", "END_OF_STREAM");
123                 }
124
125                 if (i != this.cursor && (this.tokens[i] === undefined || this.tokens[i].is("WHIT") || this.tokens[i].is("COMM"))) {
126                     if (n < 0) i--; else i++;
127                     continue;
128                 }
129                 
130                 if (count == Math.abs(n)) {
131                     return this.tokens[i];
132                 }
133                 count++;
134                 (n < 0)? i-- : i++;
135             }
136         // should never get here..
137             return false; // because null isn't an object and caller always expects an object;
138             
139         },
140
141         /**
142          *  @return {Token|null}
143          */
144             
145            
146         next : function(/**Number*/howMany) {
147             if (typeof howMany == "undefined") howMany = 1;
148             if (howMany < 1) return null;
149             var got = [];
150
151             for (var i = 1; i <= howMany; i++) {
152                 if (this.cursor+i >= this.tokens.length) {
153                     return null;
154                 }
155                 got.push(this.tokens[this.cursor+i]);
156             }
157             this.cursor += howMany;
158
159             if (howMany == 1) {
160                 return got[0];
161             }
162             else return got;
163         },
164         // what about comments after 'function'...
165         // is this used ???
166         nextTok  : function() {
167             return this.nextNonSpace();
168         },
169         nextNonSpace : function ()
170         {
171             
172             while (true) {
173                 tok = this.next(1);
174                 if (!tok) {
175                     return false;
176                 }
177                 if (tok.is('WHIT') ||  tok.is('COMM')) {
178                     continue;
179                 }
180                 return tok;
181             }
182         },
183         /**
184          *    @type JSDOC.Token[]
185          * @param start {String}  token name or data (eg. '{'
186          * @param stop {String} (Optional) token name or data (eg. '}'
187          */
188         balance : function(/**String*/start, /**String*/stop) {
189             
190             
191             start = typeof(Lang.punc(start)) == 'undefined' ? start : Lang.punc(start);
192             
193             if (!stop) stop = Lang.matching(start);
194             
195             var depth = 0;
196             var got = [];
197             var started = false;
198             //Seed.print("START:" + start);
199             //Seed.print("STOP:" + stop);
200             while ((token = this.look())) {
201                 if (token.is(start)) {
202               //      Seed.print("balance: START : " + depth + " " + token.data);
203                     depth++;
204                     started = true;
205                 }
206                 
207                 if (started) {
208                     got.push(token);
209                 }
210                 
211                 if (token.is(stop)) {
212                     depth--;
213                 //    Seed.print("balance: STOP: "  + depth + " " + token.data);
214                     if (depth < 1) return got;
215                 }
216                 if (!this.next()) break;
217             }
218         },
219
220         getMatchingToken : function(/**String*/start, /**String*/stop) {
221             var depth = 0;
222             var cursor = this.cursor;
223             
224             if (!start) {
225                 start = Lang.matching(stop);
226                 depth = 1;
227             }
228             if (!stop) stop = Lang.matching(start);
229             
230             while ((token = this.tokens[cursor])) {
231                 if (token.is(start)) {
232                     depth++;
233                 }
234                 
235                 if (token.is(stop) && cursor) {
236                     depth--;
237                     if (depth == 0) return this.tokens[cursor];
238                 }
239                 cursor++;
240             }
241         },
242
243         insertAhead : function(/**JSDOC.Token*/token) {
244             this.tokens.splice(this.cursor+1, 0, token);
245         },
246          
247         remaining : function() {
248             var ret = [];
249             while (true) {
250                 var tok = this.look(1,true);
251                 if (!tok || !tok.is || tok.is('VOID')) {
252                     return ret;
253                 }
254                 ret.push(this.next(1));
255             }
256         },
257          
258
259         arrayToString : function(ar) {
260             console.log(typeof(ar));
261             var ret = [];
262             ar.forEach(function(e) {
263                 ret.push(e.data);
264             })
265             return ret.join('');
266         },
267         dump: function(start, end)
268         {
269             start = Math.max(start || 0, 0);
270             end = Math.min(end || this.tokens.length, this.tokens.length);
271             var out='';
272             for (var i =start;i < end; i++) {
273                 
274                 out += (this.tokens[i].outData == false) ? this.tokens[i].data : this.tokens[i].outData;
275             };
276             print(out);
277         }
278 });
279