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