15 public errordomain TokenStreamError {
18 public class TokenStream : Object
21 protected Gee.ArrayList<Token> tokens;
22 public int cursor; // where are we in the stream.
25 public TokenStream(Gee.ArrayList<Token> tokens) {
31 public Gee.ArrayList<Token> toArray()
37 public void rewind() {
44 public Token? look (int n, bool considerWhitespace) // depricated... causes all sorts of problems...
48 if (considerWhitespace == true) {
50 if (this.cursor+n < 0 || this.cursor+n > (this.tokens.size -1)) {
51 return new Token("", "VOID", "START_OF_STREAM");
53 return this.tokens.get(this.cursor+n);
62 return new Token("", "VOID", "START_OF_STREAM");
64 if (i >= this.tokens.size) {
65 return new Token("", "VOID", "END_OF_STREAM");
68 if (i != this.cursor && this.tokens.get(i).is("WHIT")) {
69 i += (n < 0) ? -1 : 1;
74 return this.tokens.get(i);
77 i += (n < 0) ? -1 : 1;
80 // return new Token("", "VOID", "STREAM_ERROR"); // because null isn't an object and caller always expects an object
83 // look through token stream, including white space...
84 public Token? lookAny (int n)
88 if (considerWhitespace == true) {
90 if (this.cursor+n < 0 || this.cursor+n > (this.tokens.size -1)) {
91 return new Token("", "VOID", "START_OF_STREAM");
93 return this.tokens.get(this.cursor+n);
102 return new Token("", "VOID", "START_OF_STREAM");
104 if (i >= this.tokens.size) {
105 return new Token("", "VOID", "END_OF_STREAM");
108 if (i != this.cursor && this.tokens.get(i).is("WHIT")) {
109 i += (n < 0) ? -1 : 1;
114 return this.tokens.get(i);
117 i += (n < 0) ? -1 : 1;
120 // return new Token("", "VOID", "STREAM_ERROR"); // because null isn't an object and caller always expects an object
126 public int lookFor (string data)
128 // non tree version..
129 var i = this.cursor < 0 ? 0 : this.cursor ;
132 if (i >= this.tokens.size) {
135 if (this.tokens.get(i).data == data) {
141 // should not get here!
148 * look ahead (or back) x number of tokens (which are not comment or whitespace)
151 public Token lookTok (int n) {
167 return new Token("", "VOID", "END_OF_STREAM");
169 if (i >= this.tokens.size) {
170 return new Token("", "VOID", "END_OF_STREAM");
173 if (i != this.cursor && ( this.tokens.get(i).is("WHIT") || this.tokens.get(i).is("COMM"))) {
174 i += (n < 0) ? -1 : 1;
179 return this.tokens.get(i);
182 i += (n < 0) ? -1 : 1;
184 // should never get here..
185 // return new Token("", "VOID", "END_OF_STREAM");; // because null isn't an object and caller always expects an object;
190 * @return {Token|null}
191 * next token (with white space)
195 public Token? next() {
198 //if (typeof howMany == "undefined") howMany = 1;
199 // if (howMany < 1) { return null; }
201 if (this.cursor+1 >= this.tokens.size) {
205 return this.tokens.get(this.cursor);
209 public Gee.ArrayList<Token>? nextM(int howMany) throws TokenStreamError {
211 //if (typeof howMany == "undefined") howMany = 1;
213 throw new TokenStreamError.ArgumentError("nextM called with wrong number : %d", howMany);
215 var got = new Gee.ArrayList<Token>();
217 for (var i = 1; i <= howMany; i++) {
218 if (this.cursor+i >= this.tokens.size) {
221 got.add(this.tokens.get(this.cursor+i));
223 this.cursor += howMany;
231 // what about comments after 'function'...
233 public Token? nextTok() {
234 return this.nextNonSpace();
237 public Token? nextNonSpace ()
241 var tok = this.next();
245 if (tok.is("WHIT") || tok.is("COMM")) {
254 * -- returns all the tokens betweeen and including stop token eg.. from {... to }
255 * @param start {String} token name or data (eg. '{'
256 * @param stop {String} (Optional) token name or data (eg. '}'
258 public Gee.ArrayList<Token> balance (string start, string in_stop = "") throws TokenStreamError
261 // accepts names or "{" etc..
263 start = Lang.punc(start) == null ? start : Lang.punc(start);
266 var newstop = Lang.matching(start);
270 throw new TokenStreamError.ArgumentError("balance called with invalid start/stop : %s",start);
272 debug("START=%s, STOP=%s \n", start,stop);
274 var got = new Gee.ArrayList<Token>();
276 //Seed.print("START:" + start);
277 //Seed.print("STOP:" + stop);
280 while (null != (token = this.look(1,false))) {
281 debug("BALANCE: %d %s " , this.cursor, token.asString());
282 if (token.is(start)) {
283 // Seed.print("balance: START : " + depth + " " + token.data);
292 if (token.is(stop)) {
295 print("balance (%d): STOP: %s\n" , depth , token.data);
297 this.next(); // shift cursor to eat closer...
298 print("returning got %d\n", got.size);
303 if (null == this.next()) {
307 return new Gee.ArrayList<Token>();
310 public Token? getMatchingToken(string start, string stop)
313 var cursor = this.cursor;
315 if (start.length < 1) {
316 var ns = Lang.matching(stop);
320 if (stop.length < 1) {
321 var ns = Lang.matching(start);
326 while (null != (token = this.tokens[cursor])) {
327 if (token.is(start)) {
331 if (token.is(stop) && cursor != 0) {
334 return this.tokens[cursor];
342 public Gee.ArrayList<Token> insertAhead(Token token)
344 this.tokens.splice(this.cursor+1, 0, token); // fixme...
348 public Gee.ArrayList<Token> remaining() {
349 var ret = new Gee.ArrayList<Token>();
351 var tok = this.look(1,true);
352 if (tok.is("VOID")) {
355 var nt = this.next();
363 public void printRange(int start, int end) {
365 for(var i = start; i < end +1; i++) {
366 print(this.tokens.get(i).asString());
371 arrayToString : function(ar) {
372 console.log(typeof(ar));
374 ar.forEach(function(e) {
380 public void dump(int start, int end)
382 start = int.max(start , 0);
383 end = int.min(end, this.tokens.size);
385 for (var i =start;i < end; i++) {
387 outs += (this.tokens[i].outData == "") ? this.tokens[i].data : this.tokens[i].outData;
392 public void dumpAll(string indent)
394 for (var i = 0;i < this.tokens.size; i++) {
396 this.tokens[i].dump("");
400 public void dumpAllFlat()
402 for (var i = 0;i < this.tokens.size; i++) {
404 print("%d: %s\n", i, this.tokens[i].asString());