console.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          */
142             
143            
144         next : function(/**Number*/howMany) {
145             if (typeof howMany == "undefined") howMany = 1;
146             if (howMany < 1) return null;
147             var got = [];
148
149             for (var i = 1; i <= howMany; i++) {
150                 if (this.cursor+i >= this.tokens.length) {
151                     return null;
152                 }
153                 got.push(this.tokens[this.cursor+i]);
154             }
155             this.cursor += howMany;
156
157             if (howMany == 1) {
158                 return got[0];
159             }
160             else return got;
161         },
162         // what about comments after 'function'...
163         // is this used ???
164         nextTok  : function() {
165             return this.nextNonSpace();
166         },
167         nextNonSpace : function ()
168         {
169             
170             while (true) {
171                 tok = this.next(1);
172                 if (!tok) {
173                     return false;
174                 }
175                 if (tok.is('WHIT') ||  tok.is('COMM')) {
176                     continue;
177                 }
178                 return tok;
179             }
180         },
181         /**
182          *    @type JSDOC.Token[]
183          * @param start {String}  token name or data (eg. '{'
184          * @param stop {String} (Optional) token name or data (eg. '}'
185          */
186         balance : function(/**String*/start, /**String*/stop) {
187             
188             start = typeof(Lang.matching(start)) == 'undefined' ? Lang.punc(start) : start;
189             
190             if (!stop) stop = Lang.matching(start);
191             
192             var depth = 0;
193             var got = [];
194             var started = false;
195             //Seed.print("STOP:" + stop);
196             while ((token = this.look())) {
197                 if (token.is(start)) {
198                     depth++;
199                     started = true;
200                 }
201                 
202                 if (started) {
203                     got.push(token);
204                 }
205                 
206                 if (token.is(stop)) {
207                     depth--;
208                     if (depth == 0) return got;
209                 }
210                 if (!this.next()) break;
211             }
212         },
213
214         getMatchingToken : function(/**String*/start, /**String*/stop) {
215             var depth = 0;
216             var cursor = this.cursor;
217             
218             if (!start) {
219                 start = Lang.matching(stop);
220                 depth = 1;
221             }
222             if (!stop) stop = Lang.matching(start);
223             
224             while ((token = this.tokens[cursor])) {
225                 if (token.is(start)) {
226                     depth++;
227                 }
228                 
229                 if (token.is(stop) && cursor) {
230                     depth--;
231                     if (depth == 0) return this.tokens[cursor];
232                 }
233                 cursor++;
234             }
235         },
236
237         insertAhead : function(/**JSDOC.Token*/token) {
238             this.tokens.splice(this.cursor+1, 0, token);
239         },
240          
241         remaining : function() {
242             var ret = [];
243             while (true) {
244                 var tok = this.look(1,true);
245                 if (!tok || !tok.is || tok.is('VOID')) {
246                     return ret;
247                 }
248                 ret.push(this.next(1));
249             }
250         },
251          
252
253         arrayToString : function(ar) {
254             console.log(typeof(ar));
255             var ret = [];
256             ar.forEach(function(e) {
257                 ret.push(e.data);
258             })
259             return ret.join('');
260         },
261         dump: function()
262         {
263             this.tokens.forEach(function(t) {
264                 print(t.toString());
265             });
266         }
267 });
268