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