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